* ALL: final improvements to the decoders/packetizers api.
authorGildas Bazin <gbazin@videolan.org>
Sun, 16 Nov 2003 21:07:31 +0000 (21:07 +0000)
committerGildas Bazin <gbazin@videolan.org>
Sun, 16 Nov 2003 21:07:31 +0000 (21:07 +0000)
   (There are still a few decoders/packetizers left to be converted but this shouldn't take too long).
* ALL: small improvements to the encoders api.

55 files changed:
include/aout_internal.h
include/audio_output.h
include/input_ext-intf.h
include/ninput.h
include/vlc_block_helper.h
include/vlc_codec.h
include/vlc_common.h
include/vlc_video.h
modules/codec/a52.c
modules/codec/adpcm.c
modules/codec/araw.c
modules/codec/cinepak.c
modules/codec/dts.c
modules/codec/dv.c
modules/codec/dvbsub.c
modules/codec/faad.c
modules/codec/ffmpeg/audio.c
modules/codec/ffmpeg/encoder.c
modules/codec/ffmpeg/ffmpeg.c
modules/codec/ffmpeg/ffmpeg.h
modules/codec/ffmpeg/video.c
modules/codec/flacdec.c
modules/codec/libmpeg2.c
modules/codec/lpcm.c
modules/codec/mpeg_audio.c
modules/codec/rawvideo.c
modules/codec/speex.c
modules/codec/spudec/spudec.c
modules/codec/subsdec.c
modules/codec/tarkin.c
modules/codec/theora.c
modules/codec/vorbis.c
modules/codec/xvid.c
modules/demux/a52sys.c
modules/demux/aac.c
modules/demux/asf/asf.c
modules/demux/au.c
modules/demux/avi/avi.c
modules/demux/livedotcom.cpp
modules/demux/mkv.cpp
modules/demux/mpeg/mpga.c
modules/demux/wav.c
modules/misc/dummy/Modules.am
modules/misc/dummy/decoder.c
modules/misc/dummy/dummy.c
modules/misc/dummy/dummy.h
modules/packetizer/copy.c
modules/packetizer/mpeg4audio.c
modules/stream_out/transcode.c
src/audio_output/common.c
src/audio_output/dec.c
src/input/input.c
src/input/input_dec.c
src/input/input_programs.c
src/libvlc.h

index 9f38dcb..81e5388 100644 (file)
@@ -2,7 +2,7 @@
  * aout_internal.h : internal defines for audio output
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: aout_internal.h,v 1.41 2003/10/27 21:54:10 gbazin Exp $
+ * $Id: aout_internal.h,v 1.42 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -97,7 +97,7 @@ struct aout_fifo_t
 /*****************************************************************************
  * aout_filter_t : audio output filter
  *****************************************************************************/
-typedef struct aout_filter_t
+struct aout_filter_t
 {
     VLC_COMMON_MEMBERS
 
@@ -113,7 +113,7 @@ typedef struct aout_filter_t
                                          struct aout_buffer_t * );
     vlc_bool_t              b_in_place;
     vlc_bool_t              b_continuity;
-} aout_filter_t;
+};
 
 /*****************************************************************************
  * aout_mixer_t : audio output mixer
@@ -255,20 +255,10 @@ int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
                     aout_buffer_t * p_buffer );
 
 /* From filters.c : */
-int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
-                                aout_filter_t ** pp_filters,
-                                int * pi_nb_filters,
-                                const audio_sample_format_t * p_input_format,
-                                const audio_sample_format_t * p_output_format );
-void aout_FiltersDestroyPipeline( aout_instance_t * p_aout,
-                                  aout_filter_t ** pp_filters,
-                                  int i_nb_filters );
-void aout_FiltersHintBuffers( aout_instance_t * p_aout,
-                              aout_filter_t ** pp_filters,
-                              int i_nb_filters, aout_alloc_t * p_first_alloc );
-void aout_FiltersPlay( aout_instance_t * p_aout,
-                       aout_filter_t ** pp_filters,
-                       int i_nb_filters, aout_buffer_t ** pp_input_buffer );
+VLC_EXPORT( int, aout_FiltersCreatePipeline, ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int * pi_nb_filters, const audio_sample_format_t * p_input_format, const audio_sample_format_t * p_output_format ) );
+VLC_EXPORT( void, aout_FiltersDestroyPipeline, ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters ) );
+VLC_EXPORT( void, aout_FiltersPlay, ( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_buffer_t ** pp_input_buffer ) );
+void aout_FiltersHintBuffers( aout_instance_t * p_aout, aout_filter_t ** pp_filters, int i_nb_filters, aout_alloc_t * p_first_alloc );
 
 /* From mixer.c : */
 int aout_MixerNew( aout_instance_t * p_aout );
index 2971b76..98820ea 100644 (file)
@@ -2,7 +2,7 @@
  * audio_output.h : audio output interface
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: audio_output.h,v 1.83 2003/10/08 21:01:07 gbazin Exp $
+ * $Id: audio_output.h,v 1.84 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
  *****************************************************************************
  * This structure defines a format for audio samples.
  *****************************************************************************/
-struct audio_sample_format_t
+struct audio_format_t
 {
     vlc_fourcc_t        i_format;
+
     unsigned int        i_rate;
+
     /* Describes the channels configuration of the samples (ie. number of
      * channels which are available in the buffer, and positions). */
     uint32_t            i_physical_channels;
+
     /* Describes from which original channels, before downmixing, the
      * buffer is derived. */
     uint32_t            i_original_channels;
+
     /* Optional - for A/52, SPDIF and DTS types : */
     /* Bytes used by one compressed frame, depends on bitrate. */
     unsigned int        i_bytes_per_frame;
+
     /* Number of sampleframes contained in one compressed frame. */
     unsigned int        i_frame_length;
     /* Please note that it may be completely arbitrary - buffers are not
@@ -48,6 +53,12 @@ struct audio_sample_format_t
      * just here for the division :
      * buffer_size = i_nb_samples * i_bytes_per_frame / i_frame_length
      */
+
+    /* FIXME ? (used by the codecs) */
+    int i_bitrate;
+    int i_channels;
+    int i_blockalign;
+    int i_bitspersample;
 };
 
 #define AOUT_FMTS_IDENTICAL( p_first, p_second ) (                          \
index 20e39fd..d07de40 100644 (file)
@@ -4,7 +4,7 @@
  * control the pace of reading.
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: input_ext-intf.h,v 1.97 2003/11/06 16:36:41 nitrox Exp $
+ * $Id: input_ext-intf.h,v 1.98 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -26,6 +26,8 @@
 #ifndef _VLC_INPUT_EXT_INTF_H
 #define _VLC_INPUT_EXT_INTF_H 1
 
+#include "ninput.h"
+
 /*
  * Communication input -> interface
  */
@@ -65,6 +67,7 @@ struct es_descriptor_t
     unsigned int            i_pes_real_size;   /* as indicated by the header */
 
     /* Decoder information */
+    es_format_t             fmt;
     decoder_fifo_t *        p_decoder_fifo;
     void *                  p_waveformatex;
     void *                  p_bitmapinfoheader;
index c9a13ca..e2b5b82 100644 (file)
@@ -2,7 +2,7 @@
  * ninput.h
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ninput.h,v 1.14 2003/11/13 17:59:34 gbazin Exp $
+ * $Id: ninput.h,v 1.15 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -24,6 +24,9 @@
 #ifndef _NINPUT_H
 #define _NINPUT_H 1
 
+#include "audio_output.h"
+#include "vlc_video.h"
+
 enum es_extra_type_e
 {
     ES_EXTRA_TYPE_UNKNOWN,
@@ -32,6 +35,12 @@ enum es_extra_type_e
     ES_EXTRA_TYPE_SUBHEADER
 };
 
+typedef struct subs_format_t
+{
+    char *psz_encoding;
+
+} subs_format_t;
+
 typedef struct
 {
     int             i_cat;
@@ -47,31 +56,16 @@ typedef struct
     char            *psz_language;
     char            *psz_description;
 
-    struct
-    {
-        int i_samplerate;
-        int i_channels;
-        int i_bitrate;
-        int i_blockalign;
-        int i_bitspersample;
-    } audio;
-
-    struct
-    {
-        int i_width;
-        int i_height;
-        int i_display_width;
-        int i_display_height;
-    } video;
-
-    struct
-    {
-        char *psz_encoding;
-    } subs;
+    audio_format_t audio;
+    video_format_t video;
+    subs_format_t  subs;
+
+    int     i_bitrate;
 
     int     i_extra_type;
     int     i_extra;
     void    *p_extra;
+
 } es_format_t;
 
 static inline void es_format_Init( es_format_t *fmt,
@@ -84,18 +78,9 @@ static inline void es_format_Init( es_format_t *fmt,
     fmt->psz_language           = NULL;
     fmt->psz_description        = NULL;
 
-    fmt->audio.i_samplerate     = 0;
-    fmt->audio.i_channels       = 0;
-    fmt->audio.i_bitrate        = 0;
-    fmt->audio.i_blockalign     = 0;
-    fmt->audio.i_bitspersample  = 0;
-
-    fmt->video.i_width          = 0;
-    fmt->video.i_height         = 0;
-    fmt->video.i_display_width  = 0;
-    fmt->video.i_display_height = 0;
-
-    fmt->subs.psz_encoding      = NULL;
+    memset( &fmt->audio, 0, sizeof(audio_format_t) );
+    memset( &fmt->video, 0, sizeof(video_format_t) );
+    memset( &fmt->subs, 0, sizeof(subs_format_t) );
 
     fmt->i_extra_type           = ES_EXTRA_TYPE_UNKNOWN;
     fmt->i_extra                = 0;
index 1e8676b..bb15502 100644 (file)
@@ -2,7 +2,7 @@
  * vlc_block_helper.h: Helper functions for data blocks management.
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: vlc_block_helper.h,v 1.4 2003/10/23 20:51:20 gbazin Exp $
+ * $Id: vlc_block_helper.h,v 1.5 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -29,26 +29,38 @@ typedef struct block_bytestream_t
     block_t             *p_chain;
     block_t             *p_block;
     int                 i_offset;
+
 } block_bytestream_t;
 
-#define block_BytestreamInit( a, b, c ) __block_BytestreamInit( VLC_OBJECT(a), b, c )
+#define block_BytestreamInit( a ) __block_BytestreamInit( VLC_OBJECT(a) )
 
 /*****************************************************************************
  * block_bytestream_t management
  *****************************************************************************/
-static inline block_bytestream_t __block_BytestreamInit( vlc_object_t *p_obj,
-                                           block_t *p_block, int i_offset )
+static inline block_bytestream_t __block_BytestreamInit( vlc_object_t *p_obj )
 {
     block_bytestream_t bytestream;
 
-    bytestream.i_offset = i_offset;
-    bytestream.p_block = p_block;
-    bytestream.p_chain = p_block;
+    bytestream.i_offset = 0;
+    bytestream.p_chain = bytestream.p_block = NULL;
 
     return bytestream;
 }
 
-static inline block_t *block_BytestreamFlush( block_bytestream_t *p_bytestream)
+static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
+{
+    while( p_bytestream->p_chain )
+    {
+        block_t *p_next;
+        p_next = p_bytestream->p_chain->p_next;
+        p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
+        p_bytestream->p_chain = p_next;
+    }
+    p_bytestream->i_offset = 0;
+    p_bytestream->p_chain = p_bytestream->p_block = NULL;
+}
+
+static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
 {
     while( p_bytestream->p_chain != p_bytestream->p_block )
     {
@@ -57,8 +69,54 @@ static inline block_t *block_BytestreamFlush( block_bytestream_t *p_bytestream)
         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
         p_bytestream->p_chain = p_next;
     }
+    while( p_bytestream->p_block &&
+           (p_bytestream->p_block->i_buffer - p_bytestream->i_offset) == 0 )
+    {
+        block_t *p_next;
+        p_next = p_bytestream->p_chain->p_next;
+        p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
+        p_bytestream->p_chain = p_bytestream->p_block = p_next;
+        p_bytestream->i_offset = 0;
+    }
+}
 
-    return p_bytestream->p_chain;
+static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
+                                         block_t *p_block )
+{
+    block_ChainAppend( &p_bytestream->p_chain, p_block );
+    if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
+}
+
+static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
+{
+    block_t *p_block;
+
+    block_BytestreamFlush( p_bytestream );
+
+    p_block = p_bytestream->p_block;
+    if( p_block == NULL )
+    {
+        return NULL;
+    }
+    else if( !p_block->p_next )
+    {
+        p_block->p_buffer += p_bytestream->i_offset;
+        p_block->i_buffer -= p_bytestream->i_offset;
+        p_bytestream->i_offset = 0;
+        p_bytestream->p_chain = p_bytestream->p_block = NULL;
+        return p_block;
+    }
+
+    while( p_block->p_next && p_block->p_next->p_next )
+        p_block = p_block->p_next;
+
+    {
+        block_t *p_block_old = p_block;
+        p_block = p_block->p_next;
+        p_block_old->p_next = NULL;
+    }
+
+    return p_block;
 }
 
 static inline int block_SkipByte( block_bytestream_t *p_bytestream )
@@ -151,6 +209,34 @@ static inline int block_GetByte( block_bytestream_t *p_bytestream,
     return VLC_EGENERIC;
 }
 
+static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
+                                   int i_data )
+{
+    block_t *p_block;
+    int i_offset, i_copy, i_size;
+
+    /* Check we have that much data */
+    i_offset = p_bytestream->i_offset;
+    i_size = i_data;
+    i_copy = 0;
+    for( p_block = p_bytestream->p_block;
+         p_block != NULL; p_block = p_block->p_next )
+    {
+        i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
+        i_size -= i_copy;
+        i_offset = 0;
+
+        if( !i_size ) break;
+    }
+
+    if( i_size )
+    {
+        /* Not enough data, bail out */
+        return VLC_EGENERIC;
+    }
+    return VLC_SUCCESS;
+}
+
 static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
                                    int i_data )
 {
index 5acb074..180538a 100644 (file)
@@ -2,7 +2,7 @@
  * vlc_codec.h: codec related structures
  *****************************************************************************
  * Copyright (C) 1999-2003 VideoLAN
- * $Id: vlc_codec.h,v 1.3 2003/11/05 18:59:01 gbazin Exp $
+ * $Id: vlc_codec.h,v 1.4 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
 #ifndef _VLC_CODEC_H
 #define _VLC_CODEC_H 1
 
+#include "ninput.h"
+
 /**
  * \file
  * This file defines the structure and types used by decoders and encoders
  */
 
+typedef struct decoder_owner_sys_t decoder_owner_sys_t;
+
 /**
  * \defgroup decoder Decoder
  *
@@ -43,15 +47,39 @@ struct decoder_t
     /* Module properties */
     module_t *          p_module;
     decoder_sys_t *     p_sys;
-    int                 ( * pf_init )  ( decoder_t * );
+
+    /* Deprecated */
     int                 ( * pf_decode )( decoder_t *, block_t * );
-    int                 ( * pf_end )   ( decoder_t * );
+    decoder_fifo_t *    p_fifo;
+    int                 ( * pf_run ) ( decoder_fifo_t * );
+    /* End deprecated */
 
-    /* Input properties */
-    decoder_fifo_t *    p_fifo;                /* stores the PES stream data */
+    picture_t *         ( * pf_decode_video )( decoder_t *, block_t ** );
+    aout_buffer_t *     ( * pf_decode_audio )( decoder_t *, block_t ** );
+    void                ( * pf_decode_sub)   ( decoder_t *, block_t ** );
+    block_t *           ( * pf_packetize )   ( decoder_t *, block_t ** );
 
-    /* Tmp field for old decoder api */
-    int                 ( * pf_run ) ( decoder_fifo_t * );
+    /* Input format ie from demuxer (XXX: a lot of field could be invalid) */
+    es_format_t         fmt_in;
+
+    /* Output format of decoder/packetizer */
+    es_format_t         fmt_out;
+
+    /*
+     * Buffers allocation
+     */
+
+    /* Audio output callbacks */
+    aout_buffer_t * ( * pf_aout_buffer_new) ( decoder_t *, int );
+    void            ( * pf_aout_buffer_del) ( decoder_t *, aout_buffer_t * );
+
+    /* Video output callbacks */
+    picture_t     * ( * pf_vout_buffer_new) ( decoder_t * );
+    void            ( * pf_vout_buffer_del) ( decoder_t *, picture_t * );
+
+
+    /* Private structure for the owner of the decoder */
+    decoder_owner_sys_t *p_owner;
 };
 
 /**
@@ -79,22 +107,12 @@ struct encoder_t
     block_t *           ( * pf_encode_audio )( encoder_t *, aout_buffer_t * );
 
     /* Properties of the input data fed to the encoder */
-    union {
-        audio_sample_format_t audio;
-        video_frame_format_t  video;
-    } format;
+    es_format_t         fmt_in;
 
     /* Properties of the output of the encoder */
-    vlc_fourcc_t i_fourcc;
-    int          i_bitrate;
-
-    int          i_extra_data;
-    uint8_t      *p_extra_data;
+    es_format_t         fmt_out;
 
     /* FIXME: move these to the ffmpeg encoder */
-    int i_frame_rate;
-    int i_frame_rate_base;
-    int i_aspect;
     int i_key_int;
     int i_b_frames;
     int i_vtolerance;
index 20398d0..1aed266 100644 (file)
@@ -3,7 +3,7 @@
  * Collection of useful common types and macros definitions
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vlc_common.h,v 1.85 2003/10/29 17:32:54 zorglub Exp $
+ * $Id: vlc_common.h,v 1.86 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@via.ecp.fr>
  *          Vincent Seguin <seguin@via.ecp.fr>
@@ -229,14 +229,17 @@ typedef struct aout_sys_t aout_sys_t;
 typedef struct aout_fifo_t aout_fifo_t;
 typedef struct aout_input_t aout_input_t;
 typedef struct aout_buffer_t aout_buffer_t;
-typedef struct audio_sample_format_t audio_sample_format_t;
+typedef struct audio_format_t audio_format_t;
+typedef audio_format_t audio_sample_format_t;
 typedef struct audio_date_t audio_date_t;
+typedef struct aout_filter_t aout_filter_t;
 
 /* Video */
 typedef struct vout_thread_t vout_thread_t;
 typedef struct vout_sys_t vout_sys_t;
 typedef struct chroma_sys_t chroma_sys_t;
-typedef struct video_frame_format_t video_frame_format_t;
+typedef struct video_format_t video_format_t;
+typedef video_format_t video_frame_format_t;
 typedef struct picture_t picture_t;
 typedef struct picture_sys_t picture_sys_t;
 typedef struct picture_heap_t picture_heap_t;
index 66b3564..70aedd2 100644 (file)
@@ -4,7 +4,7 @@
  * includes all common video types and constants.
  *****************************************************************************
  * Copyright (C) 1999, 2000 VideoLAN
- * $Id: vlc_video.h,v 1.5 2003/10/24 21:27:06 gbazin Exp $
+ * $Id: vlc_video.h,v 1.6 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  *
@@ -28,7 +28,7 @@
 /**
  * Description of a video frame
  */
-struct video_frame_format_t
+struct video_format_t
 {
     vlc_fourcc_t i_chroma;                               /**< picture chroma */
     unsigned int i_aspect;                                 /**< aspect ratio */
@@ -42,6 +42,8 @@ struct video_frame_format_t
 
     unsigned int i_bits_per_pixel;             /**< number of bits per pixel */
 
+    unsigned int i_frame_rate;                     /**< frame rate numerator */
+    unsigned int i_frame_rate_base;              /**< frame rate denominator */
 };
 
 /**
index 8ea4310..7f6b1f1 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * a52.c: A/52 basic parser
+ * a52.c: parse A/52 audio sync info and packetize the stream
  *****************************************************************************
  * Copyright (C) 2001-2002 VideoLAN
- * $Id: a52.c,v 1.28 2003/10/23 20:51:20 gbazin Exp $
+ * $Id: a52.c,v 1.29 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: St├ęphane Borel <stef@via.ecp.fr>
  *          Christophe Massiot <massiot@via.ecp.fr>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>                                              /* memcpy() */
-#include <fcntl.h>
 
 #include <vlc/vlc.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
-#include <vlc/aout.h>
-#include <vlc/sout.h>
 
 #include "vlc_block_helper.h"
 
@@ -52,33 +49,16 @@ struct decoder_sys_t
     /*
      * Input properties
      */
-    int        i_state;
+    int i_state;
 
-    block_t *p_chain;
     block_bytestream_t bytestream;
 
     /*
-     * Decoder output properties
-     */
-    aout_instance_t *     p_aout;                                  /* opaque */
-    aout_input_t *        p_aout_input;                            /* opaque */
-    audio_sample_format_t aout_format;
-    aout_buffer_t *       p_aout_buffer; /* current aout buffer being filled */
-
-    /*
-     * Packetizer output properties
-     */
-    sout_packetizer_input_t *p_sout_input;
-    sout_format_t           sout_format;
-    sout_buffer_t *         p_sout_buffer;            /* current sout buffer */
-
-    /*
      * Common properties
      */
-    uint8_t               *p_out_buffer;                    /* output buffer */
-    audio_date_t          end_date;
+    audio_date_t   end_date;
 
-    mtime_t pts;
+    mtime_t i_pts;
     int i_frame_size, i_bit_rate;
     unsigned int i_rate, i_channels, i_channels_conf;
 
@@ -89,7 +69,9 @@ enum {
     STATE_NOSYNC,
     STATE_SYNC,
     STATE_HEADER,
-    STATE_DATA
+    STATE_NEXT_SYNC,
+    STATE_GET_DATA,
+    STATE_SEND_DATA
 };
 
 /****************************************************************************
@@ -97,17 +79,14 @@ enum {
  ****************************************************************************/
 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 void CloseDecoder  ( vlc_object_t * );
+static void *DecodeBlock  ( decoder_t *, block_t ** );
 
 static int  SyncInfo      ( const byte_t *, int *, int *, int *,int * );
 
-static int GetOutBuffer ( decoder_t *, uint8_t ** );
-static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
-static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
-static int SendOutBuffer( decoder_t * );
+static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
+static aout_buffer_t *GetAoutBuffer( decoder_t * );
+static block_t       *GetSoutBuffer( decoder_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -115,12 +94,12 @@ static int SendOutBuffer( decoder_t * );
 vlc_module_begin();
     set_description( _("A/52 parser") );
     set_capability( "decoder", 100 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 
     add_submodule();
     set_description( _("A/52 audio packetizer") );
     set_capability( "packetizer", 10 );
-    set_callbacks( OpenPacketizer, NULL );
+    set_callbacks( OpenPacketizer, CloseDecoder );
 vlc_module_end();
 
 /*****************************************************************************
@@ -129,25 +108,38 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ')
-         && p_dec->p_fifo->i_fourcc != VLC_FOURCC('a','5','2','b') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','5','2',' ')
+          && p_dec->fmt_in.i_codec != VLC_FOURCC('a','5','2','b') )
     {
         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 =
+    if( ( p_dec->p_sys = 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;
+
+    /* Misc init */
+    p_sys->b_packetizer = VLC_FALSE;
+    p_sys->i_state = STATE_NOSYNC;
+    aout_DateSet( &p_sys->end_date, 0 );
+
+    p_sys->bytestream = block_BytestreamInit( p_dec );
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('a','5','2',' ');
+
+    /* Set callback */
+    p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
 
     return VLC_SUCCESS;
 }
@@ -163,68 +155,38 @@ static int OpenPacketizer( vlc_object_t *p_this )
     return i_ret;
 }
 
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    p_dec->p_sys->i_state = STATE_NOSYNC;
-
-    p_dec->p_sys->p_out_buffer = NULL;
-    aout_DateSet( &p_dec->p_sys->end_date, 0 );
-
-    p_dec->p_sys->p_aout = NULL;
-    p_dec->p_sys->p_aout_input = NULL;
-    p_dec->p_sys->p_aout_buffer = NULL;
-    p_dec->p_sys->aout_format.i_format = VLC_FOURCC('a','5','2',' ');
-
-    p_dec->p_sys->p_sout_input = NULL;
-    p_dec->p_sys->p_sout_buffer = NULL;
-    p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
-    p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC( 'a', '5', '2', ' ' );
-
-    p_dec->p_sys->p_chain = NULL;
-
-    return VLC_SUCCESS;
-}
-
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function is called just after the thread is launched.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     uint8_t p_header[A52_HEADER_SIZE];
+    uint8_t *p_buf;
+    void *p_out_buffer;
 
-    if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
+    if( !pp_block || !*pp_block ) return NULL;
+
+    if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
     {
         /* We've just started the stream, wait for the first PTS. */
-        block_Release( p_block );
-        return VLC_SUCCESS;
+        block_Release( *pp_block );
+        return NULL;
     }
 
-    if( p_block->b_discontinuity )
+    if( (*pp_block)->b_discontinuity )
     {
-        p_sys->i_state = STATE_SYNC;
+        p_sys->i_state = STATE_NOSYNC;
     }
 
-    if( p_sys->p_chain )
-    {
-        block_ChainAppend( &p_sys->p_chain, p_block );
-    }
-    else
-    {
-        block_ChainAppend( &p_sys->p_chain, p_block );
-        p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
-    }
+    block_BytestreamPush( &p_sys->bytestream, *pp_block );
 
     while( 1 )
     {
         switch( p_sys->i_state )
         {
-
         case STATE_NOSYNC:
             while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
                    == VLC_SUCCESS )
@@ -238,30 +200,21 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             }
             if( p_sys->i_state != STATE_SYNC )
             {
-                if( block_PeekByte( &p_sys->bytestream, p_header )
-                    == VLC_SUCCESS && p_header[0] == 0x0b )
-                {
-                    /* Start of a sync word, need more data */
-                    return VLC_SUCCESS;
-                }
-
-                block_ChainRelease( p_sys->p_chain );
-                p_sys->p_chain = NULL;
+               block_BytestreamFlush( &p_sys->bytestream );
 
                 /* Need more data */
-                return VLC_SUCCESS;
+                return NULL;
             }
 
         case STATE_SYNC:
             /* New frame, set the Presentation Time Stamp */
-            p_sys->pts = p_sys->bytestream.p_block->i_pts;
-            if( p_sys->pts != 0 &&
-                p_sys->pts != aout_DateGet( &p_sys->end_date ) )
+            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
+            if( p_sys->i_pts != 0 &&
+                p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
             {
-                aout_DateSet( &p_sys->end_date, p_sys->pts );
+                aout_DateSet( &p_sys->end_date, p_sys->i_pts );
             }
             p_sys->i_state = STATE_HEADER;
-            break;
 
         case STATE_HEADER:
             /* Get A/52 frame header (A52_HEADER_SIZE bytes) */
@@ -269,7 +222,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                                  A52_HEADER_SIZE ) != VLC_SUCCESS )
             {
                 /* Need more data */
-                return VLC_SUCCESS;
+                return NULL;
             }
 
             /* Check if frame is valid and get frame info */
@@ -285,247 +238,160 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                 p_sys->i_state = STATE_NOSYNC;
                 break;
             }
-            p_sys->i_state = STATE_DATA;
+            p_sys->i_state = STATE_NEXT_SYNC;
 
-        case STATE_DATA:
-            /* TODO: If p_block == NULL, flush the buffer without checking the
+        case STATE_NEXT_SYNC:
+            /* TODO: If pp_block == NULL, flush the buffer without checking the
              * next sync word */
 
-           /* Check if next expected frame contains the sync word */
-           if( block_PeekOffsetBytes( &p_sys->bytestream,
-                                      p_sys->i_frame_size, p_header, 2 )
-               != VLC_SUCCESS )
-           {
-               /* Need more data */
-               return VLC_SUCCESS;
-           }
-
-           if( p_header[0] != 0x0b || p_header[1] != 0x77 )
-           {
-               msg_Dbg( p_dec, "emulated sync word "
-                        "(no sync on following frame)" );
-               p_sys->i_state = STATE_NOSYNC;
-               block_SkipByte( &p_sys->bytestream );
-               break;
+            /* Check if next expected frame contains the sync word */
+            if( block_PeekOffsetBytes( &p_sys->bytestream,
+                                       p_sys->i_frame_size, p_header, 2 )
+                != VLC_SUCCESS )
+            {
+                /* Need more data */
+                return NULL;
             }
 
-            if( !p_sys->p_out_buffer )
-            if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
+            if( p_header[0] != 0x0b || p_header[1] != 0x77 )
             {
-                return VLC_EGENERIC;
+                msg_Dbg( p_dec, "emulated sync word "
+                         "(no sync on following frame)" );
+                p_sys->i_state = STATE_NOSYNC;
+                block_SkipByte( &p_sys->bytestream );
+                break;
             }
+            p_sys->i_state = STATE_SEND_DATA;
+            break;
 
-            /* Copy the whole frame into the buffer */
-            if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
-                                p_sys->i_frame_size ) != VLC_SUCCESS )
+        case STATE_GET_DATA:
+            /* Make sure we have enough data.
+             * (Not useful if we went through NEXT_SYNC) */
+            if( block_WaitBytes( &p_sys->bytestream,
+                                 p_sys->i_frame_size ) != VLC_SUCCESS )
             {
                 /* Need more data */
-                return VLC_SUCCESS;
+                return NULL;
             }
+            p_sys->i_state = STATE_SEND_DATA;
 
-            p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
+        case STATE_SEND_DATA:
+            if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
+            {
+                //p_dec->b_error = VLC_TRUE;
+                return NULL;
+            }
 
-            SendOutBuffer( p_dec );
-            p_sys->i_state = STATE_NOSYNC;
+            /* Copy the whole frame into the buffer. When we reach this point
+             * we already know we have enough data available. */
+            block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
 
             /* Make sure we don't reuse the same pts twice */
-            if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
-                p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
-        }
-    }
+            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
+                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
 
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * EndDecoder: clean up the decoder
- *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
-{
-    if( p_dec->p_sys->p_aout_input != NULL )
-    {
-        if( p_dec->p_sys->p_aout_buffer )
-        {
-            aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
-                                  p_dec->p_sys->p_aout_input,
-                                  p_dec->p_sys->p_aout_buffer );
-        }
+            /* So p_block doesn't get re-added several times */
+            *pp_block = block_BytestreamPop( &p_sys->bytestream );
 
-        aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
-    }
+            p_sys->i_state = STATE_NOSYNC;
 
-    if( p_dec->p_sys->p_sout_input != NULL )
-    {
-        if( p_dec->p_sys->p_sout_buffer )
-        {
-            sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
-                               p_dec->p_sys->p_sout_buffer );
+            return p_out_buffer;
         }
-
-        sout_InputDelete( p_dec->p_sys->p_sout_input );
     }
 
-    if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
-
-    free( p_dec->p_sys );
-
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
- * GetOutBuffer:
+ * CloseDecoder: clean up the decoder
  *****************************************************************************/
-static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i_ret;
 
-    if( p_sys->b_packetizer )
-    {
-        i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
-        *pp_out_buffer =
-            p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
-    }
-    else
-    {
-        i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
-        *pp_out_buffer =
-            p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
-    }
+    block_BytestreamRelease( &p_sys->bytestream );
 
-    return i_ret;
+    free( p_sys );
 }
 
 /*****************************************************************************
- * GetAoutBuffer:
+ * GetOutBuffer:
  *****************************************************************************/
-static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
+static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p_buf;
 
-    if( p_sys->p_aout_input != NULL &&
-        ( p_sys->aout_format.i_rate != p_sys->i_rate
-        || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
-        || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
+    if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
     {
-        /* Parameters changed - this should not happen. */
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-        p_sys->p_aout_input = NULL;
-    }
+        msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
+                  p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
 
-    /* Creating the audio input if not created yet. */
-    if( p_sys->p_aout_input == NULL )
-    {
-        p_sys->aout_format.i_rate = p_sys->i_rate;
-        p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
-        p_sys->aout_format.i_physical_channels
-            = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
-        p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
-        p_sys->aout_format.i_frame_length = A52_FRAME_NB;
         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
-        aout_DateSet( &p_sys->end_date, p_sys->pts );
-        p_sys->p_aout_input = aout_DecNew( p_dec,
-                                           &p_sys->p_aout,
-                                           &p_sys->aout_format );
-        if( p_sys->p_aout_input == NULL )
-        {
-            *pp_buffer = NULL;
-            return VLC_EGENERIC;
-        }
+        aout_DateSet( &p_sys->end_date, p_sys->i_pts );
     }
 
-    *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
-                                    A52_FRAME_NB );
-    if( *pp_buffer == NULL )
+    p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
+    p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
+    p_dec->fmt_out.audio.i_bitrate  = p_sys->i_bit_rate;
+    p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
+    p_dec->fmt_out.audio.i_frame_length = A52_FRAME_NB;
+
+    p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
+
+    if( p_sys->b_packetizer )
     {
-        return VLC_EGENERIC;
+        block_t *p_sout_buffer = GetSoutBuffer( p_dec );
+        p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
+        *pp_out_buffer = p_sout_buffer;
+    }
+    else
+    {
+        aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
+        p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
+        *pp_out_buffer = p_aout_buffer;
     }
 
-    (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
-    (*pp_buffer)->end_date =
-         aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
-
-    return VLC_SUCCESS;
+    return p_buf;
 }
 
 /*****************************************************************************
- * GetSoutBuffer:
+ * GetAoutBuffer:
  *****************************************************************************/
-static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
+static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    aout_buffer_t *p_buf;
 
-    if( p_sys->p_sout_input != NULL &&
-        ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
-          || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
-    {
-        /* Parameters changed - this should not happen. */
-    }
-
-    /* Creating the sout input if not created yet. */
-    if( p_sys->p_sout_input == NULL )
-    {
-        p_sys->sout_format.i_sample_rate = p_sys->i_rate;
-        p_sys->sout_format.i_channels    = p_sys->i_channels;
-        p_sys->sout_format.i_block_align = 0;
-        p_sys->sout_format.i_bitrate     = p_sys->i_bit_rate;
-        p_sys->sout_format.i_extra_data  = 0;
-        p_sys->sout_format.p_extra_data  = NULL;
+    p_buf = p_dec->pf_aout_buffer_new( p_dec, A52_FRAME_NB  );
+    if( p_buf == NULL ) return NULL;
 
-        aout_DateInit( &p_sys->end_date, p_sys->i_rate );
-        aout_DateSet( &p_sys->end_date, p_sys->pts );
+    p_buf->start_date = aout_DateGet( &p_sys->end_date );
+    p_buf->end_date = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB );
 
-        p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
-        if( p_sys->p_sout_input == NULL )
-        {
-            msg_Err( p_dec, "cannot add a new stream" );
-            *pp_buffer = NULL;
-            return VLC_EGENERIC;
-        }
-        msg_Info( p_dec, "A/52 channels:%d samplerate:%d bitrate:%d",
-                  p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
-    }
-
-    *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
-                                 p_sys->i_frame_size );
-    if( *pp_buffer == NULL )
-    {
-        return VLC_EGENERIC;
-    }
-
-    (*pp_buffer)->i_pts =
-        (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
-
-    (*pp_buffer)->i_length =
-        aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB )
-        - (*pp_buffer)->i_pts;
-
-    return VLC_SUCCESS;
+    return p_buf;
 }
 
 /*****************************************************************************
- * SendOutBuffer:
+ * GetSoutBuffer:
  *****************************************************************************/
-static int SendOutBuffer( decoder_t *p_dec )
+static block_t *GetSoutBuffer( decoder_t *p_dec )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
 
-    if( p_sys->b_packetizer )
-    {
-        sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
-        p_sys->p_sout_buffer = NULL;
-    }
-    else
-    {
-        /* We have all we need, send the buffer to the aout core. */
-        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
-                      p_sys->p_aout_buffer );
-        p_sys->p_aout_buffer = NULL;
-    }
+    p_block = block_New( p_dec, p_sys->i_frame_size );
+    if( p_block == NULL ) return NULL;
 
-    p_sys->p_out_buffer = NULL;
+    p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
 
-    return VLC_SUCCESS;
+    p_block->i_length = aout_DateIncrement( &p_sys->end_date, A52_FRAME_NB ) -
+        p_block->i_pts;
+
+    return p_block;
 }
 
 /*****************************************************************************
index 5afd362..555f08f 100644 (file)
@@ -2,7 +2,7 @@
  * adpcm.c : adpcm variant audio decoder
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: adpcm.c,v 1.15 2003/11/05 01:47:40 fenrir Exp $
+ * $Id: adpcm.c,v 1.16 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -29,7 +29,6 @@
 #include <stdlib.h>                                      /* malloc(), free() */
 
 #include <vlc/vlc.h>
-#include <vlc/aout.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-static int  Open    ( vlc_object_t * );
+static int  OpenDecoder( vlc_object_t * );
+static void CloseDecoder( vlc_object_t * );
+
+static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
 
 vlc_module_begin();
     set_description( _("ADPCM audio decoder") );
     set_capability( "decoder", 50 );
-    set_callbacks( Open, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 vlc_module_end();
 
-
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -61,31 +62,19 @@ enum adpcm_codec_e
 
 struct decoder_sys_t
 {
-    WAVEFORMATEX       *p_wf;
     enum adpcm_codec_e codec;
 
     int                 i_block;
     int                 i_samplesperblock;
 
-    /* audio output */
-    aout_instance_t *   p_aout;       /* opaque */
-    aout_input_t *      p_aout_input; /* opaque */
-    audio_sample_format_t output_format;
-
-    audio_date_t        date;
+    audio_date_t        end_date;
 };
 
-static int Init  ( decoder_t * );
-static int Decode( decoder_t *, block_t * );
-static int End   ( decoder_t * );
-
-
-
-static void DecodeAdpcmMs       ( decoder_sys_t *, int16_t *, uint8_t * );
-static void DecodeAdpcmImaWav   ( decoder_sys_t *, int16_t *, uint8_t * );
-static void DecodeAdpcmImaQT    ( decoder_sys_t *, int16_t *, uint8_t * );
-static void DecodeAdpcmDk4      ( decoder_sys_t *, int16_t *, uint8_t * );
-static void DecodeAdpcmDk3      ( decoder_sys_t *, int16_t *, uint8_t * );
+static void DecodeAdpcmMs    ( decoder_t *, int16_t *, uint8_t * );
+static void DecodeAdpcmImaWav( decoder_t *, int16_t *, uint8_t * );
+static void DecodeAdpcmImaQT ( decoder_t *, int16_t *, uint8_t * );
+static void DecodeAdpcmDk4   ( decoder_t *, int16_t *, uint8_t * );
+static void DecodeAdpcmDk3   ( decoder_t *, int16_t *, uint8_t * );
 
 static int pi_channels_maps[6] =
 {
@@ -134,64 +123,48 @@ static int i_adaptation_coeff2[7] =
     0, -256, 0, 64, 0, -208, -232
 };
 
-
 /*****************************************************************************
  * OpenDecoder: probe the decoder and return score
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to choose.
  *****************************************************************************/
-static int Open( vlc_object_t *p_this )
+static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    switch( p_dec->p_fifo->i_fourcc )
+    switch( p_dec->fmt_in.i_codec )
     {
         case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
         case VLC_FOURCC('m','s',0x00,0x02): /* MS ADPCM */
         case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
         case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
         case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
-
-            p_dec->pf_init   = Init;
-            p_dec->pf_decode = Decode;
-            p_dec->pf_end    = End;
-
-            p_dec->p_sys     = malloc( sizeof( decoder_sys_t ) );
-            return VLC_SUCCESS;
-
+            break;
         default:
             return VLC_EGENERIC;
     }
-}
-
-/*****************************************************************************
- * Init:
- *****************************************************************************/
-static int Init  ( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
 
-    WAVEFORMATEX *p_wf;
-    if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL )
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
-        msg_Err( p_dec, "unknown raw format" );
+        msg_Err( p_dec, "out of memory" );
         return VLC_EGENERIC;
     }
 
-    if( p_wf->nChannels < 1 || p_wf->nChannels > 2 )
+    if( p_dec->fmt_in.audio.i_channels <= 0 ||
+        p_dec->fmt_in.audio.i_channels > 5 )
     {
-        msg_Err( p_dec, "bad channels count(1-2)" );
+        msg_Err( p_dec, "bad channels count(1-5)" );
         return VLC_EGENERIC;
     }
-    if( p_wf->nSamplesPerSec <= 0 )
+
+    if( p_dec->fmt_in.audio.i_rate <= 0 )
     {
         msg_Err( p_dec, "bad samplerate" );
         return VLC_EGENERIC;
     }
 
-    p_sys->p_wf = p_wf;
-    switch( p_dec->p_fifo->i_fourcc )
+    switch( p_dec->fmt_in.i_codec )
     {
         case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
             p_sys->codec = ADPCM_IMA_QT;
@@ -210,146 +183,152 @@ static int Init  ( decoder_t *p_dec )
             break;
     }
 
-    if( ( p_sys->i_block = p_wf->nBlockAlign ) <= 0 )
+    if( 1 )//( p_sys->i_block = p_wf->nBlockAlign ) <= 0 )
     {
-        p_sys->i_block = p_sys->codec==ADPCM_IMA_QT ? 34*p_wf->nChannels:1024;
+        p_sys->i_block = (p_sys->codec == ADPCM_IMA_QT) ?
+            34 * p_dec->fmt_in.audio.i_channels : 1024;
         msg_Warn( p_dec, "block size undefined, -> using %d", p_sys->i_block );
     }
 
     /* calculate samples per block */
     switch( p_sys->codec )
     {
-        case ADPCM_IMA_QT:
-            p_sys->i_samplesperblock = 64;
-            break;
-        case ADPCM_IMA_WAV:
-            p_sys->i_samplesperblock =
-                 2 * ( p_sys->i_block - 4 * p_wf->nChannels )/ p_wf->nChannels;
-                 break;
-        case ADPCM_MS:
-            p_sys->i_samplesperblock =
-                2 * (p_sys->i_block - 7 * p_wf->nChannels)/p_wf->nChannels + 2;
-            break;
-        case ADPCM_DK4:
-            p_sys->i_samplesperblock =
-               2 * (p_sys->i_block - 4 * p_wf->nChannels)/p_wf->nChannels + 1;
-            break;
-        case ADPCM_DK3:
-            p_wf->nChannels = 2;
-            p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3;
-            break;
+    case ADPCM_IMA_QT:
+        p_sys->i_samplesperblock = 64;
+        break;
+    case ADPCM_IMA_WAV:
+        p_sys->i_samplesperblock =
+            2 * ( p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels ) /
+            p_dec->fmt_in.audio.i_channels;
+        break;
+    case ADPCM_MS:
+        p_sys->i_samplesperblock =
+            2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels) /
+            p_dec->fmt_in.audio.i_channels + 2;
+        break;
+    case ADPCM_DK4:
+        p_sys->i_samplesperblock =
+            2 * (p_sys->i_block - 4 * p_dec->fmt_in.audio.i_channels) /
+            p_dec->fmt_in.audio.i_channels + 1;
+        break;
+    case ADPCM_DK3:
+        p_dec->fmt_in.audio.i_channels = 2;
+        p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3;
+        break;
     }
-    msg_Dbg( p_dec,
-             "format: samplerate:%dHz channels:%d bits/sample:%d blockalign:%d samplesperblock %d",
-             p_wf->nSamplesPerSec, p_wf->nChannels,
-             p_wf->wBitsPerSample, p_wf->nBlockAlign,
+
+    msg_Dbg( p_dec, "format: samplerate:%dHz channels:%d bits/sample:%d "
+             "blockalign:%d samplesperblock %d",
+             p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
+             p_dec->fmt_in.audio.i_bitspersample, p_sys->i_block,
              p_sys->i_samplesperblock );
 
-    p_sys->output_format.i_format = AOUT_FMT_S16_NE;
-    p_sys->output_format.i_rate = p_wf->nSamplesPerSec;
-    p_sys->output_format.i_physical_channels =
-    p_sys->output_format.i_original_channels =
-            pi_channels_maps[p_wf->nChannels];
+    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
+    p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
+    p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_dec->fmt_out.audio.i_original_channels =
+            pi_channels_maps[p_dec->fmt_in.audio.i_channels];
 
-    p_sys->p_aout = NULL;
-    p_sys->p_aout_input = aout_DecNew( p_dec,
-                                       &p_sys->p_aout, &p_sys->output_format);
-    if( p_sys->p_aout_input == NULL )
-    {
-        msg_Err( p_dec, "cannot create aout" );
-        return VLC_EGENERIC;
-    }
+    aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
+    aout_DateSet( &p_sys->end_date, 0 );
 
-    aout_DateInit( &p_sys->date, p_sys->output_format.i_rate );
-    aout_DateSet( &p_sys->date, 0 );
+    p_dec->pf_decode_audio = DecodeBlock;
 
     return VLC_SUCCESS;
 }
 
 /*****************************************************************************
- * Decode:
+ * DecodeBlock:
  *****************************************************************************/
-static int Decode( decoder_t *p_dec, block_t *p_block )
+static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys  = p_dec->p_sys;
-    mtime_t        i_pts  = p_block->i_pts;
-    uint8_t       *p_data = p_block->p_buffer;
-    int            i_data = p_block->i_buffer;
+    block_t *p_block;
 
-    while( i_data >= p_sys->i_block )
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
+
+    if( p_block->i_pts != 0 &&
+        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
+    {
+        aout_DateSet( &p_sys->end_date, p_block->i_pts );
+    }
+    else if( !aout_DateGet( &p_sys->end_date ) )
     {
-        aout_buffer_t *out;
+        /* We've just started the stream, wait for the first PTS. */
+        block_Release( p_block );
+        return NULL;
+    }
 
-        if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->date ) )
-        {
-            aout_DateSet( &p_sys->date, i_pts );
-        }
-        else if( !aout_DateGet( &p_sys->date ) )
-        {
-            block_Release( p_block );
-            return VLC_SUCCESS;
-        }
-        i_pts = 0;
+    /* Don't re-use the same pts twice */
+    p_block->i_pts = 0;
+
+    if( p_block->i_buffer >= p_sys->i_block )
+    {
+        aout_buffer_t *p_out;
 
-        out = aout_DecNewBuffer( p_sys->p_aout,
-                                 p_sys->p_aout_input,
-                                 p_sys->i_samplesperblock );
-        if( out == NULL )
+        p_out = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_samplesperblock );
+        if( p_out == NULL )
         {
-            msg_Err( p_dec, "cannot get aout buffer" );
             block_Release( p_block );
-            return VLC_EGENERIC;
+            return NULL;
         }
-        out->start_date = aout_DateGet( &p_sys->date );
-        out->end_date   = aout_DateIncrement( &p_sys->date,
-                                              p_sys->i_samplesperblock );
+
+        p_out->start_date = aout_DateGet( &p_sys->end_date );
+        p_out->end_date =
+            aout_DateIncrement( &p_sys->end_date, p_sys->i_samplesperblock );
 
         switch( p_sys->codec )
         {
-            case ADPCM_IMA_QT:
-                DecodeAdpcmImaQT( p_sys, (int16_t*)out->p_buffer, p_data );
-                break;
-            case ADPCM_IMA_WAV:
-                DecodeAdpcmImaWav( p_sys, (int16_t*)out->p_buffer, p_data );
-                break;
-            case ADPCM_MS:
-                DecodeAdpcmMs( p_sys, (int16_t*)out->p_buffer, p_data );
-                break;
-            case ADPCM_DK4:
-                DecodeAdpcmDk4( p_sys, (int16_t*)out->p_buffer, p_data );
-                break;
-            case ADPCM_DK3:
-                DecodeAdpcmDk3( p_sys, (int16_t*)out->p_buffer, p_data );
-                break;
-            default:
-                break;
+        case ADPCM_IMA_QT:
+            DecodeAdpcmImaQT( p_dec, (int16_t*)p_out->p_buffer,
+                              p_block->p_buffer );
+            break;
+        case ADPCM_IMA_WAV:
+            DecodeAdpcmImaWav( p_dec, (int16_t*)p_out->p_buffer,
+                               p_block->p_buffer );
+            break;
+        case ADPCM_MS:
+            DecodeAdpcmMs( p_dec, (int16_t*)p_out->p_buffer,
+                           p_block->p_buffer );
+            break;
+        case ADPCM_DK4:
+            DecodeAdpcmDk4( p_dec, (int16_t*)p_out->p_buffer,
+                            p_block->p_buffer );
+            break;
+        case ADPCM_DK3:
+            DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer,
+                            p_block->p_buffer );
+            break;
+        default:
+            break;
         }
-        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out );
 
-        p_data += p_sys->i_block;
-        i_data -= p_sys->i_block;
+        p_block->p_buffer += p_out->i_nb_bytes;
+        p_block->i_buffer -= p_out->i_nb_bytes;
+        return p_out;
     }
 
     block_Release( p_block );
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
- * End:
+ * CloseDecoder:
  *****************************************************************************/
-static int End   ( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_sys->p_aout_input )
-    {
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-    }
     free( p_sys );
-
-    return VLC_SUCCESS;
 }
 
+/*****************************************************************************
+ * Local functions
+ *****************************************************************************/
 #define CLAMP( v, min, max ) \
     if( (v) < (min) ) (v) = (min); \
     if( (v) > (max) ) (v) = (max)
@@ -401,14 +380,16 @@ static int AdpcmMsExpandNibble(adpcm_ms_channel_t *p_channel,
     return( i_predictor );
 }
 
-static void DecodeAdpcmMs( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer )
+static void DecodeAdpcmMs( decoder_t *p_dec, int16_t *p_sample,
+                           uint8_t *p_buffer )
 {
+    decoder_sys_t *p_sys  = p_dec->p_sys;
     adpcm_ms_channel_t channel[2];
     int i_nibbles;
     int b_stereo;
     int i_block_predictor;
 
-    b_stereo = p_sys->p_wf->nChannels == 2 ? 1 : 0;
+    b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0;
 
     GetByte( i_block_predictor );
     CLAMP( i_block_predictor, 0, 6 );
@@ -453,8 +434,8 @@ static void DecodeAdpcmMs( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_b
         *p_sample++ = channel[0].i_sample1;
     }
 
-    for( i_nibbles =  2 *( p_sys->i_block - 7 * p_sys->p_wf->nChannels );
-         i_nibbles > 0; i_nibbles -= 2,p_buffer++ )
+    for( i_nibbles = 2 * (p_sys->i_block - 7 * p_dec->fmt_in.audio.i_channels);
+         i_nibbles > 0; i_nibbles -= 2, p_buffer++ )
     {
         *p_sample++ = AdpcmMsExpandNibble( &channel[0], (*p_buffer) >> 4);
         *p_sample++ = AdpcmMsExpandNibble( &channel[b_stereo ? 1 : 0],
@@ -495,13 +476,15 @@ static int AdpcmImaWavExpandNibble(adpcm_ima_wav_channel_t *p_channel,
     return( p_channel->i_predictor );
 }
 
-static void DecodeAdpcmImaWav( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer )
+static void DecodeAdpcmImaWav( decoder_t *p_dec, int16_t *p_sample,
+                               uint8_t *p_buffer )
 {
+    decoder_sys_t *p_sys  = p_dec->p_sys;
     adpcm_ima_wav_channel_t channel[2];
     int                     i_nibbles;
     int                     b_stereo;
 
-    b_stereo = p_sys->p_wf->nChannels == 2 ? 1 : 0;
+    b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0;
 
     GetWord( channel[0].i_predictor );
     GetByte( channel[0].i_step_index );
@@ -562,16 +545,17 @@ static void DecodeAdpcmImaWav( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t
 /*
  * Ima4 in QT file
  */
-static void DecodeAdpcmImaQT( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer )
+static void DecodeAdpcmImaQT( decoder_t *p_dec, int16_t *p_sample,
+                              uint8_t *p_buffer )
 {
     adpcm_ima_wav_channel_t channel[2];
     int                     i_nibbles;
     int                     i_ch;
     int                     i_step;
 
-    i_step   = p_sys->p_wf->nChannels;
+    i_step = p_dec->fmt_in.audio.i_channels;
 
-    for( i_ch = 0; i_ch < p_sys->p_wf->nChannels; i_ch++ )
+    for( i_ch = 0; i_ch < p_dec->fmt_in.audio.i_channels; i_ch++ )
     {
         /* load preambule */
         channel[i_ch].i_predictor  = (int16_t)((( ( p_buffer[0] << 1 )|(  p_buffer[1] >> 7 ) ))<<7);
@@ -599,14 +583,15 @@ static void DecodeAdpcmImaQT( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *
 /*
  * Dk4
  */
-
-static void DecodeAdpcmDk4( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer )
+static void DecodeAdpcmDk4( decoder_t *p_dec, int16_t *p_sample,
+                            uint8_t *p_buffer )
 {
+    decoder_sys_t *p_sys  = p_dec->p_sys;
     adpcm_ima_wav_channel_t channel[2];
     int                     i_nibbles;
     int                     b_stereo;
 
-    b_stereo = p_sys->p_wf->nChannels == 2 ? 1 : 0;
+    b_stereo = p_dec->fmt_in.audio.i_channels == 2 ? 1 : 0;
 
     GetWord( channel[0].i_predictor );
     GetByte( channel[0].i_step_index );
@@ -644,8 +629,10 @@ static void DecodeAdpcmDk4( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_
 /*
  * Dk3
  */
-static void DecodeAdpcmDk3( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_buffer )
+static void DecodeAdpcmDk3( decoder_t *p_dec, int16_t *p_sample,
+                            uint8_t *p_buffer )
 {
+    decoder_sys_t *p_sys  = p_dec->p_sys;
     uint8_t                 *p_end = &p_buffer[p_sys->i_block];
     adpcm_ima_wav_channel_t sum;
     adpcm_ima_wav_channel_t diff;
@@ -705,4 +692,3 @@ static void DecodeAdpcmDk3( decoder_sys_t *p_sys, int16_t *p_sample, uint8_t *p_
         }
     }
 }
-
index 7e0b85e..ae7dd17 100644 (file)
@@ -2,7 +2,7 @@
  * araw.c: Pseudo audio decoder; for raw pcm data
  *****************************************************************************
  * Copyright (C) 2001, 2003 VideoLAN
- * $Id: araw.c,v 1.23 2003/11/08 04:57:56 fenrir Exp $
+ * $Id: araw.c,v 1.24 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>                                      /* malloc(), free() */
-#include <vlc/vlc.h>
 
-#include <vlc/aout.h>
+#include <vlc/vlc.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
-#include <vlc/sout.h>
-
 #include "codecs.h"
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-static int  DecoderOpen    ( vlc_object_t * );
+static int  DecoderOpen ( vlc_object_t * );
+static void DecoderClose( vlc_object_t * );
 
-static int  EncoderOpen  ( vlc_object_t *p_this );
-static void EncoderClose ( vlc_object_t *p_this );
+static int  EncoderOpen ( vlc_object_t * );
+static void EncoderClose( vlc_object_t * );
 
 vlc_module_begin();
     /* audio decoder module */
     set_description( _("Raw/Log Audio decoder") );
     set_capability( "decoder", 50 );
-    set_callbacks( DecoderOpen, NULL );
+    set_callbacks( DecoderOpen, DecoderClose );
 
     /* audio encoder submodule */
     add_submodule();
     set_description( _("Raw audio encoder") );
-    set_capability( "audio encoder", 10 );
+    set_capability( "encoder", 10 );
     set_callbacks( EncoderOpen, EncoderClose );
 vlc_module_end();
 
-
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int DecoderInit  ( decoder_t * );
-static int DecoderDecode( decoder_t *, block_t * );
-static int DecoderEnd   ( decoder_t * );
+static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
+static block_t *EncoderEncode( encoder_t *, aout_buffer_t * );
 
 struct decoder_sys_t
 {
-    WAVEFORMATEX    *p_wf;
-
-    int16_t        *p_logtos16;  // used with m/alaw to int16_t
-
-    /* Output properties */
-    aout_instance_t *   p_aout;       /* opaque */
-    aout_input_t *      p_aout_input; /* opaque */
-    audio_sample_format_t output_format;
+    int16_t *p_logtos16;  /* used with m/alaw to int16_t */
 
-    audio_date_t        date;
+    audio_date_t end_date;
 };
 
-
-static block_t *EncoderEncode( encoder_t *, aout_buffer_t *p_aout_buf );
-
-/*****************************************************************************
- * DecoderOpen: probe the decoder and return score
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to choose.
- *****************************************************************************/
-static int DecoderOpen( vlc_object_t *p_this )
-{
-    decoder_t *p_dec = (decoder_t*)p_this;
-
-    switch( p_dec->p_fifo->i_fourcc )
-    {
-        case VLC_FOURCC('a','r','a','w'): /* from wav/avi/asf file */
-        case VLC_FOURCC('t','w','o','s'): /* _signed_ big endian samples (mov)*/
-        case VLC_FOURCC('s','o','w','t'): /* _signed_ little endian samples (mov)*/
-
-        case VLC_FOURCC('a','l','a','w'):
-        case VLC_FOURCC('u','l','a','w'):
-            p_dec->pf_init   = DecoderInit;
-            p_dec->pf_decode = DecoderDecode;
-            p_dec->pf_end    = DecoderEnd;
-
-            p_dec->p_sys     = malloc( sizeof( decoder_sys_t ) );
-            return VLC_SUCCESS;
-
-        default:
-            return VLC_EGENERIC;
-    }
-}
-
 static int pi_channels_maps[6] =
 {
     0,
@@ -195,264 +151,267 @@ static int16_t alawtos16[256] =
 };
 
 /*****************************************************************************
- * DecoderInit: initialize data before entering main loop
+ * DecoderOpen: probe the decoder and return score
  *****************************************************************************/
-static int DecoderInit( decoder_t *p_dec )
+static int DecoderOpen( vlc_object_t *p_this )
 {
-    decoder_sys_t *p_sys = p_dec->p_sys;
+    decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+
+    switch( p_dec->fmt_in.i_codec )
+    {
+    /* from wav/avi/asf file */
+    case VLC_FOURCC('a','r','a','w'):
+    /* _signed_ big endian samples (mov)*/
+    case VLC_FOURCC('t','w','o','s'):
+    /* _signed_ little endian samples (mov)*/
+    case VLC_FOURCC('s','o','w','t'):
+
+    case VLC_FOURCC('a','l','a','w'):
+    case VLC_FOURCC('u','l','a','w'):
+        break;
+
+    default:
+        return VLC_EGENERIC;
+    }
 
-    WAVEFORMATEX *p_wf;
-    if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL )
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
-        msg_Err( p_dec, "unknown raw format" );
+        msg_Err( p_dec, "out of memory" );
         return VLC_EGENERIC;
     }
 
-    if( p_wf->nChannels <= 0 || p_wf->nChannels > 5 )
+    if( p_dec->fmt_in.audio.i_channels <= 0 ||
+        p_dec->fmt_in.audio.i_channels > 5 )
     {
         msg_Err( p_dec, "bad channels count(1-5)" );
         return VLC_EGENERIC;
     }
-    if( p_wf->nSamplesPerSec <= 0 )
+
+    if( p_dec->fmt_in.audio.i_rate <= 0 )
     {
         msg_Err( p_dec, "bad samplerate" );
         return VLC_EGENERIC;
     }
 
-    p_sys->p_wf = p_wf;
     p_sys->p_logtos16 = NULL;
 
-    /* fixing some values */
-    if( p_wf->nBlockAlign == 0 &&
-        ( p_wf->wFormatTag == WAVE_FORMAT_PCM ||
-          p_wf->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ) )
-    {
-        p_wf->nBlockAlign = ( p_wf->wBitsPerSample + 7 ) / 8 * p_wf->nChannels;
-    }
+    msg_Dbg( p_dec, "samplerate:%dHz channels:%d bits/sample:%d",
+             p_dec->fmt_in.audio.i_rate, p_dec->fmt_in.audio.i_channels,
+             p_dec->fmt_in.audio.i_bitspersample );
 
-    msg_Dbg( p_dec,
-             "samplerate:%dHz channels:%d bits/sample:%d blockalign:%d",
-             p_wf->nSamplesPerSec,  p_wf->nChannels,
-             p_wf->wBitsPerSample,  p_wf->nBlockAlign );
-
-    if( p_wf->wFormatTag  == WAVE_FORMAT_IEEE_FLOAT )
+    if( 0 /* p_wf->wFormatTag == WAVE_FORMAT_IEEE_FLOAT */ )
     {
-        switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
+        switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
         {
-            case( 4 ):
-                p_sys->output_format.i_format = VLC_FOURCC('f','l','3','2');
-                break;
-            case( 8 ):
-                p_sys->output_format.i_format = VLC_FOURCC('f','l','6','4');
-                break;
-            default:
-                msg_Err( p_dec, "bad parameters(bits/sample)" );
-                return VLC_EGENERIC;
+        case 4:
+            p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
+            break;
+        case 8:
+            p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','6','4');
+            break;
+        default:
+            msg_Err( p_dec, "bad parameters(bits/sample)" );
+            return VLC_EGENERIC;
         }
     }
     else
     {
-        if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 't', 'w', 'o', 's' ) )
+        if( p_dec->fmt_in.i_codec == VLC_FOURCC( 't', 'w', 'o', 's' ) )
         {
-            switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
+            switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
             {
-                case( 1 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','8',' ',' ');
-                    break;
-                case( 2 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','1','6','b');
-                    break;
-                case( 3 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','2','4','b');
-                    break;
-                case( 4 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','3','2','b');
-                    break;
-                default:
-                    msg_Err( p_dec, "bad parameters(bits/sample)" );
-                    return VLC_EGENERIC;
+            case 1:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
+                break;
+            case 2:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
+                break;
+            case 3:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
+                break;
+            case 4:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b');
+                break;
+            default:
+                msg_Err( p_dec, "bad parameters(bits/sample)" );
+                return VLC_EGENERIC;
             }
         }
-        else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 's', 'o', 'w', 't' ) )
+        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 's', 'o', 'w', 't' ) )
         {
-            switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
+            switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
             {
-                case( 1 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','8',' ',' ');
-                    break;
-                case( 2 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','1','6','l');
-                    break;
-                case( 3 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','2','4','l');
-                    break;
-                case( 4 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','3','2','l');
-                    break;
-                default:
-                    msg_Err( p_dec, "bad parameters(bits/sample)" );
-                    return VLC_EGENERIC;
+            case 1:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');
+                break;
+            case 2:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
+                break;
+            case 3:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
+                break;
+            case 4:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
+                break;
+            default:
+                msg_Err( p_dec, "bad parameters(bits/sample)" );
+                return VLC_EGENERIC;
             }
         }
-        else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
+        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'r', 'a', 'w' ) )
         {
-            switch( ( p_wf->wBitsPerSample + 7 ) / 8 )
+            switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 )
             {
-                case( 1 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('u','8',' ',' ');
-                    break;
-                case( 2 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','1','6','l');
-                    break;
-                case( 3 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','2','4','l');
-                    break;
-                case( 4 ):
-                    p_sys->output_format.i_format = VLC_FOURCC('s','3','2','l');
-                    break;
-                default:
-                    msg_Err( p_dec, "bad parameters(bits/sample)" );
-                    return VLC_EGENERIC;
+            case 1:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' ');
+                break;
+            case 2:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l');
+                break;
+            case 3:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l');
+                break;
+            case 4:
+                p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l');
+                break;
+            default:
+                msg_Err( p_dec, "bad parameters(bits/sample)" );
+                return VLC_EGENERIC;
             }
         }
-        else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'a', 'l', 'a', 'w' ) )
+        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'l', 'a', 'w' ) )
         {
-            p_sys->output_format.i_format = AOUT_FMT_S16_NE;
+            p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
             p_sys->p_logtos16  = alawtos16;
-            p_wf->wBitsPerSample = 8;
+            p_dec->fmt_in.audio.i_bitspersample = 8;
         }
-        else if( p_dec->p_fifo->i_fourcc == VLC_FOURCC( 'u', 'l', 'a', 'w' ) )
+        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'u', 'l', 'a', 'w' ) )
         {
-            p_sys->output_format.i_format = AOUT_FMT_S16_NE;
+            p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
             p_sys->p_logtos16  = ulawtos16;
-            p_wf->wBitsPerSample = 8;
+            p_dec->fmt_in.audio.i_bitspersample = 8;
         }
     }
-    p_sys->output_format.i_rate = p_wf->nSamplesPerSec;
 
-    p_sys->output_format.i_physical_channels =
-    p_sys->output_format.i_original_channels = pi_channels_maps[p_wf->nChannels];
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
+    p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_dec->fmt_out.audio.i_original_channels =
+            pi_channels_maps[p_dec->fmt_in.audio.i_channels];
 
-    p_sys->p_aout       = NULL;
-    p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout,
-                                       &p_sys->output_format );
-    if( p_sys->p_aout_input == NULL )
-    {
-        msg_Err( p_dec, "cannot create aout" );
-        return VLC_EGENERIC;
-    }
+    aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );
+    aout_DateSet( &p_sys->end_date, 0 );
 
-    aout_DateInit( &p_sys->date, p_sys->output_format.i_rate );
-    aout_DateSet( &p_sys->date, 0 );
+    p_dec->pf_decode_audio = DecodeBlock;
 
     return VLC_SUCCESS;
 }
 
-/*****************************************************************************
- * DecoderDecode: decodes a frame
- *****************************************************************************/
-static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
+/****************************************************************************
+ * DecodeBlock: the whole thing
+ ****************************************************************************
+ * This function must be fed with whole samples (see nBlockAlign).
+ ****************************************************************************/
+static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int            i_size = p_block->i_buffer;
-    uint8_t        *p = p_block->p_buffer;
-    int            i_samples; // per channels
+    block_t *p_block;
+    int i_samples;
 
-    if( p_sys->p_wf->nBlockAlign > 0 )
-    {
-        /* Align it (it should already be aligned by demuxer) */
-        i_size -= i_size % p_sys->p_wf->nBlockAlign;
-    }
-    if( i_size < p_sys->p_wf->nBlockAlign )
-    {
-        block_Release( p_block );
-        return VLC_SUCCESS;
-    }
-    i_samples = i_size / ( ( p_sys->p_wf->wBitsPerSample + 7 ) / 8 ) /
-                p_sys->p_wf->nChannels;
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
 
-    if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) )
+    if( p_block->i_pts != 0 &&
+        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
     {
-        aout_DateSet( &p_sys->date, p_block->i_pts );
+        aout_DateSet( &p_sys->end_date, p_block->i_pts );
     }
-    else if( !aout_DateGet( &p_sys->date ) )
+    else if( !aout_DateGet( &p_sys->end_date ) )
     {
+        /* We've just started the stream, wait for the first PTS. */
         block_Release( p_block );
-        return VLC_SUCCESS;
+        return NULL;
     }
 
-    while( i_samples > 0 )
+    /* Don't re-use the same pts twice */
+    p_block->i_pts = 0;
+
+    i_samples = p_block->i_buffer * 8 / p_dec->fmt_in.audio.i_bitspersample /
+        p_dec->fmt_in.audio.i_channels;
+
+
+    /* Create chunks of max 1024 samples */
+    if( i_samples > 0 )
     {
-        int           i_copy = __MIN( i_samples, 1024 );
-        aout_buffer_t *out;
+        aout_buffer_t *p_out;
+        i_samples = __MIN( i_samples, 1024 );
 
-        out = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input, i_copy );
-        if( out == NULL )
+        p_out = p_dec->pf_aout_buffer_new( p_dec, i_samples );
+        if( p_out == NULL )
         {
-            msg_Err( p_dec, "cannot get aout buffer" );
             block_Release( p_block );
-            return VLC_EGENERIC;
+            return NULL;
         }
 
-        out->start_date = aout_DateGet( &p_sys->date );
-        out->end_date   = aout_DateIncrement( &p_sys->date, i_copy );
+        p_out->start_date = aout_DateGet( &p_sys->end_date );
+        p_out->end_date   = aout_DateIncrement( &p_sys->end_date, i_samples );
 
         if( p_sys->p_logtos16 )
         {
-            int16_t      *s = (int16_t*)out->p_buffer;
+            int16_t *s = (int16_t*)p_out->p_buffer;
             unsigned int i;
 
-            for( i = 0; i < out->i_nb_bytes / 2; i++ )
+            for( i = 0; i < p_out->i_nb_bytes / 2; i++ )
             {
-                *s++ = p_sys->p_logtos16[*p++];
+                *s++ = p_sys->p_logtos16[*p_block->p_buffer++];
+                p_block->i_buffer++;
             }
         }
         else
         {
-            memcpy( out->p_buffer, p, out->i_nb_bytes );
-
-            p += out->i_nb_bytes;
+            memcpy( p_out->p_buffer, p_block->p_buffer, p_out->i_nb_bytes );
+            p_block->p_buffer += p_out->i_nb_bytes;
+            p_block->i_buffer -= p_out->i_nb_bytes;
         }
 
-        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out );
-
-        i_samples -= i_copy;
+        return p_out;
     }
+
     block_Release( p_block );
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
- * DecoderEnd : faad decoder thread destruction
+ * DecoderClose: decoder destruction
  *****************************************************************************/
-static int DecoderEnd( decoder_t *p_dec )
+static void DecoderClose( vlc_object_t *p_this )
 {
-    decoder_sys_t *p_sys = p_dec->p_sys;
+    decoder_t *p_dec = (decoder_t *)p_this;
 
-    if( p_sys->p_aout_input )
-    {
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-    }
-    free( p_sys );
-
-    return VLC_SUCCESS;
+    free( p_dec->p_sys );
 }
 
 /*****************************************************************************
  * EncoderOpen:
  *****************************************************************************/
-static int  EncoderOpen  ( vlc_object_t *p_this )
+static int EncoderOpen( vlc_object_t *p_this )
 {
     encoder_t *p_enc = (encoder_t *)p_this;
 
-    if( p_enc->format.audio.i_format != VLC_FOURCC( 's', '1', '6', 'b' ) &&
-        p_enc->format.audio.i_format != VLC_FOURCC( 's', '1', '6', 'l' ) )
+    if( p_enc->fmt_in.i_codec != VLC_FOURCC( 's', '1', '6', 'b' ) &&
+        p_enc->fmt_in.i_codec != VLC_FOURCC( 's', '1', '6', 'l' ) )
     {
         msg_Warn( p_enc, "unhandled input format" );
         return VLC_EGENERIC;
     }
 
-    switch( p_enc->i_fourcc )
+    switch( p_enc->fmt_out.i_codec )
     {
         case VLC_FOURCC( 's', '1', '6', 'b' ):
         case VLC_FOURCC( 's', '1', '6', 'l' ):
@@ -469,11 +428,7 @@ static int  EncoderOpen  ( vlc_object_t *p_this )
     }
 
     p_enc->p_sys = NULL;
-    p_enc->pf_header = NULL;
     p_enc->pf_encode_audio = EncoderEncode;
-    p_enc->pf_encode_video = NULL;
-    p_enc->i_extra_data = 0;
-    p_enc->p_extra_data = NULL;
 
     return VLC_SUCCESS;
 }
@@ -494,21 +449,22 @@ static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
     block_t *p_block = NULL;
     unsigned int i;
 
-    if( p_enc->i_fourcc == p_enc->format.audio.i_format )
+    if( p_enc->fmt_in.i_codec == p_enc->fmt_out.i_codec )
     {
         if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes ) ) )
         {
-            memcpy( p_block->p_buffer, p_aout_buf->p_buffer, p_aout_buf->i_nb_bytes );
+            memcpy( p_block->p_buffer, p_aout_buf->p_buffer,
+                    p_aout_buf->i_nb_bytes );
         }
     }
-    else if( p_enc->i_fourcc == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
+    else if( p_enc->fmt_out.i_codec == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
     {
         if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes / 2 ) ) )
         {
             uint8_t *p_dst = (uint8_t*)p_block->p_buffer;
             int8_t  *p_src = (int8_t*) p_aout_buf->p_buffer;
 
-            if( p_enc->format.audio.i_format == VLC_FOURCC( 's', '1', '6', 'l' ) )
+            if( p_enc->fmt_in.i_codec == VLC_FOURCC( 's', '1', '6', 'l' ) )
             {
                 p_src++;
             }
@@ -519,14 +475,14 @@ static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
             }
         }
     }
-    else if( p_enc->i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) )
+    else if( p_enc->fmt_out.i_codec == VLC_FOURCC( 's', '8', ' ', ' ' ) )
     {
         if( ( p_block = block_New( p_enc, p_aout_buf->i_nb_bytes / 2 ) ) )
         {
             int8_t *p_dst = (int8_t*)p_block->p_buffer;
             int8_t *p_src = (int8_t*)p_aout_buf->p_buffer;
 
-            if( p_enc->format.audio.i_format == VLC_FOURCC( 's', '1', '6', 'l' ) )
+            if( p_enc->fmt_in.i_codec == VLC_FOURCC( 's', '1', '6', 'l' ) )
             {
                 p_src++;
             }
@@ -559,11 +515,9 @@ static block_t *EncoderEncode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
     if( p_block )
     {
         p_block->i_dts = p_block->i_pts = p_aout_buf->start_date;
-        p_block->i_length = (int64_t)p_aout_buf->i_nb_samples * (int64_t)1000000 /
-                            p_enc->format.audio.i_rate;
+        p_block->i_length = (int64_t)p_aout_buf->i_nb_samples *
+            (int64_t)1000000 / p_enc->fmt_in.audio.i_rate;
     }
 
     return p_block;
 }
-
-
index a9ef93b..4a3b8ee 100644 (file)
@@ -2,7 +2,7 @@
  * cinepak.c: cinepak video decoder
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: cinepak.c,v 1.2 2003/10/25 00:49:13 sam Exp $
+ * $Id: cinepak.c,v 1.3 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -71,20 +71,14 @@ struct decoder_sys_t
      * Cinepak properties
      */
     cinepak_context_t *p_context;
-
-    /*
-     * Output properties
-     */
-    vout_thread_t *p_vout;
 };
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int OpenDecoder( vlc_object_t * );
-static int InitDecoder( decoder_t * );
-static int RunDecoder ( decoder_t *, block_t * );
-static int EndDecoder ( decoder_t * );
+static int  OpenDecoder( vlc_object_t * );
+static void CloseDecoder( vlc_object_t * );
+static picture_t *DecodeBlock ( decoder_t *, block_t ** );
 
 static int cinepak_decode_frame( cinepak_context_t *, int, uint8_t * );
 
@@ -94,7 +88,7 @@ static int cinepak_decode_frame( cinepak_context_t *, int, uint8_t * );
 vlc_module_begin();
     set_description( _("Cinepak video decoder") );
     set_capability( "decoder", 70 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 vlc_module_end();
 
 /*****************************************************************************
@@ -106,8 +100,10 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+    vlc_value_t val;
 
-    switch( p_dec->p_fifo->i_fourcc )
+    switch( p_dec->fmt_in.i_codec )
     {
         case VLC_FOURCC('c','v','i','d'):
         case VLC_FOURCC('C','V','I','D'):
@@ -118,30 +114,13 @@ static int OpenDecoder( vlc_object_t *p_this )
     }
 
     /* Allocate the memory needed to store the decoder's structure */
-    if( ( p_dec->p_sys =
+    if( ( p_dec->p_sys = p_sys =
           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
         msg_Err( p_dec, "out of memory" );
         return VLC_EGENERIC;
     }
 
-    p_dec->pf_init = InitDecoder;
-    p_dec->pf_decode = RunDecoder;
-    p_dec->pf_end = EndDecoder;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    vlc_value_t val;
-
-    p_sys->p_vout = NULL;
-
     if( !(p_sys->p_context = malloc( sizeof( cinepak_context_t ) ) ) )
     {
         msg_Err( p_dec, "out of memory" );
@@ -152,57 +131,53 @@ static int InitDecoder( decoder_t *p_dec )
     var_Get( p_dec, "grayscale", &val );
     p_sys->p_context->b_grayscale = val.b_bool;
 
+    p_dec->pf_decode_video = DecodeBlock;
+
     msg_Dbg( p_dec, "cinepak decoder started" );
 
     return VLC_SUCCESS;
 }
 
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function must be fed with whole frames.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     int i_status, i_plane;
     uint8_t *p_dst, *p_src;
     picture_t *p_pic;
+    block_t *p_block;
+
+    if( !pp_block || !*pp_block ) return NULL;
 
-    i_status = cinepak_decode_frame( p_sys->p_context,
-                                     p_block->i_buffer, p_block->p_buffer );
+    p_block = *pp_block;
+
+    i_status = cinepak_decode_frame( p_sys->p_context, p_block->i_buffer,
+                                     p_block->p_buffer );
     if( i_status < 0 )
     {
         msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
                   p_block->i_buffer );
         block_Release( p_block );
-        return VLC_SUCCESS;
+        return NULL;
     }
 
-    /* Check our vout */
-    p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
-                                  p_sys->p_context->i_width,
-                                  p_sys->p_context->i_height,
-                                  VLC_FOURCC('I','4','2','0'),
-                                  p_sys->p_context->i_width
-                                    * VOUT_ASPECT_FACTOR
-                                    / p_sys->p_context->i_height );
-    if( !p_sys->p_vout )
-    {
-        msg_Err( p_dec, "cannot create vout" );
-        block_Release( p_block );
-        return VLC_EGENERIC;
-    }
+    p_dec->fmt_out.video.i_width = p_sys->p_context->i_width;
+    p_dec->fmt_out.video.i_height = p_sys->p_context->i_height;
+    p_dec->fmt_out.video.i_aspect = p_sys->p_context->i_width
+        * VOUT_ASPECT_FACTOR / p_sys->p_context->i_height;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
+
+    /* Get a new picture */
+    p_pic = p_dec->pf_vout_buffer_new( p_dec );
 
-    /* Send decoded frame to vout */
-    while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
+    if( p_pic == NULL )
     {
-        if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
-        {
-            block_Release( p_block );
-            return VLC_EGENERIC;
-        }
-        msleep( VOUT_OUTMEM_SLEEP );
+        block_Release( p_block );
+        return NULL;
     }
 
     for( i_plane = 0; i_plane < 3; i_plane++ )
@@ -224,25 +199,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         }
     }
 
-    vout_DatePicture( p_sys->p_vout, p_pic, p_block->i_pts);
-    vout_DisplayPicture( p_sys->p_vout, p_pic );
-
+    p_pic->date = p_block->i_pts;
     block_Release( p_block );
-    return VLC_SUCCESS;
+
+    return p_pic;
 }
 
 /*****************************************************************************
- * EndDecoder: theora decoder destruction
+ * CloseDecoder: decoder destruction
  *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
     int i;
 
     msg_Dbg( p_dec, "cinepak decoder stopped" );
 
-    vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
-
     for( i = 0; i < 3; i++ )
     {
         if( p_sys->p_context->p_pix[i] ) free( p_sys->p_context->p_pix[i] );
@@ -251,8 +224,6 @@ static int EndDecoder( decoder_t *p_dec )
     free( p_sys->p_context );
 
     free( p_sys );
-
-    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
index 84e41ed..45e72f6 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * dts.c: DTS basic parser
+ * dts.c: parse DTS audio sync info and packetize the stream
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: dts.c,v 1.4 2003/09/02 20:19:25 gbazin Exp $
+ * $Id: dts.c,v 1.5 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Gildas Bazin <gbazin@netcourrier.com>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>                                              /* memcpy() */
-#include <fcntl.h>
 
 #include <vlc/vlc.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
-#include <vlc/aout.h>
-#include <vlc/sout.h>
 
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
+#include "vlc_block_helper.h"
 
 #define DTS_HEADER_SIZE 10
 
@@ -53,48 +48,35 @@ struct decoder_sys_t
     /*
      * Input properties
      */
-    int     i_state;
+    int i_state;
 
-    uint8_t p_header[DTS_HEADER_SIZE];
-    int     i_header;
-
-    mtime_t pts;
-
-    int     i_frame_size;
+    block_bytestream_t bytestream;
 
     /*
-     * Decoder output properties
+     * Common properties
      */
-    aout_instance_t *     p_aout;                                  /* opaque */
-    aout_input_t *        p_aout_input;                            /* opaque */
-    audio_sample_format_t aout_format;
-    aout_buffer_t *       p_aout_buffer; /* current aout buffer being filled */
+    audio_date_t   end_date;
+
+    mtime_t i_pts;
+
+    int i_frame_size, i_bit_rate;
+    unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
+
     /* This is very hacky. For DTS over S/PDIF we apparently need to send
      * 3 frames at a time. This should likely be moved to the output stage. */
-    int                   i_frames_in_buf;
-
-    /*
-     * Packetizer output properties
-     */
-    sout_packetizer_input_t *p_sout_input;
-    sout_format_t           sout_format;
-    sout_buffer_t *         p_sout_buffer;            /* current sout buffer */
+    int i_frames_in_buf;
+    aout_buffer_t *p_aout_buffer;        /* current aout buffer being filled */
 
-    /*
-     * Common properties
-     */
-    uint8_t               *p_out_buffer;                    /* output buffer */
-    int                   i_out_buffer;         /* position in output buffer */
-    audio_date_t          end_date;
 };
 
 enum {
 
     STATE_NOSYNC,
-    STATE_PARTIAL_SYNC,
     STATE_SYNC,
     STATE_HEADER,
-    STATE_DATA
+    STATE_NEXT_SYNC,
+    STATE_GET_DATA,
+    STATE_SEND_DATA
 };
 
 /****************************************************************************
@@ -102,18 +84,15 @@ enum {
  ****************************************************************************/
 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 void CloseDecoder  ( vlc_object_t * );
+static void *DecodeBlock  ( decoder_t *, block_t ** );
 
 static int  SyncInfo      ( const byte_t *, unsigned int *, unsigned int *,
                             unsigned int *, unsigned int *, unsigned int * );
 
-static int GetOutBuffer ( decoder_t *, uint8_t ** );
-static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
-static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
-static int SendOutBuffer( decoder_t * );
+static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
+static aout_buffer_t *GetAoutBuffer( decoder_t * );
+static block_t       *GetSoutBuffer( decoder_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -121,7 +100,7 @@ static int SendOutBuffer( decoder_t * );
 vlc_module_begin();
     set_description( _("DTS parser") );
     set_capability( "decoder", 100 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 
     add_submodule();
     set_description( _("DTS audio packetizer") );
@@ -135,25 +114,39 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','t','s',' ')
-         && p_dec->p_fifo->i_fourcc != VLC_FOURCC('d','t','s','b') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ')
+         && p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
     {
         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 =
+    if( ( p_dec->p_sys = 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;
+
+    /* Misc init */
+    p_sys->b_packetizer = VLC_FALSE;
+    p_sys->i_state = STATE_NOSYNC;
+    aout_DateSet( &p_sys->end_date, 0 );
+    p_sys->i_frames_in_buf = 0;
+
+    p_sys->bytestream = block_BytestreamInit( p_dec );
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('d','t','s',' ');
+
+    /* Set callback */
+    p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
 
     return VLC_SUCCESS;
 }
@@ -169,420 +162,264 @@ static int OpenPacketizer( vlc_object_t *p_this )
     return i_ret;
 }
 
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    p_dec->p_sys->i_state = STATE_NOSYNC;
-
-    p_dec->p_sys->p_out_buffer = NULL;
-    p_dec->p_sys->i_out_buffer = 0;
-    aout_DateSet( &p_dec->p_sys->end_date, 0 );
-
-    p_dec->p_sys->p_aout = NULL;
-    p_dec->p_sys->p_aout_input = NULL;
-    p_dec->p_sys->p_aout_buffer = NULL;
-    p_dec->p_sys->aout_format.i_format = VLC_FOURCC('d','t','s',' ');
-
-    p_dec->p_sys->p_sout_input = NULL;
-    p_dec->p_sys->p_sout_buffer = NULL;
-    p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
-    p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC('d','t','s',' ');
-
-    return VLC_SUCCESS;
-}
-
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function is called just after the thread is launched.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i, i_block_pos = 0;
-    mtime_t i_pts = p_block->i_pts;
+    uint8_t p_header[DTS_HEADER_SIZE];
+    uint8_t *p_buf;
+    void *p_out_buffer;
 
-    while( i_block_pos < p_block->i_buffer )
+    if( !pp_block || !*pp_block ) return NULL;
+
+    if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
+    {
+        /* We've just started the stream, wait for the first PTS. */
+        block_Release( *pp_block );
+        return NULL;
+    }
+
+    if( (*pp_block)->b_discontinuity )
+    {
+        p_sys->i_state = STATE_NOSYNC;
+    }
+
+    block_BytestreamPush( &p_sys->bytestream, *pp_block );
+
+    while( 1 )
     {
         switch( p_sys->i_state )
         {
         case STATE_NOSYNC:
             /* Look for sync dword - should be 0x7ffe8001 */
-            while( i_block_pos < p_block->i_buffer &&
-                   p_block->p_buffer[i_block_pos] != 0x7f )
+            while( block_PeekBytes( &p_sys->bytestream, p_header, 4 )
+                   == VLC_SUCCESS )
             {
-                i_block_pos++;
-            }
-
-            if( i_block_pos < p_block->i_buffer )
-            {
-                p_sys->i_state = STATE_PARTIAL_SYNC;
-                i_block_pos++;
-                p_sys->p_header[0] = 0x7f;
-                p_sys->i_header = 1;
-                break;
-            }
-            break;
-
-        case STATE_PARTIAL_SYNC:
-            /* Get the full 4 sync bytes */
-            if( p_sys->i_header < 4 )
-            {
-                int i_size = __MIN( 4 - p_sys->i_header,
-                                    p_block->i_buffer - i_block_pos );
-
-                memcpy( p_sys->p_header + p_sys->i_header,
-                        p_block->p_buffer + i_block_pos, i_size );
-                i_block_pos += i_size;
-                p_sys->i_header += i_size;
-            }
-
-            if( p_sys->i_header < 4 )
-                break;
-
-            if( p_sys->p_header[0] == 0x7f && p_sys->p_header[1] == 0xfe &&
-                p_sys->p_header[2] == 0x80 && p_sys->p_header[3] == 0x01 )
-            {
-                p_sys->i_state = STATE_SYNC;
-            }
-            else
-            {
-                for( i = 1; i < 4; i++ )
+                if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
+                    p_header[2] == 0x80 && p_header[3] == 0x01 )
                 {
-                    if( p_sys->p_header[i] == 0x7f ) break;
-                }
-
-                if( p_sys->p_header[i] == 0x7f )
-                {
-                    /* Potential new sync */
-                    p_sys->i_header -= i;
-                    memmove( p_sys->p_header, &p_sys->p_header[i],
-                             p_sys->i_header );
+                    p_sys->i_state = STATE_SYNC;
                     break;
                 }
+                block_SkipByte( &p_sys->bytestream );
+            }
+            if( p_sys->i_state != STATE_SYNC )
+            {
+                block_BytestreamFlush( &p_sys->bytestream );
 
-                /* retry to sync*/
-                p_sys->i_state = STATE_NOSYNC;
+                /* Need more data */
+                return NULL;
             }
-            break;
 
         case STATE_SYNC:
             /* New frame, set the Presentation Time Stamp */
-            p_sys->pts = i_pts; i_pts = 0;
-            if( p_sys->pts != 0 &&
-                p_sys->pts != aout_DateGet( &p_sys->end_date ) )
+            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
+            if( p_sys->i_pts != 0 &&
+                p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
             {
-                aout_DateSet( &p_sys->end_date, p_sys->pts );
+                aout_DateSet( &p_sys->end_date, p_sys->i_pts );
             }
             p_sys->i_state = STATE_HEADER;
-            break;
 
         case STATE_HEADER:
             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
-            if( p_sys->i_header < DTS_HEADER_SIZE )
+            if( block_PeekBytes( &p_sys->bytestream, p_header,
+                                 DTS_HEADER_SIZE ) != VLC_SUCCESS )
             {
-                int i_size = __MIN( DTS_HEADER_SIZE - p_sys->i_header,
-                                    p_block->i_buffer - i_block_pos );
-
-                memcpy( p_sys->p_header + p_sys->i_header,
-                        p_block->p_buffer + i_block_pos, i_size );
-                i_block_pos += i_size;
-                p_sys->i_header += i_size;
+                /* Need more data */
+                return NULL;
             }
 
-            if( p_sys->i_header < DTS_HEADER_SIZE )
+            /* Check if frame is valid and get frame info */
+            p_sys->i_frame_size = SyncInfo( p_header,
+                                            &p_sys->i_channels,
+                                            &p_sys->i_channels_conf,
+                                            &p_sys->i_rate,
+                                            &p_sys->i_bit_rate,
+                                            &p_sys->i_frame_length );
+            if( !p_sys->i_frame_size )
+            {
+                msg_Dbg( p_dec, "emulated sync word" );
+                block_SkipByte( &p_sys->bytestream );
+                p_sys->i_state = STATE_NOSYNC;
                 break;
+            }
+            p_sys->i_state = STATE_NEXT_SYNC;
 
-            if( GetOutBuffer( p_dec, &p_sys->p_out_buffer )
+        case STATE_NEXT_SYNC:
+            /* TODO: If pp_block == NULL, flush the buffer without checking the
+             * next sync word */
+
+            /* Check if next expected frame contains the sync word */
+            if( block_PeekOffsetBytes( &p_sys->bytestream,
+                                       p_sys->i_frame_size, p_header, 4 )
                 != VLC_SUCCESS )
             {
-                block_Release( p_block );
-                return VLC_EGENERIC;
+                /* Need more data */
+                return NULL;
             }
 
-            if( !p_sys->p_out_buffer )
+            if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
+                p_header[2] == 0x80 && p_header[3] == 0x01 )
             {
+                msg_Dbg( p_dec, "emulated sync word "
+                         "(no sync on following frame)" );
                 p_sys->i_state = STATE_NOSYNC;
+                block_SkipByte( &p_sys->bytestream );
                 break;
             }
-
-            memcpy( p_sys->p_out_buffer, p_sys->p_header, DTS_HEADER_SIZE );
-            p_sys->i_out_buffer = DTS_HEADER_SIZE;
-            p_sys->i_state = STATE_DATA;
+            p_sys->i_state = STATE_SEND_DATA;
             break;
 
-        case STATE_DATA:
-            /* Copy the whole DTS frame into the aout buffer */
-            if( p_sys->i_out_buffer < p_sys->i_frame_size )
+        case STATE_GET_DATA:
+            /* Make sure we have enough data.
+             * (Not useful if we went through NEXT_SYNC) */
+            if( block_WaitBytes( &p_sys->bytestream,
+                                 p_sys->i_frame_size ) != VLC_SUCCESS )
             {
-                int i_size = __MIN( p_sys->i_frame_size - p_sys->i_out_buffer,
-                                    p_block->i_buffer - i_block_pos );
-
-                memcpy( p_sys->p_out_buffer + p_sys->i_out_buffer,
-                        p_block->p_buffer + i_block_pos, i_size );
-                i_block_pos += i_size;
-                p_sys->i_out_buffer += i_size;
+                /* Need more data */
+                return NULL;
             }
+            p_sys->i_state = STATE_SEND_DATA;
 
-            if( p_sys->i_out_buffer < p_sys->i_frame_size )
-                break; /* Need more data */
+        case STATE_SEND_DATA:
+            if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
+            {
+                //p_dec->b_error = VLC_TRUE;
+                return NULL;
+            }
 
-            SendOutBuffer( p_dec );
+            /* Copy the whole frame into the buffer. When we reach this point
+             * we already know we have enough data available. */
+            block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
 
-            p_sys->i_state = STATE_NOSYNC;
-            break;
-        }
-    }
+            /* Make sure we don't reuse the same pts twice */
+            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
+                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
 
-    block_Release( p_block );
-    return VLC_SUCCESS;
-}
+            /* So p_block doesn't get re-added several times */
+            *pp_block = block_BytestreamPop( &p_sys->bytestream );
 
-/*****************************************************************************
- * EndDecoder: clean up the decoder
- *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
-{
-    if( p_dec->p_sys->p_aout_input != NULL )
-    {
-        if( p_dec->p_sys->p_aout_buffer )
-        {
-            aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
-                                  p_dec->p_sys->p_aout_input,
-                                  p_dec->p_sys->p_aout_buffer );
-        }
+            p_sys->i_state = STATE_NOSYNC;
 
-        aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
-    }
+            if( !p_sys->b_packetizer )
+            {
+                if( p_sys->i_frames_in_buf != 3 ) return NULL;
+                else
+                {
+                    p_sys->i_frames_in_buf = 0;
+                    p_sys->p_aout_buffer = 0;
+                }
+            }
 
-    if( p_dec->p_sys->p_sout_input != NULL )
-    {
-        if( p_dec->p_sys->p_sout_buffer )
-        {
-            sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
-                               p_dec->p_sys->p_sout_buffer );
+            return p_out_buffer;
         }
-
-        sout_InputDelete( p_dec->p_sys->p_sout_input );
     }
 
-    free( p_dec->p_sys );
-
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
- * GetOutBuffer:
+ * CloseDecoder: clean up the decoder
  *****************************************************************************/
-static int GetOutBuffer ( decoder_t *p_dec, uint8_t **pp_out_buffer )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i_ret;
 
-    if( p_sys->b_packetizer )
-    {
-        i_ret= GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
-        *pp_out_buffer =
-            p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
-    }
-    else
-    {
-        i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
-        if( p_sys->i_frames_in_buf == 1 )
-            *pp_out_buffer = p_sys->p_aout_buffer ?
-                p_sys->p_aout_buffer->p_buffer : NULL;
-       else
-            *pp_out_buffer = p_sys->p_aout_buffer ?
-                p_sys->p_aout_buffer->p_buffer + p_sys->i_frame_size *
-                (p_sys->i_frames_in_buf - 1) : NULL;
-    }
+    block_BytestreamRelease( &p_sys->bytestream );
 
-    return i_ret;
+    free( p_sys );
 }
 
 /*****************************************************************************
- * GetAoutBuffer:
+ * GetOutBuffer:
  *****************************************************************************/
-static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
+static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
 {
-    int i_bit_rate;
-    unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
-
     decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p_buf;
 
-    /* Check if frame is valid and get frame info */
-    p_sys->i_frame_size = SyncInfo( p_sys->p_header,
-                                    &i_channels, &i_channels_conf,
-                                    &i_rate, &i_bit_rate, &i_frame_length );
-
-    if( !p_sys->i_frame_size )
+    if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
     {
-        msg_Warn( p_dec, "dts syncinfo failed" );
-        *pp_buffer = NULL;
-        return VLC_SUCCESS;
-    }
+        msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
+                  p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
 
-    if( p_sys->p_aout_input != NULL && ( p_sys->aout_format.i_rate != i_rate
-        || p_sys->aout_format.i_original_channels != i_channels_conf
-        || (int)p_sys->aout_format.i_bytes_per_frame != p_sys->i_frame_size ) )
-    {
-        /* Parameters changed - this should not happen. */
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-        p_sys->p_aout_input = NULL;
+        aout_DateInit( &p_sys->end_date, p_sys->i_rate );
+        aout_DateSet( &p_sys->end_date, p_sys->i_pts );
     }
 
-    /* Creating the audio input if not created yet. */
-    if( p_sys->p_aout_input == NULL )
-    {
-        p_sys->aout_format.i_rate = i_rate;
-        p_sys->aout_format.i_original_channels = i_channels_conf;
-        p_sys->aout_format.i_physical_channels
-            = i_channels_conf & AOUT_CHAN_PHYSMASK;
-        p_sys->aout_format.i_bytes_per_frame = p_sys->i_frame_size;
-        p_sys->aout_format.i_frame_length = i_frame_length;
-        aout_DateInit( &p_sys->end_date, i_rate );
-        aout_DateSet( &p_sys->end_date, p_sys->pts );
-        p_sys->i_frames_in_buf = 3;
-        p_sys->p_aout_input = aout_DecNew( p_dec,
-                                           &p_sys->p_aout,
-                                           &p_sys->aout_format );
-
-        if ( p_sys->p_aout_input == NULL )
-        {
-            *pp_buffer = NULL;
-            return VLC_SUCCESS;
-        }
-    }
+    p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
+    p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
+    p_dec->fmt_out.audio.i_bitrate  = p_sys->i_bit_rate;
+    p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
+    p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
+
+    p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
 
-    if( !aout_DateGet( &p_sys->end_date ) )
+    if( p_sys->b_packetizer )
     {
-        /* We've just started the stream, wait for the first PTS. */
-        *pp_buffer = NULL;
-        return VLC_SUCCESS;
+        block_t *p_sout_buffer = GetSoutBuffer( p_dec );
+        p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
+        *pp_out_buffer = p_sout_buffer;
     }
-
-    if( p_sys->i_frames_in_buf == 3 )
+    else
     {
-        p_sys->i_frames_in_buf = 0;
-        *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
-                                        i_frame_length * 3 );
-        if( *pp_buffer == NULL )
+        if( !p_sys->i_frames_in_buf )
         {
-            return VLC_SUCCESS;
+            p_sys->p_aout_buffer = GetAoutBuffer( p_dec );
         }
-
-        (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
-        (*pp_buffer)->end_date =
-             aout_DateIncrement( &p_sys->end_date, i_frame_length * 3 );
+        p_buf = p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer +
+            p_sys->i_frames_in_buf * p_sys->i_frame_size : NULL;
+        *pp_out_buffer = p_sys->p_aout_buffer;
     }
 
     p_sys->i_frames_in_buf++;
 
-    return VLC_SUCCESS;
+    return p_buf;
 }
 
 /*****************************************************************************
- * GetSoutBuffer:
+ * GetAoutBuffer:
  *****************************************************************************/
-static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
+static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
 {
-    int i_bit_rate;
-    unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
-
     decoder_sys_t *p_sys = p_dec->p_sys;
+    aout_buffer_t *p_buf;
 
-    /* Check if frame is valid and get frame info */
-    p_sys->i_frame_size = SyncInfo( p_sys->p_header,
-                                    &i_channels, &i_channels_conf,
-                                    &i_rate, &i_bit_rate, &i_frame_length );
-
-    if( !p_sys->i_frame_size )
-    {
-        msg_Warn( p_dec, "dts syncinfo failed" );
-        *pp_buffer = NULL;
-        return VLC_SUCCESS;
-    }
-
-    if( p_sys->p_sout_input != NULL &&
-        ( p_sys->sout_format.i_sample_rate != (int)i_rate
-          || p_sys->sout_format.i_channels != (int)i_channels ) )
-    {
-        /* Parameters changed - this should not happen. */
-    }
-
-    /* Creating the sout input if not created yet. */
-    if( p_sys->p_sout_input == NULL )
-    {
-        p_sys->sout_format.i_sample_rate = i_rate;
-        p_sys->sout_format.i_channels    = i_channels;
-        p_sys->sout_format.i_block_align = 0;
-        p_sys->sout_format.i_bitrate     = i_bit_rate;
-        p_sys->sout_format.i_extra_data  = 0;
-        p_sys->sout_format.p_extra_data  = NULL;
-
-        aout_DateInit( &p_sys->end_date, i_rate );
-        aout_DateSet( &p_sys->end_date, p_sys->pts );
-
-        p_sys->p_sout_input = sout_InputNew( p_dec,
-                                             &p_sys->sout_format );
-
-        if( p_sys->p_sout_input == NULL )
-        {
-            msg_Err( p_dec, "cannot add a new stream" );
-            *pp_buffer = NULL;
-            return VLC_EGENERIC;
-        }
-        msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
-                  i_channels, i_rate, i_bit_rate );
-    }
-
-    if( !aout_DateGet( &p_sys->end_date ) )
-    {
-        /* We've just started the stream, wait for the first PTS. */
-        *pp_buffer = NULL;
-        return VLC_SUCCESS;
-    }
-
-    *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
-                                 p_sys->i_frame_size );
-    if( *pp_buffer == NULL )
-    {
-        return VLC_SUCCESS;
-    }
-
-    (*pp_buffer)->i_pts =
-        (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
+    p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 );
+    if( p_buf == NULL ) return NULL;
 
-    (*pp_buffer)->i_length =
-        aout_DateIncrement( &p_sys->end_date, i_frame_length )
-        - (*pp_buffer)->i_pts;
+    p_buf->start_date = aout_DateGet( &p_sys->end_date );
+    p_buf->end_date =
+        aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 );
 
-    return VLC_SUCCESS;
+    return p_buf;
 }
 
 /*****************************************************************************
- * SendOutBuffer:
+ * GetSoutBuffer:
  *****************************************************************************/
-static int SendOutBuffer( decoder_t *p_dec )
+static block_t *GetSoutBuffer( decoder_t *p_dec )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
 
-    if( p_sys->b_packetizer )
-    {
-        sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
-        p_sys->p_sout_buffer = NULL;
-    }
-    else if( p_sys->i_frames_in_buf == 3 )
-    {
-        /* We have all we need, send the buffer to the aout core. */
-        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
-                      p_sys->p_aout_buffer );
-        p_sys->p_aout_buffer = NULL;
-    }
+    p_block = block_New( p_dec, p_sys->i_frame_size );
+    if( p_block == NULL ) return NULL;
 
-    return VLC_SUCCESS;
+    p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
+
+    p_block->i_length = aout_DateIncrement( &p_sys->end_date,
+        p_sys->i_frame_length ) - p_block->i_pts;
+
+    return p_block;
 }
 
 /*****************************************************************************
index d84b1a7..5f9acf9 100644 (file)
@@ -2,7 +2,7 @@
  * dv.c: a decoder for DV video
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: dv.c,v 1.5 2003/09/02 20:19:25 gbazin Exp $
+ * $Id: dv.c,v 1.6 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -59,7 +59,7 @@ 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('d','v','s','d') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','s','d') )
     {
         return VLC_EGENERIC;
     }
index f561f96..2a3f2d2 100644 (file)
@@ -2,7 +2,7 @@
  * dvbsub.c : DVB subtitles decoder thread
  *****************************************************************************
  * Copyright (C) 2003 ANEVIA
- * $Id: dvbsub.c,v 1.2 2003/11/06 19:35:05 nitrox Exp $
+ * $Id: dvbsub.c,v 1.3 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Damien LUCAS <damien.lucas@anevia.com>
  *
@@ -275,7 +275,7 @@ vlc_module_end();
 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('d','v','b','s') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','b','s') )
     {
         return VLC_EGENERIC;
     }
index ae96b4b..a6000b4 100644 (file)
@@ -2,7 +2,7 @@
  * decoder.c: AAC decoder using libfaad2
  *****************************************************************************
  * Copyright (C) 2001, 2003 VideoLAN
- * $Id: faad.c,v 1.3 2003/11/05 01:47:40 fenrir Exp $
+ * $Id: faad.c,v 1.4 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * Module descriptor
  *****************************************************************************/
 static int  Open( vlc_object_t * );
+static void CloseDecoder( vlc_object_t * );
 
 vlc_module_begin();
     set_description( _("AAC audio decoder (using libfaad2)") );
     set_capability( "decoder", 60 );
-    set_callbacks( Open, NULL );
+    set_callbacks( Open, CloseDecoder );
 vlc_module_end();
 
 
 /****************************************************************************
  * Local prototypes
  ****************************************************************************/
-static int  InitDecoder   ( decoder_t * );
-static int  RunDecoder    ( decoder_t *, block_t * );
-static int  EndDecoder    ( decoder_t * );
+static aout_buffer_t *DecodeBlock( decoder_t *, block_t ** );
 
 struct decoder_sys_t
 {
     /* faad handler */
     faacDecHandle *hfaad;
 
-    /* audio output */
-    audio_sample_format_t output_format;
-    aout_instance_t *     p_aout;                                  /* opaque */
-    aout_input_t *        p_aout_input;                            /* opaque */
-
     /* samples */
-    audio_date_t          date;
+    audio_date_t date;
 
     /* temporary buffer */
-    uint8_t               *p_buffer;
-    int                   i_buffer;
-    int                   i_buffer_size;
+    uint8_t *p_buffer;
+    int     i_buffer;
+    int     i_buffer_size;
 };
 
-/*****************************************************************************
- * OpenDecoder: probe the decoder and return score
- *****************************************************************************/
-static int  Open( vlc_object_t *p_this )
-{
-    decoder_t *p_dec = (decoder_t*)p_this;
-
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','4','a') )
-    {
-        return VLC_EGENERIC;
-    }
-
-    p_dec->pf_init = InitDecoder;
-    p_dec->pf_decode = RunDecoder;
-    p_dec->pf_end = EndDecoder;
-
-    p_dec->p_sys  = malloc( sizeof( decoder_sys_t ) );
-
-    return VLC_SUCCESS;
-}
-
 static unsigned int pi_channels_maps[7] =
 {
     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,
+    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,
      /* FIXME */
-    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARCENTER
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
+        AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARCENTER
 };
 
 /*****************************************************************************
- * InitDecoder:
+ * OpenDecoder: probe the decoder and return score
  *****************************************************************************/
-static int  InitDecoder   ( decoder_t *p_dec )
+static int Open( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
-    WAVEFORMATEX    wf, *p_wf;
     faacDecConfiguration *cfg;
 
-    if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','4','a') )
     {
-        p_wf = &wf;
-        memset( p_wf, 0, sizeof( WAVEFORMATEX ) );
+        return VLC_EGENERIC;
+    }
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+    {
+        msg_Err( p_dec, "out of memory" );
+        return VLC_EGENERIC;
     }
 
     /* Open a faad context */
@@ -123,37 +106,43 @@ static int  InitDecoder   ( decoder_t *p_dec )
         return VLC_EGENERIC;
     }
 
-    if( p_wf->cbSize > 0 )
+    /* Misc init */
+    aout_DateSet( &p_sys->date, 0 );
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
+    p_dec->pf_decode_audio = DecodeBlock;
+
+    if( p_dec->fmt_in.i_extra > 0 )
     {
         /* We have a decoder config so init the handle */
-        unsigned long   i_rate;
-        unsigned char   i_channels;
+        unsigned long i_rate;
+        unsigned char i_channels;
 
-        if( faacDecInit2( p_sys->hfaad,
-                          (uint8_t*)&p_wf[1], p_wf->cbSize,
+        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
+                          p_dec->fmt_in.i_extra,
                           &i_rate, &i_channels ) < 0 )
         {
             return VLC_EGENERIC;
         }
 
-        p_sys->output_format.i_rate = i_rate;
-        p_sys->output_format.i_physical_channels =
-        p_sys->output_format.i_original_channels =
-            pi_channels_maps[i_channels];
+        p_dec->fmt_out.audio.i_rate = i_rate;
+        p_dec->fmt_out.audio.i_channels = i_channels;
+        p_dec->fmt_out.audio.i_physical_channels =
+            p_dec->fmt_out.audio.i_original_channels =
+                pi_channels_maps[i_channels];
+
+        aout_DateInit( &p_sys->date, i_rate );
     }
     else
     {
         /* Will be initalised from first frame */
-        p_sys->output_format.i_rate = 0;
-        p_sys->output_format.i_physical_channels =
-        p_sys->output_format.i_original_channels = 0;
+        p_dec->fmt_out.audio.i_rate = 0;
+        p_dec->fmt_out.audio.i_channels = 0;
+        p_dec->fmt_out.audio.i_physical_channels =
+            p_dec->fmt_out.audio.i_original_channels = 0;
     }
-    p_sys->output_format.i_format = VLC_FOURCC('f','l','3','2');
-
-    p_sys->p_aout = NULL;
-    p_sys->p_aout_input = NULL;
 
-    /* set the faad config */
+    /* Set the faad config */
     cfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
     cfg->outputFormat = FAAD_FMT_FLOAT;
     faacDecSetConfiguration( p_sys->hfaad, cfg );
@@ -167,28 +156,36 @@ static int  InitDecoder   ( decoder_t *p_dec )
 }
 
 /*****************************************************************************
- * InitDecoder:
+ * DecodeBlock:
  *****************************************************************************/
-static int  RunDecoder    ( decoder_t *p_dec, block_t *p_block )
+static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
 
-    int          i_used = 0;
-    mtime_t      i_pts = p_block->i_pts;
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
 
     /* Append the block to the temporary buffer */
     if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
     {
-        p_sys->i_buffer_size += p_block->i_buffer;
+        p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
         p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
     }
-    memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer );
-    p_sys->i_buffer += p_block->i_buffer;
 
-    if( p_sys->output_format.i_rate == 0 )
+    if( p_block->i_buffer )
+    {
+        memcpy( &p_sys->p_buffer[p_sys->i_buffer],
+                p_block->p_buffer, p_block->i_buffer );
+        p_sys->i_buffer += p_block->i_buffer;
+        p_block->i_buffer = 0;
+    }
+
+    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
     {
-        unsigned long   i_rate;
-        unsigned char   i_channels;
+        unsigned long i_rate;
+        unsigned char i_channels;
 
         /* Init faad with the first frame */
         if( faacDecInit( p_sys->hfaad,
@@ -196,137 +193,121 @@ static int  RunDecoder    ( decoder_t *p_dec, block_t *p_block )
                          &i_rate, &i_channels ) < 0 )
         {
             block_Release( p_block );
-            return VLC_EGENERIC;
+            return NULL;
         }
-        p_sys->output_format.i_rate = i_rate;
-        p_sys->output_format.i_physical_channels =
-        p_sys->output_format.i_original_channels =
-            pi_channels_maps[i_channels];
+
+        p_dec->fmt_out.audio.i_rate = i_rate;
+        p_dec->fmt_out.audio.i_channels = i_channels;
+        p_dec->fmt_out.audio.i_physical_channels =
+            p_dec->fmt_out.audio.i_original_channels =
+                pi_channels_maps[i_channels];
+
+        aout_DateInit( &p_sys->date, i_rate );
+    }
+
+    if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) )
+    {
+        aout_DateSet( &p_sys->date, p_block->i_pts );
+    }
+    else if( !aout_DateGet( &p_sys->date ) )
+    {
+        /* We've just started the stream, wait for the first PTS. */
+        block_Release( p_block );
+        p_sys->i_buffer = 0;
+        return NULL;
     }
 
     /* Decode all data */
-    while( i_used < p_sys->i_buffer )
+    if( p_sys->i_buffer )
     {
         void *samples;
         faacDecFrameInfo frame;
-        aout_buffer_t   *out;
+        aout_buffer_t *p_out;
 
         samples = faacDecDecode( p_sys->hfaad, &frame,
-                                 &p_sys->p_buffer[i_used], p_sys->i_buffer - i_used );
+                                 p_sys->p_buffer, p_sys->i_buffer );
 
         if( frame.error > 0 )
         {
             msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );
-            /* flush the buffer */
+
+            /* Flush the buffer */
             p_sys->i_buffer = 0;
             block_Release( p_block );
-            return VLC_SUCCESS;
+            return NULL;
         }
+
         if( frame.channels <= 0 || frame.channels > 6 )
         {
             msg_Warn( p_dec, "invalid channels count" );
-            /* flush the buffer */
+
+            /* Flush the buffer */
             p_sys->i_buffer = 0;
             block_Release( p_block );
-            return VLC_SUCCESS;
+            return NULL;
         }
+
         if( frame.samples <= 0 )
         {
             msg_Warn( p_dec, "decoded zero samples" );
-            /* flush the buffer */
+
+            /* Flush the buffer */
             p_sys->i_buffer = 0;
             block_Release( p_block );
-            return VLC_SUCCESS;
+            return NULL;
         }
 
-        /* we have decoded a valid frame */
-        /* msg_Dbg( p_dec, "consumed %d for %dHz %dc %lld", frame.bytesconsumed, frame.samplerate, frame.channels, i_pts ); */
-        i_used += frame.bytesconsumed;
-
-
-        /* create/recreate the output */
-        if( p_sys->p_aout_input &&
-            ( p_sys->output_format.i_original_channels != pi_channels_maps[frame.channels] ||
-              p_sys->output_format.i_rate != frame.samplerate ) )
+        /* We decoded a valid frame */
+        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
         {
-            aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-            p_sys->p_aout_input = NULL;
+            aout_DateInit( &p_sys->date, frame.samplerate );
+            aout_DateSet( &p_sys->date, p_block->i_pts );
         }
+        p_block->i_pts = 0;  /* PTS is valid only once */
 
-        if( p_sys->p_aout_input == NULL )
-        {
-            p_sys->output_format.i_physical_channels =
-            p_sys->output_format.i_original_channels = pi_channels_maps[frame.channels];
-            p_sys->output_format.i_rate = frame.samplerate;
-
-            aout_DateInit( &p_sys->date, p_sys->output_format.i_rate );
-            aout_DateSet( &p_sys->date, 0 );
-
-            p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->output_format );
-        }
+        p_dec->fmt_out.audio.i_rate = frame.samplerate;
+        p_dec->fmt_out.audio.i_channels = frame.channels;
+        p_dec->fmt_out.audio.i_physical_channels =
+            p_dec->fmt_out.audio.i_original_channels =
+                pi_channels_maps[frame.channels];
 
-        if( p_sys->p_aout_input == NULL )
+        p_out = p_dec->pf_aout_buffer_new( p_dec,
+                                           frame.samples / frame.channels );
+        if( p_out == NULL )
         {
-            msg_Err( p_dec, "cannot create aout" );
+            p_sys->i_buffer = 0;
             block_Release( p_block );
-            return VLC_EGENERIC;
+            return NULL;
         }
 
-        if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->date ) )
-        {
-            aout_DateSet( &p_sys->date, i_pts );
-        }
-        else if( !aout_DateGet( &p_sys->date ) )
-        {
-            /* Wait for a dated packet */
-            msg_Dbg( p_dec, "no date" );
-            p_sys->i_buffer = 0;
-            return VLC_SUCCESS;
-        }
-        i_pts = 0;  /* PTS is valid only once */
+        p_out->start_date = aout_DateGet( &p_sys->date );
+        p_out->end_date = aout_DateIncrement( &p_sys->date,
+                                              frame.samples / frame.channels );
+
+        memcpy( p_out->p_buffer, samples, p_out->i_nb_bytes );
 
-        if( ( out = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
-                                       frame.samples / frame.channels ) ) == NULL )
+        p_sys->i_buffer -= frame.bytesconsumed;
+        if( p_sys->i_buffer > 0 )
         {
-            msg_Err( p_dec, "cannot get a new buffer" );
-            block_Release( p_block );
-            return VLC_EGENERIC;
+            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
+                     p_sys->i_buffer );
         }
-        out->start_date = aout_DateGet( &p_sys->date );
-        out->end_date   = aout_DateIncrement( &p_sys->date,
-                                              frame.samples / frame.channels );
-        memcpy( out->p_buffer, samples, out->i_nb_bytes );
-
-        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out );
-    }
 
-    p_sys->i_buffer -= i_used;
-    if( p_sys->i_buffer > 0 )
-    {
-        memmove( &p_sys->p_buffer[0], &p_sys->p_buffer[i_used], p_sys->i_buffer );
+        return p_out;
     }
 
     block_Release( p_block );
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
- * InitDecoder:
+ * CloseDecoder:
  *****************************************************************************/
-static int  EndDecoder    ( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_sys->p_aout_input )
-    {
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-    }
-
     faacDecClose( p_sys->hfaad );
     free( p_sys );
-
-    return VLC_SUCCESS;
 }
-
-
-
index df9191f..b50f0c1 100644 (file)
@@ -2,7 +2,7 @@
  * audio.c: audio decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2003 VideoLAN
- * $Id: audio.c,v 1.21 2003/10/27 10:00:40 gbazin Exp $
+ * $Id: audio.c,v 1.22 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
 #include <string.h>
 
 #include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/aout.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>                                              /* getpid() */
-#endif
-
-#ifdef HAVE_SYS_TIMES_H
-#   include <sys/times.h>
-#endif
-
 #include "codecs.h"
 #include "aout_internal.h"
 
@@ -83,8 +73,6 @@ struct decoder_sys_t
     /*
      * Output properties
      */
-    aout_instance_t       *p_aout;
-    aout_input_t          *p_aout_input;
     audio_sample_format_t aout_format;
     audio_date_t          end_date;
 };
@@ -98,7 +86,6 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
                       AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
 {
     decoder_sys_t *p_sys;
-    WAVEFORMATEX wf, *p_wf;
 
     /* Allocate the memory needed to store the decoder's structure */
     if( ( p_dec->p_sys = p_sys =
@@ -113,25 +100,19 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
     p_dec->p_sys->i_codec_id = i_codec_id;
     p_dec->p_sys->psz_namecodec = psz_namecodec;
 
-    if( ( p_wf = p_dec->p_fifo->p_waveformatex ) == NULL )
-    {
-        msg_Warn( p_dec, "audio informations missing" );
-        p_wf = &wf;
-        memset( p_wf, 0, sizeof( WAVEFORMATEX ) );
-    }
-
     /* ***** Fill p_context with init values ***** */
-    p_sys->p_context->sample_rate = p_wf->nSamplesPerSec;
-    p_sys->p_context->channels = p_wf->nChannels;
-    p_sys->p_context->block_align = p_wf->nBlockAlign;
-    p_sys->p_context->bit_rate = p_wf->nAvgBytesPerSec * 8;
+    p_sys->p_context->sample_rate = p_dec->fmt_in.audio.i_rate;
+    p_sys->p_context->channels = p_dec->fmt_in.audio.i_channels;
+    p_sys->p_context->block_align = p_dec->fmt_in.audio.i_blockalign;
+    p_sys->p_context->bit_rate = p_dec->fmt_in.i_bitrate;
 
-    if( ( p_sys->p_context->extradata_size = p_wf->cbSize ) > 0 )
+    if( ( p_sys->p_context->extradata_size = p_dec->fmt_in.i_extra ) > 0 )
     {
         p_sys->p_context->extradata =
-            malloc( p_wf->cbSize + FF_INPUT_BUFFER_PADDING_SIZE );
-        memcpy( p_sys->p_context->extradata, &p_wf[1], p_wf->cbSize);
-        memset( &((uint8_t*)p_sys->p_context->extradata)[p_wf->cbSize], 0,
+            malloc( p_dec->fmt_in.i_extra + FF_INPUT_BUFFER_PADDING_SIZE );
+        memcpy( p_sys->p_context->extradata,
+                p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
+        memset( p_sys->p_context->extradata + p_dec->fmt_in.i_extra, 0,
                 FF_INPUT_BUFFER_PADDING_SIZE );
     }
 
@@ -148,131 +129,106 @@ int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
 
     p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
 
-    p_sys->p_aout = NULL;
-    p_sys->p_aout_input = NULL;
-
     aout_DateSet( &p_sys->end_date, 0 );
 
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
+
     return VLC_SUCCESS;
 }
 
 /*****************************************************************************
  * DecodeAudio: Called to decode one frame
  *****************************************************************************/
-int E_( DecodeAudio )( decoder_t *p_dec, block_t *p_block )
+aout_buffer_t *E_( DecodeAudio )( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    aout_buffer_t *p_aout_buffer;
-    mtime_t i_pts;
+    int i_used, i_output, i_samples;
+    uint8_t *p_samples;
+    aout_buffer_t *p_buffer;
+    block_t *p_block;
+
+    if( !pp_block || !*pp_block ) return NULL;
 
-    uint8_t *p_buffer, *p_samples;
-    int i_buffer, i_samples;
+    p_block = *pp_block;
 
     if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
     {
         /* We've just started the stream, wait for the first PTS. */
         block_Release( p_block );
-        return VLC_SUCCESS;
+        return NULL;
     }
 
-    i_pts = p_block->i_pts;
-    i_buffer = p_block->i_buffer;
-    p_buffer = p_block->p_buffer;
-
-    while( i_buffer )
+    if( !p_block->i_buffer )
     {
-        int i_used, i_output;
+        block_Release( p_block );
+        return NULL;
+    }
 
-        i_used = avcodec_decode_audio( p_sys->p_context,
-                                       (int16_t*)p_sys->p_output, &i_output,
-                                       p_buffer, i_buffer );
+    i_used = avcodec_decode_audio( p_sys->p_context,
+                                   (int16_t*)p_sys->p_output, &i_output,
+                                   p_block->p_buffer, p_block->i_buffer );
+
+    if( i_used < 0 )//|| i_output == 0 )
+    {
         if( i_used < 0 )
-        {
-            msg_Warn( p_dec, "cannot decode one frame (%d bytes)", i_buffer );
-            break;
-        }
-
-        i_buffer -= i_used;
-        p_buffer += i_used;
-
-        if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
-        {
-            msg_Warn( p_dec, "invalid channels count %d",
-                      p_sys->p_context->channels );
-            break;
-        }
-
-        /* **** First check if we have a valid output **** */
-        if( p_sys->p_aout_input == NULL ||
-            p_sys->aout_format.i_original_channels !=
-            pi_channels_maps[p_sys->p_context->channels] )
-        {
-            if( p_sys->p_aout_input != NULL )
-            {
-                /* **** Delete the old **** */
-                aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-            }
-
-            /* **** Create a new audio output **** */
-            p_sys->aout_format.i_format = AOUT_FMT_S16_NE;
-            p_sys->aout_format.i_rate = p_sys->p_context->sample_rate;
-            p_sys->aout_format.i_physical_channels =
-                p_sys->aout_format.i_original_channels =
-                    pi_channels_maps[p_sys->p_context->channels];
-
-            aout_DateInit( &p_sys->end_date, p_sys->aout_format.i_rate );
-            p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout,
-                                               &p_sys->aout_format );
-        }
-
-        if( !p_sys->p_aout_input )
-        {
-            msg_Err( p_dec, "cannot create audio output" );
-            block_Release( p_block );
-            return VLC_EGENERIC;
-        }
-
-        if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->end_date ) )
-        {
-            aout_DateSet( &p_sys->end_date, i_pts );
-            i_pts = 0;
-        }
-
-        /* **** Now we can output these samples **** */
-        i_samples = i_output / 2 / p_sys->p_context->channels;
-
-        p_samples = p_sys->p_output;
-        while( i_samples > 0 )
-        {
-            int i_smaller_samples;
-
-            i_smaller_samples = __MIN( 8000, i_samples );
-
-            p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout,
-                                               p_sys->p_aout_input,
-                                               i_smaller_samples );
-            if( !p_aout_buffer )
-            {
-                msg_Err( p_dec, "cannot get aout buffer" );
-                block_Release( p_block );
-                return VLC_EGENERIC;
-            }
-
-            p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
-            p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
-                                                          i_smaller_samples );
-            memcpy( p_aout_buffer->p_buffer, p_samples,
-                    p_aout_buffer->i_nb_bytes );
-
-            aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer );
-
-            p_samples += i_smaller_samples * 2 * p_sys->p_context->channels;
-            i_samples -= i_smaller_samples;
-        }
+            msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
+                      p_block->i_buffer );
+
+        block_Release( p_block );
+        return NULL;
     }
 
-    block_Release( p_block );
-    return VLC_SUCCESS;
+    p_block->i_buffer -= i_used;
+    p_block->p_buffer += i_used;
+
+    if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
+    {
+        msg_Warn( p_dec, "invalid channels count %d",
+                  p_sys->p_context->channels );
+        block_Release( p_block );
+        return NULL;
+    }
+
+    if( p_dec->fmt_out.audio.i_rate != p_sys->p_context->sample_rate )
+    {
+        aout_DateInit( &p_sys->end_date, p_sys->p_context->sample_rate );
+        aout_DateSet( &p_sys->end_date, p_block->i_pts );
+    }
+
+    /* **** Set audio output parameters **** */
+    p_dec->fmt_out.audio.i_rate     = p_sys->p_context->sample_rate;
+    p_dec->fmt_out.audio.i_channels = p_sys->p_context->channels;
+    p_dec->fmt_out.audio.i_original_channels =
+        p_dec->fmt_out.audio.i_physical_channels =
+            pi_channels_maps[p_sys->p_context->channels];
+
+    if( p_block->i_pts != 0 &&
+        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
+    {
+        aout_DateSet( &p_sys->end_date, p_block->i_pts );
+        p_block->i_pts = 0;
+    }
+
+    /* **** Now we can output these samples **** */
+    i_samples = i_output / 2 / p_sys->p_context->channels;
+    p_samples = p_sys->p_output;
+
+    p_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );
+    if( !p_buffer )
+    {
+        msg_Err( p_dec, "cannot get aout buffer" );
+        block_Release( p_block );
+        return NULL;
+    }
+
+    p_buffer->start_date = aout_DateGet( &p_sys->end_date );
+    p_buffer->end_date = aout_DateIncrement( &p_sys->end_date, i_samples );
+
+    memcpy( p_buffer->p_buffer, p_samples, p_buffer->i_nb_bytes );
+
+    return p_buffer;
 }
 
 /*****************************************************************************
@@ -283,9 +239,4 @@ void E_(EndAudioDec)( decoder_t *p_dec )
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     if( p_sys->p_output ) free( p_sys->p_output );
-
-    if( p_sys->p_aout_input )
-    {
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-    }
 }
index 72da933..fa3c307 100644 (file)
@@ -2,7 +2,7 @@
  * encoder.c: video and audio encoder using the ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: encoder.c,v 1.6 2003/11/05 23:32:31 hartman Exp $
+ * $Id: encoder.c,v 1.7 2003/11/16 21:07:31 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-int  E_(OpenVideoEncoder) ( vlc_object_t * );
-void E_(CloseVideoEncoder)( vlc_object_t * );
-
-int  E_(OpenAudioEncoder) ( vlc_object_t * );
-void E_(CloseAudioEncoder)( vlc_object_t * );
+int  E_(OpenEncoder) ( vlc_object_t * );
+void E_(CloseEncoder)( vlc_object_t * );
 
 static block_t *EncodeVideo( encoder_t *, picture_t * );
 static block_t *EncodeAudio( encoder_t *, aout_buffer_t * );
@@ -92,29 +89,35 @@ struct encoder_sys_t
 };
 
 /*****************************************************************************
- * OpenVideoEncoder: probe the encoder
+ * OpenEncoder: probe the encoder
  *****************************************************************************/
-int E_(OpenVideoEncoder)( vlc_object_t *p_this )
+int E_(OpenEncoder)( vlc_object_t *p_this )
 {
     encoder_t *p_enc = (encoder_t *)p_this;
     encoder_sys_t *p_sys = p_enc->p_sys;
-    AVCodecContext  *p_context;
+    AVCodecContext *p_context;
     AVCodec *p_codec;
     int i_codec_id, i_cat;
     char *psz_namecodec;
 
-    if( !E_(GetFfmpegCodec)( p_enc->i_fourcc, &i_cat, &i_codec_id,
+    if( !E_(GetFfmpegCodec)( p_enc->fmt_out.i_codec, &i_cat, &i_codec_id,
                              &psz_namecodec ) )
     {
         return VLC_EGENERIC;
     }
 
-    if( i_cat != VIDEO_ES )
+    if( p_enc->fmt_out.i_cat == VIDEO_ES && i_cat != VIDEO_ES )
     {
         msg_Err( p_enc, "\"%s\" is not a video encoder", psz_namecodec );
         return VLC_EGENERIC;
     }
 
+    if( p_enc->fmt_out.i_cat == AUDIO_ES && i_cat != AUDIO_ES )
+    {
+        msg_Err( p_enc, "\"%s\" is not an audio encoder", psz_namecodec );
+        return VLC_EGENERIC;
+    }
+
     /* Initialization must be done before avcodec_find_decoder() */
     E_(InitLibavcodec)(p_this);
 
@@ -134,41 +137,86 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this )
     p_enc->p_sys = p_sys;
     p_sys->p_codec = p_codec;
 
-    p_enc->pf_header = NULL;
     p_enc->pf_encode_video = EncodeVideo;
-    p_enc->format.video.i_chroma = VLC_FOURCC('I','4','2','0');
+    p_enc->pf_encode_audio = EncodeAudio;
 
-    if( p_enc->i_fourcc == VLC_FOURCC( 'm','p','1','v' ) ||
-        p_enc->i_fourcc == VLC_FOURCC( 'm','p','2','v' ) )
+    p_sys->p_buffer_out = NULL;
+    p_sys->p_buffer = NULL;
+
+    p_sys->p_context = p_context = avcodec_alloc_context();
+
+    /* Set CPU capabilities */
+#ifdef HAVE_MMX
+    p_context->dsp_mask = 0;
+    if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX )
+    {
+        p_context->dsp_mask &= FF_MM_MMX;
+    }
+    if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT )
+    {
+        p_context->dsp_mask &= FF_MM_MMXEXT;
+    }
+    if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW )
+    {
+        p_context->dsp_mask &= FF_MM_3DNOW;
+    }
+    if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE )
     {
-        p_enc->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
+        p_context->dsp_mask &= FF_MM_SSE;
+        p_context->dsp_mask &= FF_MM_SSE2; /* FIXME */
     }
+    /* Hack to make sure everything can be disabled **/
+    p_context->dsp_mask &= (FF_MM_FORCE >> 1);
+#endif
 
-    p_sys->p_context = p_context = avcodec_alloc_context();
-    p_context->width = p_enc->format.video.i_width;
-    p_context->height = p_enc->format.video.i_height;
-    p_context->bit_rate = p_enc->i_bitrate;
+    /* Make sure we get extradata filled by the encoder */
+    p_context->extradata_size = 0;
+    p_context->extradata = NULL;
+    p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+    if( p_enc->fmt_in.i_cat == VIDEO_ES )
+    {
+        p_context->width = p_enc->fmt_in.video.i_width;
+        p_context->height = p_enc->fmt_in.video.i_height;
 
-    p_context->frame_rate = p_enc->i_frame_rate;
+        p_context->frame_rate = p_enc->fmt_in.video.i_frame_rate;
 #if LIBAVCODEC_BUILD >= 4662
-    p_context->frame_rate_base= p_enc->i_frame_rate_base;
+        p_context->frame_rate_base= p_enc->fmt_in.video.i_frame_rate_base;
 #endif
 
 #if LIBAVCODEC_BUILD >= 4687
-    p_context->sample_aspect_ratio =
-        av_d2q( p_enc->i_aspect * p_context->height / p_context->width /
-                VOUT_ASPECT_FACTOR, 255 );
+        p_context->sample_aspect_ratio =
+            av_d2q( p_enc->fmt_in.video.i_aspect * p_context->height /
+                    p_context->width / VOUT_ASPECT_FACTOR, 255 );
 #else
-    p_context->aspect_ratio = ((float)p_enc->i_aspect) / VOUT_ASPECT_FACTOR;
+        p_context->aspect_ratio = ((float)p_enc->fmt_in.video.i_aspect) /
+            VOUT_ASPECT_FACTOR;
 #endif
 
-    p_context->gop_size = p_enc->i_key_int >= 0 ? p_enc->i_key_int : 50;
+        p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE );
+
+        /* Ffmpeg does handle the conversion itself */
+        //p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
+    }
+    else if( p_enc->fmt_in.i_cat == AUDIO_ES )
+    {
+        p_enc->fmt_in.i_codec  = AOUT_FMT_S16_NE;
+        p_context->bit_rate    = p_enc->fmt_out.i_bitrate;
+        p_context->sample_rate = p_enc->fmt_in.audio.i_rate;
+        p_context->channels    = p_enc->fmt_in.audio.i_channels;
+        p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels;
+        p_sys->p_buffer = malloc( p_sys->i_frame_size );
+        p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
+    }
+
+    /* Misc parameters */
+    p_context->gop_size = p_enc->i_key_int > 0 ? p_enc->i_key_int : 50;
     p_context->max_b_frames =
         __MIN( p_enc->i_b_frames, FF_MAX_B_FRAMES );
     p_context->b_frame_strategy = 0;
     p_context->b_quant_factor = 2.0;
 
-    if( p_enc->i_vtolerance >= 0 )
+    if( p_enc->i_vtolerance > 0 )
     {
         p_context->bit_rate_tolerance = p_enc->i_vtolerance;
     }
@@ -186,7 +234,7 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this )
 
     if( i_codec_id == CODEC_ID_RAWVIDEO )
     {
-        p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->i_fourcc );
+        p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->fmt_in.i_codec );
     }
 
     /* Make sure we get extradata filled by the encoder */
@@ -194,19 +242,40 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this )
     p_context->extradata = NULL;
     p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
 
-    if( avcodec_open( p_context, p_sys->p_codec ) )
+    if( avcodec_open( p_context, p_codec ) )
     {
-        msg_Err( p_enc, "cannot open encoder" );
-        return VLC_EGENERIC;
+        if( p_enc->fmt_in.i_cat == AUDIO_ES && p_context->channels > 2 )
+        {
+            p_context->channels = 2;
+            p_enc->fmt_in.audio.i_channels = 2; // FIXME
+            if( avcodec_open( p_context, p_codec ) )
+            {
+                msg_Err( p_enc, "cannot open encoder" );
+                return VLC_EGENERIC;
+            }
+            msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
+        }
+        else
+        {
+            msg_Err( p_enc, "cannot open encoder" );
+            return VLC_EGENERIC;
+        }
     }
 
-    p_enc->i_extra_data = p_context->extradata_size;
-    p_enc->p_extra_data = p_context->extradata;
+    p_enc->fmt_out.i_extra = p_context->extradata_size;
+    p_enc->fmt_out.p_extra = p_context->extradata;
     p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
 
-    p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE );
+    if( p_enc->fmt_in.i_cat == AUDIO_ES )
+    {
+        p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels;
+        p_sys->p_buffer = malloc( p_sys->i_frame_size );
+    }
+
     p_sys->i_last_ref_pts = 0;
     p_sys->i_buggy_pts_detect = 0;
+    p_sys->i_samples_delay = 0;
+    p_sys->i_pts = 0;
 
     msg_Dbg( p_enc, "found encoder %s", psz_namecodec );
 
@@ -229,7 +298,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
     }
 
     /* Set the pts of the frame being encoded (segfaults with mpeg4!)*/
-    if( p_enc->i_fourcc == VLC_FOURCC( 'm', 'p', 'g', 'v' ) )
+    if( p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', 'g', 'v' ) )
         frame.pts = p_pict->date;
     else
         frame.pts = 0;
@@ -250,8 +319,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
             p_sys->i_buggy_pts_detect = p_sys->p_context->coded_frame->pts;
 
             /* FIXME, 3-2 pulldown is not handled correctly */
-            p_block->i_length = I64C(1000000) * p_enc->i_frame_rate_base /
-                                  p_enc->i_frame_rate;
+            p_block->i_length = I64C(1000000) *
+                p_enc->fmt_in.video.i_frame_rate_base /
+                p_enc->fmt_in.video.i_frame_rate;
             p_block->i_pts    = p_sys->p_context->coded_frame->pts;
 
             if( !p_sys->p_context->delay ||
@@ -279,8 +349,9 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
         {
             /* Buggy libavcodec which doesn't update coded_frame->pts
              * correctly */
-            p_block->i_length = I64C(1000000) * p_enc->i_frame_rate_base /
-                                  p_enc->i_frame_rate;
+            p_block->i_length = I64C(1000000) *
+                p_enc->fmt_in.video.i_frame_rate_base /
+                p_enc->fmt_in.video.i_frame_rate;
             p_block->i_dts = p_block->i_pts = p_pict->date;
         }
 
@@ -290,118 +361,6 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
     return NULL;
 }
 
-/*****************************************************************************
- * CloseVideoEncoder: ffmpeg video encoder destruction
- *****************************************************************************/
-void E_(CloseVideoEncoder)( vlc_object_t *p_this )
-{
-    encoder_t *p_enc = (encoder_t *)p_this;
-    encoder_sys_t *p_sys = p_enc->p_sys;
-
-    avcodec_close( p_sys->p_context );
-    free( p_sys->p_context );
-    free( p_sys->p_buffer_out );
-    free( p_sys );
-}
-
-/*****************************************************************************
- * OpenAudioEncoder: probe the encoder
- *****************************************************************************/
-int E_(OpenAudioEncoder)( vlc_object_t *p_this )
-{
-    encoder_t *p_enc = (encoder_t *)p_this;
-    encoder_sys_t *p_sys;
-    AVCodecContext *p_context;
-    AVCodec *p_codec;
-    int i_codec_id, i_cat;
-    char *psz_namecodec;
-
-    if( !E_(GetFfmpegCodec)( p_enc->i_fourcc, &i_cat, &i_codec_id,
-                             &psz_namecodec ) )
-    {
-        return VLC_EGENERIC;
-    }
-
-    if( i_cat != AUDIO_ES )
-    {
-        msg_Err( p_enc, "\"%s\" is not an audio encoder", psz_namecodec );
-        return VLC_EGENERIC;
-    }
-
-    /* Initialization must be done before avcodec_find_decoder() */
-    E_(InitLibavcodec)(p_this);
-
-    p_codec = avcodec_find_encoder( i_codec_id );
-    if( !p_codec )
-    {
-        msg_Err( p_enc, "cannot find encoder %s", psz_namecodec );
-        return VLC_EGENERIC;
-    }
-
-    /* Allocate the memory needed to store the decoder's structure */
-    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
-    {
-        msg_Err( p_enc, "out of memory" );
-        return VLC_EGENERIC;
-    }
-    p_enc->p_sys = p_sys;
-    p_sys->p_codec = p_codec;
-
-    p_enc->pf_header = NULL;
-    p_enc->pf_encode_audio = EncodeAudio;
-    p_enc->format.audio.i_format = VLC_FOURCC('s','1','6','n');
-
-    p_sys->p_context = p_context = avcodec_alloc_context();
-    p_context->bit_rate    = p_enc->i_bitrate;
-    p_context->sample_rate = p_enc->format.audio.i_rate;
-    p_context->channels    =
-        aout_FormatNbChannels( &p_enc->format.audio );
-
-    /* Make sure we get extradata filled by the encoder */
-    p_context->extradata_size = 0;
-    p_context->extradata = NULL;
-    p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
-    if( avcodec_open( p_context, p_codec ) < 0 )
-    {
-        if( p_context->channels > 2 )
-        {
-            p_context->channels = 2;
-            //id->f_dst.i_channels   = 2;
-            if( avcodec_open( p_context, p_codec ) < 0 )
-            {
-                msg_Err( p_enc, "cannot open encoder" );
-                return VLC_EGENERIC;
-            }
-            msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
-        }
-        else
-        {
-            msg_Err( p_enc, "cannot open encoder" );
-            return VLC_EGENERIC;
-        }
-    }
-
-    p_enc->i_extra_data = p_context->extradata_size;
-    p_enc->p_extra_data = p_context->extradata;
-    p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
-
-    p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels;
-    p_sys->p_buffer = malloc( p_sys->i_frame_size );
-    p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
-
-    msg_Warn( p_enc, "avcodec_setup_audio: %d %d %d %d",
-              p_context->frame_size, p_context->bit_rate, p_context->channels,
-              p_context->sample_rate );
-
-    p_sys->i_samples_delay = 0;
-    p_sys->i_pts = 0;
-
-    msg_Dbg( p_enc, "found encoder %s", psz_namecodec );
-
-    return VLC_SUCCESS;
-}
-
 /****************************************************************************
  * EncodeAudio: the whole thing
  ****************************************************************************/
@@ -416,7 +375,7 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
 
     p_sys->i_pts = p_aout_buf->start_date -
                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
-                (mtime_t)p_enc->format.audio.i_rate;
+                (mtime_t)p_enc->fmt_in.audio.i_rate;
 
     p_sys->i_samples_delay += i_samples;
 
@@ -484,16 +443,18 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
 }
 
 /*****************************************************************************
- * CloseAudioEncoder: ffmpeg audio encoder destruction
+ * CloseEncoder: ffmpeg encoder destruction
  *****************************************************************************/
-void E_(CloseAudioEncoder)( vlc_object_t *p_this )
+void E_(CloseEncoder)( vlc_object_t *p_this )
 {
     encoder_t *p_enc = (encoder_t *)p_this;
     encoder_sys_t *p_sys = p_enc->p_sys;
 
     avcodec_close( p_sys->p_context );
     free( p_sys->p_context );
-    free( p_sys->p_buffer );
-    free( p_sys->p_buffer_out );
+
+    if( p_sys->p_buffer ) free( p_sys->p_buffer );
+    if( p_sys->p_buffer_out ) free( p_sys->p_buffer_out );
+
     free( p_sys );
 }
index c6a9268..b90f2d8 100644 (file)
@@ -2,7 +2,7 @@
  * ffmpeg.c: video decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ffmpeg.c,v 1.58 2003/10/29 20:53:41 gbazin Exp $
+ * $Id: ffmpeg.c,v 1.59 2003/11/16 21:07:31 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
 #include <string.h>
 
 #include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/aout.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
-#ifdef HAVE_SYS_TIMES_H
-#   include <sys/times.h>
-#endif
-
 /* ffmpeg header */
 #ifdef HAVE_FFMPEG_AVCODEC_H
 #   include <ffmpeg/avcodec.h>
@@ -77,10 +71,7 @@ struct decoder_sys_t
  * Local prototypes
  ****************************************************************************/
 static int OpenDecoder( vlc_object_t * );
-static int InitDecoder( decoder_t * );
-static int EndDecoder( decoder_t * );
-
-static int b_ffmpeginit = 0;
+static void CloseDecoder( vlc_object_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -90,7 +81,7 @@ vlc_module_begin();
     /* decoder main module */
     add_category_hint( N_("ffmpeg"), NULL, VLC_FALSE );
     set_capability( "decoder", 70 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
     set_description( _("ffmpeg audio/video decoder((MS)MPEG4,SVQ1,H263,WMV,WMA)") );
 
     add_bool( "ffmpeg-dr", 1, NULL, DR_TEXT, DR_TEXT, VLC_TRUE );
@@ -115,18 +106,12 @@ vlc_module_begin();
     set_callbacks( E_(OpenChroma), NULL );
     set_description( _("ffmpeg chroma conversion") );
 
-     /* video encoder submodule */
-     add_submodule();
-     set_description( _("ffmpeg video encoder") );
-     set_capability( "video encoder", 100 );
-     set_callbacks( E_(OpenVideoEncoder), E_(CloseVideoEncoder) );
-     /* audio encoder submodule */
-     add_submodule();
-     set_description( _("ffmpeg audio encoder") );
-     set_capability( "audio encoder", 10 );
-     set_callbacks( E_(OpenAudioEncoder), E_(CloseAudioEncoder) );
+    /* encoder submodule */
+    add_submodule();
+    set_description( _("ffmpeg audio/video encoder") );
+    set_capability( "encoder", 100 );
+    set_callbacks( E_(OpenEncoder), E_(CloseEncoder) );
+
     var_Create( p_module->p_libvlc, "avcodec", VLC_VAR_MUTEX );
 vlc_module_end();
 
@@ -136,10 +121,14 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*) p_this;
-    int i_cat, i_codec_id;
+    int i_cat, i_codec_id, i_result;
     char *psz_namecodec;
 
-    if( !E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc, &i_cat, &i_codec_id,
+    AVCodecContext *p_context;
+    AVCodec        *p_codec;
+
+    /* *** determine codec type *** */
+    if( !E_(GetFfmpegCodec)( p_dec->fmt_in.i_codec, &i_cat, &i_codec_id,
                              &psz_namecodec ) )
     {
         return VLC_EGENERIC;
@@ -148,54 +137,51 @@ static int OpenDecoder( vlc_object_t *p_this )
     /* Initialization must be done before avcodec_find_decoder() */
     E_(InitLibavcodec)(p_this);
 
-    if( !avcodec_find_decoder( i_codec_id ) )
-    {
-        msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec );
-        return VLC_EGENERIC;
-    }
-
-    p_dec->pf_init = InitDecoder;
-    p_dec->pf_decode = (i_cat == VIDEO_ES) ? E_(DecodeVideo) : E_(DecodeAudio);
-    p_dec->pf_end = EndDecoder;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    int i_cat, i_codec_id, i_result;
-    char *psz_namecodec;
-    AVCodecContext *p_context;
-    AVCodec        *p_codec;
-
-    /* *** determine codec type *** */
-    E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc,
-                        &i_cat, &i_codec_id, &psz_namecodec );
-
     /* *** ask ffmpeg for a decoder *** */
     if( !( p_codec = avcodec_find_decoder( i_codec_id ) ) )
     {
-        msg_Err( p_dec, "codec not found (%s)", psz_namecodec );
+        msg_Dbg( p_dec, "codec not found (%s)", psz_namecodec );
         return VLC_EGENERIC;
     }
 
     /* *** get a p_context *** */
     p_context = avcodec_alloc_context();
 
+    /* Set CPU capabilities */
+#ifdef HAVE_MMX
+    p_context->dsp_mask = 0;
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMX )
+    {
+        p_context->dsp_mask &= FF_MM_MMX;
+    }
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT )
+    {
+        p_context->dsp_mask &= FF_MM_MMXEXT;
+    }
+    if( p_dec->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW )
+    {
+        p_context->dsp_mask &= FF_MM_3DNOW;
+    }
+    if( p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE )
+    {
+        p_context->dsp_mask &= FF_MM_SSE;
+        p_context->dsp_mask &= FF_MM_SSE2; /* FIXME */
+    }
+    /* Hack to make sure everything can be disabled **/
+    p_context->dsp_mask &= (FF_MM_FORCE >> 1);
+#endif
+
     switch( i_cat )
     {
     case VIDEO_ES:
+        p_dec->pf_decode_video = E_(DecodeVideo);
         i_result = E_( InitVideoDec )( p_dec, p_context, p_codec,
                                        i_codec_id, psz_namecodec );
-        p_dec->pf_decode = E_(DecodeVideo);
         break;
     case AUDIO_ES:
+        p_dec->pf_decode_audio = E_(DecodeAudio);
         i_result = E_( InitAudioDec )( p_dec, p_context, p_codec,
                                        i_codec_id, psz_namecodec );
-        p_dec->pf_decode = E_(DecodeAudio);
         break;
     default:
         i_result = VLC_EGENERIC;
@@ -205,12 +191,13 @@ static int InitDecoder( decoder_t *p_dec )
 
     return i_result;
 }
-  
+
 /*****************************************************************************
- * EndDecoder: decoder destruction
+ * CloseDecoder: decoder destruction
  *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     if( !p_sys->p_context )
@@ -234,7 +221,6 @@ static int EndDecoder( decoder_t *p_dec )
     }
 
     free( p_sys );
-    return VLC_SUCCESS;
 }
   
 /*****************************************************************************
@@ -692,12 +678,13 @@ int E_(GetFfmpegChroma)( vlc_fourcc_t i_chroma )
 
 void E_(InitLibavcodec)( vlc_object_t *p_object )
 {
+    static int b_ffmpeginit = 0;
     vlc_value_t lockval;
 
     var_Get( p_object->p_libvlc, "avcodec", &lockval );
     vlc_mutex_lock( lockval.p_address );
 
-     /* *** init ffmpeg library (libavcodec) *** */
+    /* *** init ffmpeg library (libavcodec) *** */
     if( !b_ffmpeginit )
     {
         avcodec_init();
index 2393c21..d4a5794 100644 (file)
@@ -2,7 +2,7 @@
  * ffmpeg.h: decoder using the ffmpeg library
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: ffmpeg.h,v 1.27 2003/10/27 01:04:38 gbazin Exp $
+ * $Id: ffmpeg.h,v 1.28 2003/11/16 21:07:31 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -42,20 +42,20 @@ int E_(GetFfmpegChroma)( vlc_fourcc_t );
 int  E_( InitVideoDec )( decoder_t *, AVCodecContext *, AVCodec *,
                          int, char * );
 void E_( EndVideoDec ) ( decoder_t * );
-int  E_( DecodeVideo ) ( decoder_t *, block_t * );
+picture_t *E_( DecodeVideo ) ( decoder_t *, block_t ** );
 
 /* Audio decoder module */
 int  E_( InitAudioDec )( decoder_t *, AVCodecContext *, AVCodec *,
                          int, char * );
 void E_( EndAudioDec ) ( decoder_t * );
-int  E_( DecodeAudio ) ( decoder_t *, block_t * );
+aout_buffer_t *E_( DecodeAudio ) ( decoder_t *, block_t ** );
 
 /* Chroma conversion module */
 int  E_(OpenChroma)( vlc_object_t * );
 
 /* Video encoder module */
-int  E_(OpenVideoEncoder) ( vlc_object_t * );
-void E_(CloseVideoEncoder)( vlc_object_t * );
+int  E_(OpenEncoder) ( vlc_object_t * );
+void E_(CloseEncoder)( vlc_object_t * );
 
 /* Audio encoder module */
 int  E_(OpenAudioEncoder) ( vlc_object_t * );
index 1349a26..74ed35a 100644 (file)
@@ -2,7 +2,7 @@
  * video.c: video decoder using the ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: video.c,v 1.43 2003/10/28 14:17:52 gbazin Exp $
+ * $Id: video.c,v 1.44 2003/11/16 21:07:31 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
 #include <string.h>
 
 #include <vlc/vlc.h>
-#include <vlc/vout.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
-#ifdef HAVE_SYS_TIMES_H
-#   include <sys/times.h>
-#endif
-
 /* ffmpeg header */
 #ifdef HAVE_FFMPEG_AVCODEC_H
 #   include <ffmpeg/avcodec.h>
@@ -66,11 +61,8 @@ struct decoder_sys_t
     AVFrame          *p_ff_pic;
     BITMAPINFOHEADER *p_format;
 
-    vout_thread_t    *p_vout;
-
     /* for frame skipping algo */
     int b_hurry_up;
-    int i_frame_error;
     int i_frame_skip;
 
     /* how many decoded frames are late */
@@ -82,11 +74,12 @@ struct decoder_sys_t
 
     vlc_bool_t b_has_b_frames;
 
-    int i_buffer;
-    char *p_buffer;
+    int i_buffer_orig, i_buffer;
+    char *p_buffer_orig, *p_buffer;
 
     /* Postprocessing handle */
     void *p_pp;
+    vlc_bool_t b_pp_init;
 };
 
 /*****************************************************************************
@@ -99,20 +92,31 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );
 /*****************************************************************************
  * Local Functions
  *****************************************************************************/
-static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
+static uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
 {
-    /* FIXME FIXME some of them are wrong */
     switch( i_ff_chroma )
     {
     case PIX_FMT_YUV420P:
-    case PIX_FMT_YUV422:
-        return( VLC_FOURCC('I','4','2','0') );
-    case PIX_FMT_RGB24:
-        return( VLC_FOURCC('R','V','2','4') );
+        return VLC_FOURCC('I','4','2','0');
     case PIX_FMT_YUV422P:
-        return( VLC_FOURCC('I','4','2','2') );
+        return VLC_FOURCC('I','4','2','2');
     case PIX_FMT_YUV444P:
-        return( VLC_FOURCC('I','4','4','4') );
+        return VLC_FOURCC('I','4','4','4');
+
+    case PIX_FMT_YUV422:
+        return VLC_FOURCC('Y','U','Y','2');
+
+    case PIX_FMT_RGB555:
+        return VLC_FOURCC('R','V','1','5');
+    case PIX_FMT_RGB565:
+        return VLC_FOURCC('R','V','1','6');
+    case PIX_FMT_RGB24:
+        return VLC_FOURCC('R','V','2','4');
+    case PIX_FMT_RGBA32:
+        return VLC_FOURCC('R','V','3','2');
+    case PIX_FMT_GRAY8:
+        return VLC_FOURCC('G','R','E','Y');
+
     case PIX_FMT_YUV410P:
     case PIX_FMT_YUV411P:
     case PIX_FMT_BGR24:
@@ -121,50 +125,54 @@ static inline uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
     }
 }
 
-/* Return a Vout */
-static vout_thread_t *ffmpeg_CreateVout( decoder_t  *p_dec,
-                                         AVCodecContext *p_context )
+/* Returns a new picture buffer */
+static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec,
+                                            AVCodecContext *p_context )
 {
-    vout_thread_t *p_vout;
-    unsigned int   i_width = p_context->width;
-    unsigned int   i_height = p_context->height;
-    uint32_t       i_chroma = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
-    unsigned int   i_aspect;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    picture_t *p_pic;
 
-    if( !i_width || !i_height )
+    p_dec->fmt_out.video.i_width = p_context->width;
+    p_dec->fmt_out.video.i_height = p_context->height;
+    p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
+
+    if( !p_context->width || !p_context->height )
     {
-        return( NULL ); /* Can't create a new vout without display size */
+        return NULL; /* invalid display size */
     }
 
-    if( !i_chroma )
+    if( !p_dec->fmt_out.i_codec )
     {
         /* we make conversion if possible*/
-        i_chroma = VLC_FOURCC('I','4','2','0');
+        p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
     }
 
 #if LIBAVCODEC_BUILD >= 4687
-    i_aspect = VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) *
-        p_context->width / p_context->height );
+    p_dec->fmt_out.video.i_aspect =
+        VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) *
+            p_context->width / p_context->height );
 #else
-    i_aspect = VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
+    p_dec->fmt_out.video.i_aspect =
+        VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
 #endif
-    if( i_aspect == 0 )
+    if( p_dec->fmt_out.video.i_aspect == 0 )
     {
-        i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
+        p_dec->fmt_out.video.i_aspect =
+            VOUT_ASPECT_FACTOR * p_context->width / p_context->height;
     }
 
-    /* Spawn a video output if there is none. First we look for our children,
-     * then we look for any other vout that might be available. */
-    p_vout = vout_Request( p_dec, p_dec->p_sys->p_vout,
-                           i_width, i_height, i_chroma, i_aspect );
+    p_pic = p_dec->pf_vout_buffer_new( p_dec );
 
 #ifdef LIBAVCODEC_PP
-    if( p_dec->p_sys->p_pp )
-        E_(InitPostproc)( p_dec, p_dec->p_sys->p_pp, i_width, i_height,
-                          p_context->pix_fmt );
+    if( p_sys->p_pp && !p_sys->b_pp_init )
+    {
+        E_(InitPostproc)( p_dec, p_sys->p_pp, p_context->width,
+                          p_context->height, p_context->pix_fmt );
+        p_sys->b_pp_init = VLC_TRUE;
+    }
 #endif
 
-    return p_vout;
+    return p_pic;
 }
 
 /*****************************************************************************
@@ -194,18 +202,9 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
     p_dec->p_sys->psz_namecodec = psz_namecodec;
     p_sys->p_ff_pic = avcodec_alloc_frame();
 
-    if( ( p_sys->p_format =
-          (BITMAPINFOHEADER *)p_dec->p_fifo->p_bitmapinfoheader ) != NULL )
-    {
-        /* ***** Fill p_context with init values ***** */
-        p_sys->p_context->width  = p_sys->p_format->biWidth;
-        p_sys->p_context->height = p_sys->p_format->biHeight;
-    }
-    else
-    {
-        msg_Warn( p_dec, "display informations missing" );
-        p_sys->p_format = NULL;
-    }
+    /* ***** Fill p_context with init values ***** */
+    p_sys->p_context->width  = p_dec->fmt_in.video.i_width;
+    p_sys->p_context->height = p_dec->fmt_in.video.i_height;
 
     /*  ***** Get configuration of ffmpeg plugin ***** */
     i_tmp = config_GetInt( p_dec, "ffmpeg-workaround-bugs" );
@@ -258,6 +257,7 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
 
 #ifdef LIBAVCODEC_PP
     p_sys->p_pp = NULL;
+    p_dec->p_sys->b_pp_init = VLC_FALSE;
     if( E_(OpenPostproc)( p_dec, &p_sys->p_pp ) == VLC_SUCCESS )
     {
         /* for now we cannot do postproc and dr */
@@ -280,16 +280,15 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
     p_sys->p_context->opaque = p_dec;
 
     /* ***** init this codec with special data ***** */
-    if( p_sys->p_format && p_sys->p_format->biSize > sizeof(BITMAPINFOHEADER) )
+    if( p_dec->fmt_in.i_extra )
     {
         int b_gotpicture;
-        int i_size = p_sys->p_format->biSize - sizeof(BITMAPINFOHEADER);
+        int i_size = p_dec->fmt_in.i_extra;
 
         if( p_sys->i_codec_id == CODEC_ID_MPEG4 )
         {
             uint8_t *p_vol = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
-
-            memcpy( p_vol, &p_sys->p_format[1], i_size );
+            memcpy( p_vol, p_dec->fmt_in.p_extra, i_size );
             memset( &p_vol[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE );
 
             avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
@@ -307,7 +306,7 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
 
             memcpy( &p[0],  "SVQ3", 4 );
             memset( &p[4], 0, 8 );
-            memcpy( &p[12], &p_sys->p_format[1], i_size );
+            memcpy( &p[12], p_dec->fmt_in.p_extra, i_size );
         }
 #endif
         else
@@ -316,20 +315,24 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
             p_sys->p_context->extradata =
                 malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
             memcpy( p_sys->p_context->extradata,
-                    &p_sys->p_format[1], i_size );
+                    p_dec->fmt_in.p_extra, i_size );
             memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
                     0, FF_INPUT_BUFFER_PADDING_SIZE );
         }
     }
 
     /* ***** misc init ***** */
-    p_sys->p_vout = NULL;
     p_sys->input_pts = 0;
     p_sys->i_pts = 0;
     p_sys->b_has_b_frames = VLC_FALSE;
     p_sys->i_late_frames = 0;
-    p_sys->i_buffer = 1;
-    p_sys->p_buffer = malloc( p_sys->i_buffer );
+    p_sys->i_buffer = 0;
+    p_sys->i_buffer_orig = 1;
+    p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer );
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+    p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
 
     return VLC_SUCCESS;
 }
@@ -337,17 +340,22 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
 /*****************************************************************************
  * DecodeVideo: Called to decode one or more frames
  *****************************************************************************/
-int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
+picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i_buffer, b_drawpicture;
-    char *p_buffer;
+    int b_drawpicture;
+    block_t *p_block;
+
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
 
     if( p_block->i_pts > 0 )
     {
         p_sys->input_pts = p_block->i_pts;
     }
 
+#if 0
     /* TODO implement it in a better way */
     /* A good idea could be to decode all I pictures and see for the other */
     if( p_sys->b_hurry_up && p_sys->i_late_frames > 4 )
@@ -364,7 +372,8 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
 
             p_sys->i_late_frames--; /* needed else it will never be decrease */
             block_Release( p_block );
-            return VLC_SUCCESS;
+            p_sys->i_buffer = 0;
+            return NULL;
         }
     }
     else
@@ -383,6 +392,7 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
         p_sys->i_late_frames--;
         return VLC_SUCCESS;
     }
+#endif
 
     if( !p_sys->p_context->width || !p_sys->p_context->height )
     {
@@ -395,36 +405,46 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
 
     /* Don't forget that ffmpeg requires a little more bytes
      * that the real frame size */
-    i_buffer = p_block->i_buffer;
-    if( i_buffer + FF_INPUT_BUFFER_PADDING_SIZE > p_sys->i_buffer )
+    if( p_block->i_buffer )
     {
-        free( p_sys->p_buffer );
-        p_sys->i_buffer = i_buffer + FF_INPUT_BUFFER_PADDING_SIZE;
-        p_sys->p_buffer = malloc( p_sys->i_buffer );
+        p_sys->i_buffer = p_block->i_buffer;
+        if( p_sys->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE >
+            p_sys->i_buffer_orig )
+        {
+            free( p_sys->p_buffer_orig );
+            p_sys->i_buffer_orig =
+                p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE;
+            p_sys->p_buffer_orig = malloc( p_sys->i_buffer_orig );
+        }
+        p_sys->p_buffer = p_sys->p_buffer_orig;
+        p_sys->i_buffer = p_block->i_buffer;
+        p_dec->p_vlc->pf_memcpy( p_sys->p_buffer, p_block->p_buffer,
+                                 p_block->i_buffer );
+        memset( p_sys->p_buffer + p_block->i_buffer, 0,
+                FF_INPUT_BUFFER_PADDING_SIZE );
+
+        p_block->i_buffer = 0;
     }
-    p_buffer = p_sys->p_buffer;
-    p_dec->p_vlc->pf_memcpy( p_buffer, p_block->p_buffer, p_block->i_buffer );
-    memset( p_buffer + i_buffer, 0, FF_INPUT_BUFFER_PADDING_SIZE );
 
-    while( i_buffer )
+    while( p_sys->i_buffer )
     {
         int i_used, b_gotpicture;
         picture_t *p_pic;
 
         i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
                                        &b_gotpicture,
-                                       p_buffer, i_buffer );
+                                       p_sys->p_buffer, p_sys->i_buffer );
         if( i_used < 0 )
         {
-            msg_Warn( p_dec, "cannot decode one frame (%d bytes)", i_buffer );
-            p_sys->i_frame_error++;
+            msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
+                      p_sys->i_buffer );
             block_Release( p_block );
-            return VLC_SUCCESS;
+            return NULL;
         }
 
         /* Consumed bytes */
-        i_buffer -= i_used;
-        p_buffer += i_used;
+        p_sys->i_buffer -= i_used;
+        p_sys->p_buffer += i_used;
 
         /* Nothing to display */
         if( !b_gotpicture ) continue;
@@ -449,23 +469,12 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
 
         if( !p_sys->b_direct_rendering )
         {
-            p_sys->p_vout = ffmpeg_CreateVout( p_dec, p_sys->p_context );
-            if( !p_sys->p_vout )
-            {
-                msg_Err( p_dec, "cannot create vout" );
-                block_Release( p_block );
-                return VLC_EGENERIC;
-            }
-
             /* Get a new picture */
-            while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
+            p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );
+            if( !p_pic )
             {
-                if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
-                {
-                    block_Release( p_block );
-                    return VLC_EGENERIC;
-                }
-                msleep( VOUT_OUTMEM_SLEEP );
+                block_Release( p_block );
+                return NULL;
             }
 
             /* Fill p_picture_t from AVVideoFrame and do chroma conversion
@@ -493,8 +502,7 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
         /* Send decoded frame to vout */
         if( p_sys->i_pts )
         {
-            vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts );
-            vout_DisplayPicture( p_sys->p_vout, p_pic );
+            p_pic->date = p_sys->i_pts;
 
             /* interpolate the next PTS */
             if( p_sys->p_context->frame_rate > 0 )
@@ -504,11 +512,16 @@ int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
                     p_sys->p_context->frame_rate_base /
                     (2 * p_sys->p_context->frame_rate);
             }
+            return p_pic;
+        }
+        else
+        {
+            p_dec->pf_vout_buffer_del( p_dec, p_pic );
         }
     }
 
     block_Release( p_block );
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
@@ -527,10 +540,7 @@ void E_(EndVideoDec)( decoder_t *p_dec )
     E_(ClosePostproc)( p_dec, p_sys->p_pp );
 #endif
 
-    free( p_sys->p_buffer );
-
-    /* We are about to die. Reattach video output to p_vlc. */
-    vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
+    free( p_sys->p_buffer_orig );
 }
 
 /*****************************************************************************
@@ -632,28 +642,14 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
         return avcodec_default_get_buffer( p_context, p_ff_pic );
     }
 
-    /* Check and (re)create our vout if needed */
-    p_sys->p_vout = ffmpeg_CreateVout( p_dec, p_sys->p_context );
-    if( !p_sys->p_vout )
+    /* Get a new picture */
+    //p_sys->p_vout->render.b_allow_modify_pics = 0;
+    p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );
+    if( !p_pic )
     {
-        msg_Err( p_dec, "cannot create vout" );
-        p_dec->p_fifo->b_error = 1; /* abort */
         p_sys->b_direct_rendering = 0;
         return avcodec_default_get_buffer( p_context, p_ff_pic );
     }
-
-    p_sys->p_vout->render.b_allow_modify_pics = 0;
-
-    /* Get a new picture */
-    while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
-    {
-        if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
-        {
-            p_sys->b_direct_rendering = 0;
-            return avcodec_default_get_buffer( p_context, p_ff_pic );
-        }
-        msleep( VOUT_OUTMEM_SLEEP );
-    }
     p_sys->p_context->draw_horiz_band = NULL;
 
     p_ff_pic->opaque = (void*)p_pic;
@@ -670,20 +666,19 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
 
     if( p_ff_pic->reference != 0 )
     {
-        vout_LinkPicture( p_sys->p_vout, p_pic );
+      //vout_LinkPicture( p_sys->p_vout, p_pic );
     }
 
     /* FIXME what is that, should give good value */
     p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
 
-    return( 0 );
+    return 0;
 }
 
-static void  ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
-                                     AVFrame *p_ff_pic )
+static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
+                                    AVFrame *p_ff_pic )
 {
     decoder_t *p_dec = (decoder_t *)p_context->opaque;
-    decoder_sys_t *p_sys = p_dec->p_sys;
     picture_t *p_pic;
 
     if( p_ff_pic->type != FF_BUFFER_TYPE_USER )
@@ -701,6 +696,6 @@ static void  ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
 
     if( p_ff_pic->reference != 0 )
     {
-        vout_UnlinkPicture( p_sys->p_vout, p_pic );
+      //vout_UnlinkPicture( p_sys->p_vout, p_pic );
     }
 }
index 4f3c886..3b0cd72 100644 (file)
@@ -2,7 +2,7 @@
  * flac.c: flac decoder module making use of libflac
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: flacdec.c,v 1.4 2003/09/02 20:19:25 gbazin Exp $
+ * $Id: flacdec.c,v 1.5 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
  *
@@ -116,7 +116,7 @@ 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('f','l','a','c') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','l','a','c') )
     {
         return VLC_EGENERIC;
     }
index bef10b6..d80b182 100755 (executable)
@@ -2,7 +2,7 @@
  * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: libmpeg2.c,v 1.32 2003/11/04 17:46:17 gbazin Exp $
+ * $Id: libmpeg2.c,v 1.33 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *          Christophe Massiot <massiot@via.ecp.fr>
@@ -72,18 +72,18 @@ struct decoder_sys_t
     /*
      * Output properties
      */
-    vout_thread_t *p_vout;
     vout_synchro_t *p_synchro;
+    int i_aspect;
 
 };
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int OpenDecoder( vlc_object_t * );
-static int InitDecoder( decoder_t * );
-static int RunDecoder ( decoder_t *, block_t * );
-static int EndDecoder ( decoder_t * );
+static int  OpenDecoder( vlc_object_t * );
+static void CloseDecoder( vlc_object_t * );
+
+static picture_t *DecodeBlock( decoder_t *, block_t ** );
 
 static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
 
@@ -93,7 +93,7 @@ static picture_t *GetNewPicture( decoder_t *, uint8_t ** );
 vlc_module_begin();
     set_description( _("MPEG I/II video decoder (using libmpeg2)") );
     set_capability( "decoder", 150 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
     add_shortcut( "libmpeg2" );
 vlc_module_end();
 
@@ -103,32 +103,21 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','v') &&
-        p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','1') &&
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','v') &&
+        p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','1') &&
         /* Pinnacle hardware-mpeg1 */
-        p_dec->p_fifo->i_fourcc != VLC_FOURCC('P','I','M','1') &&
+        p_dec->fmt_in.i_codec != VLC_FOURCC('P','I','M','1') &&
         /* ATI Video */
-        p_dec->p_fifo->i_fourcc != VLC_FOURCC('V','C','R','2') &&
-        p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','g','2') )
+        p_dec->fmt_in.i_codec != VLC_FOURCC('V','C','R','2') &&
+        p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','2') )
     {
         return VLC_EGENERIC;
     }
 
-    p_dec->pf_init = InitDecoder;
-    p_dec->pf_decode = RunDecoder;
-    p_dec->pf_end = EndDecoder;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
     /* Allocate the memory needed to store the decoder's structure */
-    if( ( p_dec->p_sys =
+    if( ( p_dec->p_sys = p_sys =
           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
         msg_Err( p_dec, "out of memory" );
@@ -136,30 +125,31 @@ static int InitDecoder( decoder_t *p_dec )
     }
 
     /* Initialize the thread properties */
-    memset( p_dec->p_sys, 0, sizeof(decoder_sys_t) );
-    p_dec->p_sys->p_pes      = NULL;
-    p_dec->p_sys->p_vout     = NULL;
-    p_dec->p_sys->p_mpeg2dec = NULL;
-    p_dec->p_sys->p_synchro  = NULL;
-    p_dec->p_sys->p_info     = NULL;
-    p_dec->p_sys->i_pts      = mdate() + DEFAULT_PTS_DELAY;
-    p_dec->p_sys->i_current_pts  = 0;
-    p_dec->p_sys->i_previous_pts = 0;
-    p_dec->p_sys->p_picture_to_destroy = NULL;
-    p_dec->p_sys->b_garbage_pic = 0;
-    p_dec->p_sys->b_slice_i  = 0;
-    p_dec->p_sys->b_skip     = 0;
+    memset( p_sys, 0, sizeof(decoder_sys_t) );
+    p_sys->p_pes      = NULL;
+    p_sys->p_mpeg2dec = NULL;
+    p_sys->p_synchro  = NULL;
+    p_sys->p_info     = NULL;
+    p_sys->i_pts      = mdate() + DEFAULT_PTS_DELAY;
+    p_sys->i_current_pts  = 0;
+    p_sys->i_previous_pts = 0;
+    p_sys->p_picture_to_destroy = NULL;
+    p_sys->b_garbage_pic = 0;
+    p_sys->b_slice_i  = 0;
+    p_sys->b_skip     = 0;
 
     /* Initialize decoder */
-    p_dec->p_sys->p_mpeg2dec = mpeg2_init();
-    if( p_dec->p_sys->p_mpeg2dec == NULL)
+    p_sys->p_mpeg2dec = mpeg2_init();
+    if( p_sys->p_mpeg2dec == NULL)
     {
         msg_Err( p_dec, "mpeg2_init() failed" );
-        free( p_dec->p_sys );
+        free( p_sys );
         return VLC_EGENERIC;
     }
 
-    p_dec->p_sys->p_info = mpeg2_info( p_dec->p_sys->p_mpeg2dec );
+    p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec );
+
+    p_dec->pf_decode_video = DecodeBlock;
 
     return VLC_SUCCESS;
 }
@@ -167,32 +157,29 @@ static int InitDecoder( decoder_t *p_dec )
 /*****************************************************************************
  * RunDecoder: the libmpeg2 decoder
  *****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t   *p_sys = p_dec->p_sys;
     mpeg2_state_t   state;
     picture_t       *p_pic;
-    int             i_aspect;
 
-    vlc_bool_t      b_need_more_data = VLC_FALSE;
+    block_t *p_block;
+
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
 
     while( 1 )
     {
-        if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
-        {
-            block_Release( p_block );
-            return VLC_EGENERIC;
-        }
-
         state = mpeg2_parse( p_sys->p_mpeg2dec );
 
         switch( state )
         {
         case STATE_BUFFER:
-            if( !p_block->i_buffer || b_need_more_data )
+            if( !p_block->i_buffer )
             {
                 block_Release( p_block );
-                return VLC_SUCCESS;
+                return NULL;
             }
 
             if( p_block->b_discontinuity && p_sys->p_synchro
@@ -215,16 +202,6 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                 }
                 p_sys->p_picture_to_destroy = p_pic;
 
-                memset( p_pic->p[0].p_pixels, 0,
-                        p_sys->p_info->sequence->width
-                         * p_sys->p_info->sequence->height );
-                memset( p_pic->p[1].p_pixels, 0x80,
-                        p_sys->p_info->sequence->width
-                         * p_sys->p_info->sequence->height / 4 );
-                memset( p_pic->p[2].p_pixels, 0x80,
-                        p_sys->p_info->sequence->width
-                         * p_sys->p_info->sequence->height / 4 );
-
                 if ( p_sys->b_slice_i )
                 {
                     vout_SynchroNewPicture( p_sys->p_synchro,
@@ -246,7 +223,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             mpeg2_buffer( p_sys->p_mpeg2dec, p_block->p_buffer,
                           p_block->p_buffer + p_block->i_buffer );
 
-            b_need_more_data = VLC_TRUE;
+           p_block->i_buffer = 0;
             break;
 
         case STATE_SEQUENCE:
@@ -255,25 +232,24 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             uint8_t *buf[3];
             buf[0] = buf[1] = buf[2] = NULL;
 
-            /* Check whether the input gives a particular aspect ratio */
-            if( p_dec->p_fifo->p_demux_data
-                && ( *(int*)(p_dec->p_fifo->p_demux_data) & 0x7 ) )
+            /* Check whether the input gave a particular aspect ratio */
+            if( p_dec->fmt_in.video.i_aspect )
             {
-                i_aspect = *(int*)(p_dec->p_fifo->p_demux_data);
-                switch( i_aspect )
+                p_sys->i_aspect = p_dec->fmt_in.video.i_aspect;
+                switch( p_sys->i_aspect )
                 {
                 case AR_3_4_PICTURE:
-                    i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
+                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
                     break;
                 case AR_16_9_PICTURE:
-                    i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
+                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 16 / 9;
                     break;
                 case AR_221_1_PICTURE:
-                    i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
+                    p_sys->i_aspect = VOUT_ASPECT_FACTOR * 221 / 100;
                     break;
                 case AR_SQUARE_PICTURE:
                 default:
-                    i_aspect = VOUT_ASPECT_FACTOR *
+                    p_sys->i_aspect = VOUT_ASPECT_FACTOR *
                                    p_sys->p_info->sequence->width /
                                    p_sys->p_info->sequence->height;
                     break;
@@ -282,73 +258,42 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             else
             {
                 /* Use the value provided in the MPEG sequence header */
-                i_aspect = ((uint64_t)p_sys->p_info->sequence->display_width) *
+                p_sys->i_aspect =
+                   ((uint64_t)p_sys->p_info->sequence->display_width) *
                     p_sys->p_info->sequence->pixel_width * VOUT_ASPECT_FACTOR /
                     p_sys->p_info->sequence->display_height /
                     p_sys->p_info->sequence->pixel_height;
             }
 
-            if ( p_dec->p_sys->p_vout != NULL )
-            {
-              int i_pic;
-                /* Temporary hack to free the pictures in use by libmpeg2 */
-                for ( i_pic = 0; i_pic < p_dec->p_sys->p_vout->render.i_pictures; i_pic++ )
-                {
-                    if( p_dec->p_sys->p_vout->render.pp_picture[i_pic]->i_status ==
-                          RESERVED_PICTURE )
-                        vout_DestroyPicture( p_dec->p_sys->p_vout,
-                                         p_dec->p_sys->p_vout->render.pp_picture[i_pic] );
-                    if( p_dec->p_sys->p_vout->render.pp_picture[i_pic]->i_refcount > 0 )
-                        vout_UnlinkPicture( p_dec->p_sys->p_vout,
-                                         p_dec->p_sys->p_vout->render.pp_picture[i_pic] );
-                }
-            }
-
-            p_sys->p_vout = vout_Request( p_dec, p_sys->p_vout,
-                                          p_sys->p_info->sequence->width,
-                                          p_sys->p_info->sequence->height,
-                                          VLC_FOURCC('Y','V','1','2'),
-                                          i_aspect );
-
-            if(p_sys->p_vout == NULL )
-            {
-                msg_Err( p_dec, "cannot create vout" );
-                block_Release( p_block );
-                return -1;
-            }
-
             msg_Dbg( p_dec, "%dx%d, aspect %d, %u.%03u fps",
                      p_sys->p_info->sequence->width,
-                     p_sys->p_info->sequence->height, i_aspect,
+                     p_sys->p_info->sequence->height, p_sys->i_aspect,
                      (uint32_t)((uint64_t)1001000000 * 27 /
-                                 p_sys->p_info->sequence->frame_period / 1001),
+                         p_sys->p_info->sequence->frame_period / 1001),
                      (uint32_t)((uint64_t)1001000000 * 27 /
-                                 p_sys->p_info->sequence->frame_period % 1001) );
+                         p_sys->p_info->sequence->frame_period % 1001) );
 
             mpeg2_custom_fbuf( p_sys->p_mpeg2dec, 1 );
 
             /* Set the first 2 reference frames */
             mpeg2_set_buf( p_sys->p_mpeg2dec, buf, NULL );
 
-            if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
-            memset( p_pic->p[0].p_pixels, 0,
-                    p_sys->p_info->sequence->width
-                     * p_sys->p_info->sequence->height );
-            memset( p_pic->p[1].p_pixels, 0x80,
-                    p_sys->p_info->sequence->width
-                     * p_sys->p_info->sequence->height / 4 );
-            memset( p_pic->p[2].p_pixels, 0x80,
-                    p_sys->p_info->sequence->width
-                     * p_sys->p_info->sequence->height / 4 );
+            if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
+           {
+               block_Release( p_block );
+               return NULL;
+           }
+
             mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
+
             /* This picture will never go through display_picture. */
-            vout_DatePicture( p_sys->p_vout, p_pic, 0 );
-            vout_DisplayPicture( p_sys->p_vout, p_pic );
+            p_pic->date = 0;
+
             /* For some reason, libmpeg2 will put this pic twice in
              * discard_picture. This can be considered a bug in libmpeg2. */
-            vout_LinkPicture( p_sys->p_vout, p_pic );
+            //vout_LinkPicture( p_sys->p_vout, p_pic );
 
-            if ( p_sys->p_synchro )
+            if( p_sys->p_synchro )
             {
                 vout_SynchroRelease( p_sys->p_synchro );
             }
@@ -363,10 +308,9 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             vout_SynchroNewPicture( p_sys->p_synchro,
                 p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
                 p_sys->p_info->current_picture->nb_fields,
-                0, 0,
-                p_sys->i_current_rate );
+                0, 0, p_sys->i_current_rate );
 
-            if ( p_sys->b_skip )
+            if( p_sys->b_skip )
             {
                 vout_SynchroTrash( p_sys->p_synchro );
             }
@@ -381,10 +325,9 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             uint8_t *buf[3];
             buf[0] = buf[1] = buf[2] = NULL;
 
-            if ( p_sys->b_after_sequence_header
-                  && ((p_sys->p_info->current_picture->flags
-                        & PIC_MASK_CODING_TYPE)
-                       == PIC_FLAG_CODING_TYPE_P) )
+            if ( p_sys->b_after_sequence_header &&
+                 ((p_sys->p_info->current_picture->flags &
+                       PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_P) )
             {
                 /* Intra-slice refresh. Simulate a blank I picture. */
                 msg_Dbg( p_dec, "intra-slice refresh stream" );
@@ -411,7 +354,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                    && !vout_SynchroChoose( p_sys->p_synchro,
                               p_sys->p_info->current_picture->flags
                                 & PIC_MASK_CODING_TYPE,
-                              p_sys->p_vout->render_time ) )
+                             /*p_sys->p_vout->render_time*/ 0 /*FIXME*/ ) )
             {
                 mpeg2_skip( p_sys->p_mpeg2dec, 1 );
                 p_sys->b_skip = 1;
@@ -423,7 +366,13 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                 mpeg2_skip( p_sys->p_mpeg2dec, 0 );
                 p_sys->b_skip = 0;
                 vout_SynchroDecode( p_sys->p_synchro );
-                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
+
+                if( (p_pic = GetNewPicture( p_dec, buf )) == NULL )
+               {
+                   block_Release( p_block );
+                   return NULL;
+               }
+
                 mpeg2_set_buf( p_sys->p_mpeg2dec, buf, p_pic );
             }
         }
@@ -441,26 +390,28 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                              & PIC_MASK_CODING_TYPE,
                             p_sys->b_garbage_pic );
                 p_sys->b_garbage_pic = 0;
-                vout_DisplayPicture( p_sys->p_vout, p_pic );
 
                 if ( p_sys->p_picture_to_destroy != p_pic )
                 {
-                    vout_DatePicture( p_sys->p_vout, p_pic,
-                        vout_SynchroDate( p_sys->p_synchro ) );
+                    p_pic->date = vout_SynchroDate( p_sys->p_synchro );
                 }
                 else
                 {
                     p_sys->p_picture_to_destroy = NULL;
-                    vout_DatePicture( p_sys->p_vout, p_pic, 0 );
+                    p_pic->date = 0;
                 }
+           return p_pic; /* FIXME */
             }
 
             if( p_sys->p_info->discard_fbuf &&
                 p_sys->p_info->discard_fbuf->id )
             {
-                p_pic = (picture_t *)p_sys->p_info->discard_fbuf->id;
-                vout_UnlinkPicture( p_sys->p_vout, p_pic );
+               //p_pic = (picture_t *)p_sys->p_info->discard_fbuf->id;
+                //vout_UnlinkPicture( p_sys->p_vout, p_pic );
             }
+
+           //return p_pic; /* FIXME */
+
             break;
 
         case STATE_INVALID:
@@ -470,8 +421,8 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
 
             msg_Warn( p_dec, "invalid picture encountered" );
             if ( ( p_sys->p_info->current_picture == NULL ) ||
-               ( ( p_sys->p_info->current_picture->flags & PIC_MASK_CODING_TYPE)
-                  != B_CODING_TYPE ) )
+               ( ( p_sys->p_info->current_picture->flags &
+                  PIC_MASK_CODING_TYPE) != B_CODING_TYPE ) )
             {
                 vout_SynchroReset( p_sys->p_synchro );
             }
@@ -502,7 +453,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                     p_sys->p_info->sequence->width
                      * p_sys->p_info->sequence->height / 4 );
 
-            if ( p_sys->b_slice_i )
+            if( p_sys->b_slice_i )
             {
                 vout_SynchroNewPicture( p_sys->p_synchro,
                             I_CODING_TYPE, 2, 0, 0, p_sys->i_current_rate );
@@ -517,47 +468,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         }
     }
 
-    block_Release( p_block );
-    return VLC_EGENERIC;
+    /* Never reached */
+    return NULL;
 }
 
 /*****************************************************************************
- * EndDecoder: libmpeg2 decoder destruction
+ * CloseDecoder: libmpeg2 decoder destruction
  *****************************************************************************/
-static int EndDecoder( decoder_t * p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_sys )
-    {
-        int i_pic;
-
-        if( p_sys->p_synchro )
-            vout_SynchroRelease( p_sys->p_synchro );
-
-        if( p_sys->p_vout )
-        {
-            /* Temporary hack to free the pictures in use by libmpeg2 */
-            for( i_pic = 0; i_pic < p_sys->p_vout->render.i_pictures; i_pic++ )
-            {
-                if( p_sys->p_vout->render.pp_picture[i_pic]->i_status ==
-                      RESERVED_PICTURE )
-                    vout_DestroyPicture( p_sys->p_vout,
-                                     p_sys->p_vout->render.pp_picture[i_pic] );
-                if( p_sys->p_vout->render.pp_picture[i_pic]->i_refcount > 0 )
-                    vout_UnlinkPicture( p_sys->p_vout,
-                                     p_sys->p_vout->render.pp_picture[i_pic] );
-            }
-
-            vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
-        }
+    if( p_sys->p_synchro ) vout_SynchroRelease( p_sys->p_synchro );
 
-        if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
+    if( p_sys->p_mpeg2dec ) mpeg2_close( p_sys->p_mpeg2dec );
 
-        free( p_sys );
-    }
-
-    return VLC_SUCCESS;
+    free( p_sys );
 }
 
 /*****************************************************************************
@@ -568,26 +495,28 @@ static picture_t *GetNewPicture( decoder_t *p_dec, uint8_t **pp_buf )
     decoder_sys_t *p_sys = p_dec->p_sys;
     picture_t *p_pic;
 
-    vlc_bool_t b_progressive = p_sys->p_info->current_picture != NULL ?
-        p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : 1;
-    vlc_bool_t b_top_field_first = p_sys->p_info->current_picture != NULL ?
-        p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : 1;
-    unsigned int i_nb_fields = p_sys->p_info->current_picture != NULL ?
-        p_sys->p_info->current_picture->nb_fields : 2;
+    p_dec->fmt_out.video.i_width = p_sys->p_info->sequence->width;
+    p_dec->fmt_out.video.i_height = p_sys->p_info->sequence->height;
+    p_dec->fmt_out.video.i_aspect = p_sys->i_aspect;
 
-    /* Get a new picture */
-    while( !( p_pic = vout_CreatePicture( p_sys->p_vout,
-              b_progressive, b_top_field_first, i_nb_fields ) ) )
-    {
-        if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
-            break;
+    p_dec->fmt_out.i_codec =
+        ( p_sys->p_info->sequence->chroma_height <
+          p_sys->p_info->sequence->height ) ?
+        VLC_FOURCC('I','4','2','0') : VLC_FOURCC('I','4','2','2');
 
-        msleep( VOUT_OUTMEM_SLEEP );
-    }
+    /* Get a new picture */
+    p_pic = p_dec->pf_vout_buffer_new( p_dec );
 
     if( p_pic == NULL ) return NULL;
 
-    vout_LinkPicture( p_sys->p_vout, p_pic );
+    p_pic->b_progressive = p_sys->p_info->current_picture != NULL ?
+        p_sys->p_info->current_picture->flags & PIC_FLAG_PROGRESSIVE_FRAME : 1;
+    p_pic->b_top_field_first = p_sys->p_info->current_picture != NULL ?
+        p_sys->p_info->current_picture->flags & PIC_FLAG_TOP_FIELD_FIRST : 1;
+    p_pic->i_nb_fields = p_sys->p_info->current_picture != NULL ?
+        p_sys->p_info->current_picture->nb_fields : 2;
+
+    //vout_LinkPicture( p_sys->p_vout, p_pic );
 
     pp_buf[0] = p_pic->p[0].p_pixels;
     pp_buf[1] = p_pic->p[1].p_pixels;
index fc73cc3..ccfc99b 100644 (file)
@@ -2,7 +2,7 @@
  * lpcm.c: lpcm decoder module
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: lpcm.c,v 1.17 2003/09/02 20:19:25 gbazin Exp $
+ * $Id: lpcm.c,v 1.18 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Henri Fallon <henri@videolan.org>
@@ -104,8 +104,8 @@ 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('l','p','c','m')
-         && p_dec->p_fifo->i_fourcc != VLC_FOURCC('l','p','c','b') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('l','p','c','m')
+         && p_dec->fmt_in.i_codec != VLC_FOURCC('l','p','c','b') )
     {   
         return VLC_EGENERIC;
     }
index dccabe7..8918ff6 100644 (file)
@@ -2,7 +2,7 @@
  * mpeg_audio.c: parse MPEG audio sync info and packetize the stream
  *****************************************************************************
  * Copyright (C) 2001-2003 VideoLAN
- * $Id: mpeg_audio.c,v 1.21 2003/10/23 21:28:11 gbazin Exp $
+ * $Id: mpeg_audio.c,v 1.22 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Eric Petit <titer@videolan.org>
@@ -51,32 +51,15 @@ struct decoder_sys_t
      */
     int        i_state;
 
-    block_t *p_chain;
     block_bytestream_t bytestream;
 
     /*
-     * Decoder output properties
-     */
-    aout_instance_t *     p_aout;                                  /* opaque */
-    aout_input_t *        p_aout_input;                            /* opaque */
-    audio_sample_format_t aout_format;
-    aout_buffer_t *       p_aout_buffer; /* current aout buffer being filled */
-
-    /*
-     * Packetizer output properties
-     */
-    sout_packetizer_input_t *p_sout_input;
-    sout_format_t           sout_format;
-    sout_buffer_t *         p_sout_buffer;            /* current sout buffer */
-
-    /*
      * Common properties
      */
-    uint8_t               *p_out_buffer;                    /* output buffer */
     audio_date_t          end_date;
     unsigned int          i_current_layer;
 
-    mtime_t pts;
+    mtime_t i_pts;
 
     int i_frame_size, i_free_frame_size;
     unsigned int i_channels_conf, i_channels;
@@ -90,7 +73,8 @@ enum {
     STATE_SYNC,
     STATE_HEADER,
     STATE_NEXT_SYNC,
-    STATE_DATA
+    STATE_GET_DATA,
+    STATE_SEND_DATA
 };
 
 /* This isn't the place to put mad-specific stuff. However, it makes the
@@ -104,17 +88,14 @@ enum {
 /****************************************************************************
  * Local prototypes
  ****************************************************************************/
-static int OpenDecoder   ( vlc_object_t * );
-static int OpenPacketizer( vlc_object_t * );
+static int  OpenDecoder   ( vlc_object_t * );
+static int  OpenPacketizer( vlc_object_t * );
+static void CloseDecoder  ( vlc_object_t * );
+static void *DecodeBlock  ( decoder_t *, block_t ** );
 
-static int InitDecoder   ( decoder_t * );
-static int RunDecoder    ( decoder_t *, block_t * );
-static int EndDecoder    ( decoder_t * );
-
-static int GetOutBuffer ( decoder_t *, uint8_t ** );
-static int GetAoutBuffer( decoder_t *, aout_buffer_t ** );
-static int GetSoutBuffer( decoder_t *, sout_buffer_t ** );
-static int SendOutBuffer( decoder_t * );
+static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
+static aout_buffer_t *GetAoutBuffer( decoder_t * );
+static block_t       *GetSoutBuffer( decoder_t * );
 
 static int SyncInfo( uint32_t i_header, unsigned int * pi_channels,
                      unsigned int * pi_channels_conf,
@@ -129,12 +110,12 @@ static int SyncInfo( uint32_t i_header, unsigned int * pi_channels,
 vlc_module_begin();
     set_description( _("MPEG audio layer I/II/III parser") );
     set_capability( "decoder", 100 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 
     add_submodule();
     set_description( _("MPEG audio layer I/II/III packetizer") );
     set_capability( "packetizer", 10 );
-    set_callbacks( OpenPacketizer, NULL );
+    set_callbacks( OpenPacketizer, CloseDecoder );
 vlc_module_end();
 
 /*****************************************************************************
@@ -143,24 +124,39 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC( 'm', 'p', 'g', 'a') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('m','p','g','a') )
     {
         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 =
+    if( ( p_dec->p_sys = 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;
+
+    /* Misc init */
+    p_sys->b_packetizer = VLC_FALSE;
+    p_sys->i_state = STATE_NOSYNC;
+    aout_DateSet( &p_sys->end_date, 0 );
+    p_sys->bytestream = block_BytestreamInit( p_dec );
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('m','p','g','a');
+
+    /* Set callback */
+    p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+
+    /* Start with the minimum size for a free bitrate frame */
+    p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
 
     return VLC_SUCCESS;
 }
@@ -176,66 +172,34 @@ static int OpenPacketizer( vlc_object_t *p_this )
     return i_ret;
 }
 
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    p_dec->p_sys->i_state = STATE_NOSYNC;
-
-    p_dec->p_sys->p_out_buffer = NULL;
-    aout_DateSet( &p_dec->p_sys->end_date, 0 );
-
-    p_dec->p_sys->p_aout = NULL;
-    p_dec->p_sys->p_aout_input = NULL;
-    p_dec->p_sys->p_aout_buffer = NULL;
-    p_dec->p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','a');
-
-    p_dec->p_sys->p_sout_input = NULL;
-    p_dec->p_sys->p_sout_buffer = NULL;
-    p_dec->p_sys->sout_format.i_cat = AUDIO_ES;
-    p_dec->p_sys->sout_format.i_fourcc = VLC_FOURCC('m','p','g','a');
-
-    /* Start with the minimum size for a free bitrate frame */
-    p_dec->p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
-
-    p_dec->p_sys->p_chain = NULL;
-
-    return VLC_SUCCESS;
-}
-
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function is called just after the thread is launched.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     uint8_t p_header[MAD_BUFFER_GUARD];
     uint32_t i_header;
+    uint8_t *p_buf;
+    void *p_out_buffer;
+
+    if( !pp_block || !*pp_block ) return NULL;
 
-    if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
+    if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
     {
         /* We've just started the stream, wait for the first PTS. */
-        block_Release( p_block );
-        return VLC_SUCCESS;
+        block_Release( *pp_block );
+        return NULL;
     }
 
-    if( p_block->b_discontinuity )
+    if( (*pp_block)->b_discontinuity )
     {
-        p_sys->i_state = STATE_SYNC;
+        p_sys->i_state = STATE_NOSYNC;
     }
 
-    if( p_sys->p_chain )
-    {
-        block_ChainAppend( &p_sys->p_chain, p_block );
-    }
-    else
-    {
-        block_ChainAppend( &p_sys->p_chain, p_block );
-        p_sys->bytestream = block_BytestreamInit( p_dec, p_sys->p_chain, 0 );
-    }
+    block_BytestreamPush( &p_sys->bytestream, *pp_block );
 
     while( 1 )
     {
@@ -256,30 +220,21 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             }
             if( p_sys->i_state != STATE_SYNC )
             {
-                if( block_PeekByte( &p_sys->bytestream, p_header )
-                    == VLC_SUCCESS && p_header[0] == 0xff )
-                {
-                    /* Start of a sync word, need more data */
-                    return VLC_SUCCESS;
-                }
-
-                block_ChainRelease( p_sys->p_chain );
-                p_sys->p_chain = NULL;
+                block_BytestreamFlush( &p_sys->bytestream );
 
                 /* Need more data */
-                return VLC_SUCCESS;
+                return NULL;
             }
 
         case STATE_SYNC:
             /* New frame, set the Presentation Time Stamp */
-            p_sys->pts = p_sys->bytestream.p_block->i_pts;
-            if( p_sys->pts != 0 &&
-                p_sys->pts != aout_DateGet( &p_sys->end_date ) )
+            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
+            if( p_sys->i_pts != 0 &&
+                p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
             {
-                aout_DateSet( &p_sys->end_date, p_sys->pts );
+                aout_DateSet( &p_sys->end_date, p_sys->i_pts );
             }
             p_sys->i_state = STATE_HEADER;
-            break;
 
         case STATE_HEADER:
             /* Get MPGA frame header (MPGA_HEADER_SIZE bytes) */
@@ -287,7 +242,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                                  MPGA_HEADER_SIZE ) != VLC_SUCCESS )
             {
                 /* Need more data */
-                return VLC_SUCCESS;
+                return NULL;
             }
 
             /* Build frame header */
@@ -334,7 +289,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                                        MAD_BUFFER_GUARD ) != VLC_SUCCESS )
             {
                 /* Need more data */
-                return VLC_SUCCESS;
+                return NULL;
             }
 
             if( p_header[0] == 0xff && (p_header[1] & 0xe0) == 0xe0 )
@@ -359,23 +314,9 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                                               &i_next_max_frame_size,
                                               &i_next_layer );
 
-                if( i_next_frame_size == -1 )
-                {
-                    msg_Dbg( p_dec, "emulated start code on next frame" );
-                    block_SkipByte( &p_sys->bytestream );
-                    p_sys->i_state = STATE_NOSYNC;
-                    break;
-                }
-
                 /* Free bitrate only */
-                if( p_sys->i_bit_rate == 0 )
+                if( p_sys->i_bit_rate == 0 && i_next_frame_size == -1 )
                 {
-                    if( i_next_bit_rate != 0 )
-                    {
-                        p_sys->i_frame_size++;
-                        break;
-                    }
-
                     if( (unsigned int)p_sys->i_frame_size >
                         p_sys->i_max_frame_size )
                     {
@@ -387,6 +328,17 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                         p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
                         break;
                     }
+
+                    p_sys->i_frame_size++;
+                    break;
+                }
+
+                if( i_next_frame_size == -1 )
+                {
+                    msg_Dbg( p_dec, "emulated start code on next frame" );
+                    block_SkipByte( &p_sys->bytestream );
+                    p_sys->i_state = STATE_NOSYNC;
+                    break;
                 }
 
                 /* Check info is in sync with previous one */
@@ -408,12 +360,35 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                     p_sys->i_state = STATE_NOSYNC;
                     break;
                 }
+
+                /* Free bitrate only */
+                if( p_sys->i_bit_rate == 0 )
+                {
+                    if( i_next_bit_rate != 0 )
+                    {
+                        p_sys->i_frame_size++;
+                        break;
+                    }
+                }
+
             }
             else
             {
                 /* Free bitrate only */
                 if( p_sys->i_bit_rate == 0 )
                 {
+                    if( (unsigned int)p_sys->i_frame_size >
+                        p_sys->i_max_frame_size )
+                    {
+                        msg_Dbg( p_dec, "frame too big %d > %d "
+                                 "(emulated startcode ?)", p_sys->i_frame_size,
+                                 p_sys->i_max_frame_size );
+                        block_SkipByte( &p_sys->bytestream );
+                        p_sys->i_state = STATE_NOSYNC;
+                        p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
+                        break;
+                    }
+
                     p_sys->i_frame_size++;
                     break;
                 }
@@ -425,254 +400,156 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                 break;
             }
 
-            if( GetOutBuffer( p_dec, &p_sys->p_out_buffer ) != VLC_SUCCESS )
+            p_sys->i_state = STATE_SEND_DATA;
+            break;
+
+        case STATE_GET_DATA:
+            /* Make sure we have enough data.
+             * (Not useful if we went through NEXT_SYNC) */
+            if( block_WaitBytes( &p_sys->bytestream,
+                                 p_sys->i_frame_size ) != VLC_SUCCESS )
             {
-                return VLC_EGENERIC;
+                /* Need more data */
+                return NULL;
             }
+            p_sys->i_state = STATE_SEND_DATA;
 
-            /* Free bitrate only */
-            if( p_sys->i_bit_rate == 0 )
+        case STATE_SEND_DATA:
+            if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
             {
-                p_sys->i_free_frame_size = p_sys->i_frame_size;
+                //p_dec->b_error = VLC_TRUE;
+                return NULL;
             }
 
-            p_sys->i_state = STATE_DATA;
-
-        case STATE_DATA:
-            /* Copy the whole frame into the buffer */
-            if( block_GetBytes( &p_sys->bytestream, p_sys->p_out_buffer,
-                                p_sys->i_frame_size ) != VLC_SUCCESS )
+            /* Free bitrate only */
+            if( p_sys->i_bit_rate == 0 )
             {
-                /* Need more data */
-                return VLC_SUCCESS;
+                p_sys->i_free_frame_size = p_sys->i_frame_size;
             }
 
-            p_sys->p_chain = block_BytestreamFlush( &p_sys->bytestream );
+            /* Copy the whole frame into the buffer. When we reach this point
+             * we already know we have enough data available. */
+            block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
 
             /* Get beginning of next frame for libmad */
             if( !p_sys->b_packetizer )
             {
-                memcpy( p_sys->p_out_buffer + p_sys->i_frame_size,
+                memcpy( p_buf + p_sys->i_frame_size,
                         p_header, MAD_BUFFER_GUARD );
             }
 
-            SendOutBuffer( p_dec );
             p_sys->i_state = STATE_NOSYNC;
 
             /* Make sure we don't reuse the same pts twice */
-            if( p_sys->pts == p_sys->bytestream.p_block->i_pts )
-                p_sys->pts = p_sys->bytestream.p_block->i_pts = 0;
+            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
+                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
+
+            /* So p_block doesn't get re-added several times */
+            *pp_block = block_BytestreamPop( &p_sys->bytestream );
+
+            return p_out_buffer;
         }
     }
 
-    return VLC_SUCCESS;
+    return NULL;
 }
 
 /*****************************************************************************
  * GetOutBuffer:
  *****************************************************************************/
-static int GetOutBuffer( decoder_t *p_dec, uint8_t **pp_out_buffer )
+static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i_ret;
+    uint8_t *p_buf;
+
+    if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
+    {
+        msg_Info( p_dec, "MPGA channels:%d samplerate:%d bitrate:%d",
+                  p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
+
+        aout_DateInit( &p_sys->end_date, p_sys->i_rate );
+        aout_DateSet( &p_sys->end_date, p_sys->i_pts );
+    }
+
+    p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
+    p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
+    p_dec->fmt_out.audio.i_bitrate  = p_sys->i_bit_rate;
+    p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
+    p_dec->fmt_out.audio.i_bytes_per_frame =
+        p_sys->i_max_frame_size + MAD_BUFFER_GUARD;
+
+    p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
 
     if( p_sys->b_packetizer )
     {
-        i_ret = GetSoutBuffer( p_dec, &p_sys->p_sout_buffer );
-        *pp_out_buffer =
-            p_sys->p_sout_buffer ? p_sys->p_sout_buffer->p_buffer : NULL;
+        block_t *p_sout_buffer = GetSoutBuffer( p_dec );
+        p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
+        *pp_out_buffer = p_sout_buffer;
     }
     else
     {
-        i_ret = GetAoutBuffer( p_dec, &p_sys->p_aout_buffer );
-        *pp_out_buffer =
-            p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer : NULL;
+        aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
+        p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
+        *pp_out_buffer = p_aout_buffer;
     }
 
-    return i_ret;
+    return p_buf;
 }
 
 /*****************************************************************************
  * GetAoutBuffer:
  *****************************************************************************/
-static int GetAoutBuffer( decoder_t *p_dec, aout_buffer_t **pp_buffer )
+static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    aout_buffer_t *p_buf;
 
-    if( p_sys->p_aout_input != NULL &&
-        ( p_sys->aout_format.i_rate != p_sys->i_rate
-        || p_sys->aout_format.i_original_channels != p_sys->i_channels_conf
-        || p_sys->aout_format.i_bytes_per_frame !=
-           p_sys->i_max_frame_size + MAD_BUFFER_GUARD
-        || p_sys->aout_format.i_frame_length != p_sys->i_frame_length
-        || p_sys->i_current_layer != p_sys->i_layer ) )
-    {
-        /* Parameters changed - this should not happen. */
-        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
-        p_sys->p_aout_input = NULL;
-    }
+    p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length );
+    if( p_buf == NULL ) return NULL;
 
-    /* Creating the audio input if not created yet. */
-    if( p_sys->p_aout_input == NULL )
-    {
-        p_sys->i_current_layer = p_sys->i_layer;
-        if( p_sys->i_layer == 3 )
-        {
-            p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','3');
-        }
-        else
-        {
-            p_sys->aout_format.i_format = VLC_FOURCC('m','p','g','a');
-        }
+    p_buf->start_date = aout_DateGet( &p_sys->end_date );
+    p_buf->end_date =
+        aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
 
-        p_sys->aout_format.i_rate = p_sys->i_rate;
-        p_sys->aout_format.i_original_channels = p_sys->i_channels_conf;
-        p_sys->aout_format.i_physical_channels
-            = p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
-        p_sys->aout_format.i_bytes_per_frame = p_sys->i_max_frame_size
-            + MAD_BUFFER_GUARD;
-        p_sys->aout_format.i_frame_length = p_sys->i_frame_length;
-        aout_DateInit( &p_sys->end_date, p_sys->i_rate );
-        aout_DateSet( &p_sys->end_date, p_sys->pts );
-        p_sys->p_aout_input = aout_DecNew( p_dec,
-                                           &p_sys->p_aout,
-                                           &p_sys->aout_format );
-        if( p_sys->p_aout_input == NULL )
-        {
-            *pp_buffer = NULL;
-            return VLC_EGENERIC;
-        }
-    }
-
-    *pp_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
-                                    p_sys->i_frame_length );
-    if( *pp_buffer == NULL )
-    {
-        return VLC_EGENERIC;
-    }
+    /* Hack for libmad filter */
+    p_buf->i_nb_bytes = p_sys->i_frame_size + MAD_BUFFER_GUARD;
 
-    (*pp_buffer)->start_date = aout_DateGet( &p_sys->end_date );
-    (*pp_buffer)->end_date =
-         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
-
-    return VLC_SUCCESS;
+    return p_buf;
 }
 
 /*****************************************************************************
  * GetSoutBuffer:
  *****************************************************************************/
-static int GetSoutBuffer( decoder_t *p_dec, sout_buffer_t **pp_buffer )
+static block_t *GetSoutBuffer( decoder_t *p_dec )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
 
-    if( p_sys->p_sout_input != NULL &&
-        ( p_sys->sout_format.i_sample_rate != (int)p_sys->i_rate
-          || p_sys->sout_format.i_channels != (int)p_sys->i_channels ) )
-    {
-        /* Parameters changed - this should not happen. */
-    }
+    p_block = block_New( p_dec, p_sys->i_frame_size );
+    if( p_block == NULL ) return NULL;
 
-    /* Creating the sout input if not created yet. */
-    if( p_sys->p_sout_input == NULL )
-    {
-        p_sys->sout_format.i_sample_rate = p_sys->i_rate;
-        p_sys->sout_format.i_channels    = p_sys->i_channels;
-        p_sys->sout_format.i_block_align = 0;
-        p_sys->sout_format.i_bitrate     = p_sys->i_bit_rate;
-        p_sys->sout_format.i_extra_data  = 0;
-        p_sys->sout_format.p_extra_data  = NULL;
+    p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
 
-        aout_DateInit( &p_sys->end_date, p_sys->i_rate );
-        aout_DateSet( &p_sys->end_date, p_sys->pts );
-
-        p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
-        if( p_sys->p_sout_input == NULL )
-        {
-            msg_Err( p_dec, "cannot add a new stream" );
-            *pp_buffer = NULL;
-            return VLC_EGENERIC;
-        }
-        msg_Info( p_dec, "MPGA channels:%d samplerate:%d bitrate:%d",
-                  p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
-    }
-
-    *pp_buffer = sout_BufferNew( p_sys->p_sout_input->p_sout,
-                                 p_sys->i_frame_size );
-    if( *pp_buffer == NULL )
-    {
-        return VLC_EGENERIC;
-    }
+    p_block->i_length =
+        aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length ) -
+            p_block->i_pts;
 
-    (*pp_buffer)->i_pts =
-        (*pp_buffer)->i_dts = aout_DateGet( &p_sys->end_date );
-
-    (*pp_buffer)->i_length =
-        aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length )
-        - (*pp_buffer)->i_pts;
-
-    return VLC_SUCCESS;
+    return p_block;
 }
 
 /*****************************************************************************
- * SendOutBuffer:
+ * CloseDecoder: clean up the decoder
  *****************************************************************************/
-static int SendOutBuffer( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_sys->b_packetizer )
-    {
-        sout_InputSendBuffer( p_sys->p_sout_input, p_sys->p_sout_buffer );
-        p_sys->p_sout_buffer = NULL;
-    }
-    else
-    {
-        /* We have all we need, send the buffer to the aout core. */
-        p_sys->p_aout_buffer->i_nb_bytes =
-            p_sys->i_frame_size + MAD_BUFFER_GUARD;
-        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input,
-                      p_sys->p_aout_buffer );
-        p_sys->p_aout_buffer = NULL;
-    }
-
-    p_sys->p_out_buffer = NULL;
+    block_BytestreamRelease( &p_sys->bytestream );
 
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * EndDecoder: clean up the decoder
- *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
-{
-    if( p_dec->p_sys->p_aout_input != NULL )
-    {
-        if( p_dec->p_sys->p_aout_buffer )
-        {
-            aout_DecDeleteBuffer( p_dec->p_sys->p_aout,
-                                  p_dec->p_sys->p_aout_input,
-                                  p_dec->p_sys->p_aout_buffer );
-        }
-
-        aout_DecDelete( p_dec->p_sys->p_aout, p_dec->p_sys->p_aout_input );
-    }
-
-    if( p_dec->p_sys->p_sout_input != NULL )
-    {
-        if( p_dec->p_sys->p_sout_buffer )
-        {
-            sout_BufferDelete( p_dec->p_sys->p_sout_input->p_sout,
-                               p_dec->p_sys->p_sout_buffer );
-        }
-
-        sout_InputDelete( p_dec->p_sys->p_sout_input );
-    }
-
-    if( p_dec->p_sys->p_chain ) block_ChainRelease( p_dec->p_sys->p_chain );
-
-    free( p_dec->p_sys );
-
-    return VLC_SUCCESS;
+    free( p_sys );
 }
 
 /*****************************************************************************
index 83fc9bf..390d22d 100644 (file)
@@ -2,7 +2,7 @@
  * rawvideo.c: Pseudo video decoder/packetizer for raw video data
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: rawvideo.c,v 1.7 2003/10/24 21:27:06 gbazin Exp $
+ * $Id: rawvideo.c,v 1.8 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
 #include <string.h>                                              /* strdup() */
 
 #include <vlc/vlc.h>
-#include <vlc/vout.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
-#include <vlc/sout.h>
 
 #include "codecs.h"
 
@@ -49,17 +47,6 @@ struct decoder_sys_t
     int i_raw_size;
 
     /*
-     * Output properties
-     */
-    vout_thread_t *p_vout;
-
-    /*
-     * Packetizer output properties
-     */
-    sout_packetizer_input_t *p_sout_input;
-    sout_format_t           sout_format;
-
-    /*
      * Common properties
      */
     mtime_t i_pts;
@@ -69,15 +56,14 @@ struct decoder_sys_t
 /****************************************************************************
  * Local prototypes
  ****************************************************************************/
-static int OpenDecoder   ( vlc_object_t * );
-static int OpenPacketizer( vlc_object_t * );
+static int  OpenDecoder   ( vlc_object_t * );
+static int  OpenPacketizer( vlc_object_t * );
+static void CloseDecoder  ( vlc_object_t * );
 
-static int InitDecoder   ( decoder_t * );
-static int RunDecoder    ( decoder_t *, block_t * );
-static int EndDecoder    ( decoder_t * );
+static void *DecodeBlock  ( decoder_t *, block_t ** );
 
-static int DecodeFrame   ( decoder_t *, block_t * );
-static int SendFrame     ( decoder_t *, block_t * );
+static picture_t *DecodeFrame( decoder_t *, block_t * );
+static block_t   *SendFrame  ( decoder_t *, block_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -85,25 +71,23 @@ static int SendFrame     ( decoder_t *, block_t * );
 vlc_module_begin();
     set_description( _("Pseudo Raw Video decoder") );
     set_capability( "decoder", 50 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 
     add_submodule();
     set_description( _("Pseudo Raw Video packetizer") );
     set_capability( "packetizer", 100 );
-    set_callbacks( OpenPacketizer, NULL );
+    set_callbacks( OpenPacketizer, CloseDecoder );
 vlc_module_end();
 
 /*****************************************************************************
  * OpenDecoder: probe the decoder and return score
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to choose.
  *****************************************************************************/
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    switch( p_dec->p_fifo->i_fourcc )
+    switch( p_dec->fmt_in.i_codec )
     {
         /* Planar YUV */
         case VLC_FOURCC('I','4','4','4'):
@@ -129,18 +113,47 @@ static int OpenDecoder( vlc_object_t *p_this )
             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 =
+    if( ( p_dec->p_sys = p_sys =
           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
         msg_Err( p_dec, "out of memory" );
         return VLC_EGENERIC;
     }
+    /* Misc init */
     p_dec->p_sys->b_packetizer = VLC_FALSE;
+    p_sys->i_pts = 0;
+
+    if( p_dec->fmt_in.video.i_width <= 0 ||
+        p_dec->fmt_in.video.i_height <= 0 )
+    {
+        msg_Err( p_dec, "invalid display size %dx%d",
+                 p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );
+        return VLC_EGENERIC;
+    }
+
+    /* Find out p_vdec->i_raw_size */
+    vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec,
+                     p_dec->fmt_in.video.i_width,
+                     p_dec->fmt_in.video.i_height,
+                     p_dec->fmt_in.video.i_aspect );
+    p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel *
+        p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8;
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+    p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
+    //if( !p_dec->fmt_in.video.i_aspect )
+    {
+        p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
+            p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
+    }
+
+    /* Set callbacks */
+    p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
 
     return VLC_SUCCESS;
 }
@@ -156,96 +169,27 @@ static int OpenPacketizer( vlc_object_t *p_this )
     return i_ret;
 }
 
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    video_frame_format_t format;
-
-    p_sys->i_pts = 0;
-
-    p_sys->p_sout_input = NULL;
-    p_sys->sout_format.i_cat = VIDEO_ES;
-    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;
-
-#define bih ((BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader)
-    if( bih == NULL )
-    {
-        msg_Err( p_dec, "info missing, fatal" );
-        return VLC_EGENERIC;
-    }
-    if( bih->biWidth <= 0 || bih->biHeight <= 0 )
-    {
-        msg_Err( p_dec, "invalid display size %dx%d",
-                 bih->biWidth, bih->biHeight );
-        return VLC_EGENERIC;
-    }
-
-    if( p_sys->b_packetizer )
-    {
-        /* add an input for the stream ouput */
-        p_sys->sout_format.i_width  = bih->biWidth;
-        p_sys->sout_format.i_height = bih->biHeight;
-        p_sys->sout_format.i_fourcc = p_dec->p_fifo->i_fourcc;
-
-        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;
-        }
-    }
-    else
-    {
-        /* Initialize video output */
-        p_sys->p_vout = vout_Request( p_dec, NULL,
-                                      bih->biWidth, bih->biHeight,
-                                      p_dec->p_fifo->i_fourcc,
-                                      VOUT_ASPECT_FACTOR * bih->biWidth /
-                                      bih->biHeight );
-        if( p_sys->p_vout == NULL )
-        {
-            msg_Err( p_dec, "failed to create vout" );
-            return VLC_EGENERIC;
-        }
-    }
-
-    /* Find out p_vdec->i_raw_size */
-    vout_InitFormat( &format, p_dec->p_fifo->i_fourcc,
-                     bih->biWidth, bih->biHeight,
-                     bih->biWidth * VOUT_ASPECT_FACTOR / bih->biHeight );
-    p_sys->i_raw_size = format.i_bits_per_pixel *
-        format.i_width * format.i_height / 8;
-#undef bih
-
-    return VLC_SUCCESS;
-}
-
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
- * This function must be fed with ogg packets.
+ * This function must be fed with complete frames.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    int i_ret;
+    block_t *p_block;
+    void *p_buf;
+
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
 
-#if 0
-    if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
+    if( !p_sys->i_pts && !p_block->i_pts )
     {
         /* We've just started the stream, wait for the first PTS. */
         block_Release( p_block );
-        return VLC_SUCCESS;
+        return NULL;
     }
-#endif
 
     /* Date management */
     if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
@@ -259,23 +203,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                   p_block->i_buffer, p_sys->i_raw_size );
 
         block_Release( p_block );
-        return VLC_EGENERIC;
+        return NULL;
     }
 
     if( p_sys->b_packetizer )
     {
-        i_ret = SendFrame( p_dec, p_block );
+        p_buf = SendFrame( p_dec, p_block );
     }
     else
     {
-        i_ret = DecodeFrame( p_dec, p_block );
+        p_buf = DecodeFrame( p_dec, p_block );
     }
 
     /* Date management: 1 frame per packet */
     p_sys->i_pts += ( I64C(1000000) * 1.0 / 25 /*FIXME*/ );
+    *pp_block = NULL;
 
-    block_Release( p_block );
-    return i_ret;
+    return p_buf;
 }
 
 /*****************************************************************************
@@ -306,70 +250,44 @@ static void FillPicture( decoder_t *p_dec, block_t *p_block, picture_t *p_pic )
 /*****************************************************************************
  * DecodeFrame: decodes a video frame.
  *****************************************************************************/
-static int DecodeFrame( decoder_t *p_dec, block_t *p_block )
+static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     picture_t *p_pic;
 
     /* Get a new picture */
-    while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
+    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    if( !p_pic )
     {
-        if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
-        {
-            return VLC_EGENERIC;
-        }
-        msleep( VOUT_OUTMEM_SLEEP );
+        block_Release( p_block );
+        return NULL;
     }
-    if( !p_pic ) return VLC_EGENERIC;
 
     FillPicture( p_dec, p_block, p_pic );
 
-    vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts );
-    vout_DisplayPicture( p_sys->p_vout, p_pic );
+    p_pic->date = p_sys->i_pts;
 
-    return VLC_SUCCESS;
+    block_Release( p_block );
+    return p_pic;
 }
 
 /*****************************************************************************
  * SendFrame: send a video frame to the stream output.
  *****************************************************************************/
-static int SendFrame( decoder_t *p_dec, block_t *p_block )
+static block_t *SendFrame( decoder_t *p_dec, block_t *p_block )
 {
     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_block->i_buffer );
-
-    if( !p_sout_buffer ) return VLC_EGENERIC;
+    p_block->i_dts = p_block->i_pts = p_sys->i_pts;
 
-    p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
-                             p_block->p_buffer, p_block->i_buffer );
-
-    p_sout_buffer->i_dts = p_sout_buffer->i_pts = p_sys->i_pts;
-
-    sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer );
-
-    return VLC_SUCCESS;
+    return p_block;
 }
 
 /*****************************************************************************
- * EndDecoder: decoder destruction
+ * CloseDecoder: decoder destruction
  *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    if( !p_sys->b_packetizer )
-    {
-        vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
-    }
-
-    if( p_sys->p_sout_input != NULL )
-    {
-        sout_InputDelete( p_sys->p_sout_input );
-    }
-
-    free( p_sys );
-
-    return VLC_SUCCESS;
+    decoder_t *p_dec = (decoder_t*)p_this;
+    free( p_dec->p_sys );
 }
index ec1c733..e357830 100755 (executable)
@@ -2,7 +2,7 @@
  * speex.c: speex decoder/packetizer module making use of libspeex.
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: speex.c,v 1.2 2003/10/22 18:24:08 gbazin Exp $
+ * $Id: speex.c,v 1.3 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
 #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>
@@ -54,6 +49,7 @@ struct decoder_sys_t
      * Input properties
      */
     int i_headers;
+    int i_frame_in_packet;
 
     /*
      * Speex properties
@@ -64,22 +60,9 @@ struct decoder_sys_t
     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;
+    audio_date_t end_date;
 
 };
 
@@ -97,17 +80,16 @@ static int pi_channels_maps[6] =
 /****************************************************************************
  * Local prototypes
  ****************************************************************************/
-static int OpenDecoder   ( vlc_object_t * );
-static int OpenPacketizer( vlc_object_t * );
+static int  OpenDecoder   ( vlc_object_t * );
+static int  OpenPacketizer( vlc_object_t * );
+static void CloseDecoder  ( vlc_object_t * );
 
-static int InitDecoder   ( decoder_t * );
-static int RunDecoder    ( decoder_t *, block_t * );
-static int EndDecoder    ( decoder_t * );
+static void *DecodeBlock  ( decoder_t *, block_t ** );
+static int  ProcessHeader ( decoder_t *, ogg_packet * );
+static void *ProcessPacket( decoder_t *, ogg_packet *, block_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 aout_buffer_t *DecodePacket( decoder_t *, ogg_packet * );
+static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * );
 
 static void ParseSpeexComments( decoder_t *, ogg_packet * );
 
@@ -117,12 +99,12 @@ static void ParseSpeexComments( decoder_t *, ogg_packet * );
 vlc_module_begin();
     set_description( _("Speex audio decoder") );
     set_capability( "decoder", 100 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 
     add_submodule();
     set_description( _("Speex audio packetizer") );
     set_capability( "packetizer", 100 );
-    set_callbacks( OpenPacketizer, NULL );
+    set_callbacks( OpenPacketizer, CloseDecoder );
 vlc_module_end();
 
 /*****************************************************************************
@@ -131,18 +113,15 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','x',' ') )
+    if( p_dec->fmt_in.i_codec != 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 =
+    if( ( p_dec->p_sys = p_sys =
           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
         msg_Err( p_dec, "out of memory" );
@@ -150,6 +129,23 @@ static int OpenDecoder( vlc_object_t *p_this )
     }
     p_dec->p_sys->b_packetizer = VLC_FALSE;
 
+    aout_DateSet( &p_sys->end_date, 0 );
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = AUDIO_ES;
+    p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
+
+    /* Set callbacks */
+    p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+
+    p_sys->i_headers = 0;
+    p_sys->p_state = NULL;
+    p_sys->p_header = NULL;
+    p_sys->i_frame_in_packet = 0;
+
     return VLC_SUCCESS;
 }
 
@@ -159,53 +155,42 @@ static int OpenPacketizer( vlc_object_t *p_this )
 
     int i_ret = OpenDecoder( p_this );
 
-    if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
+    if( i_ret == VLC_SUCCESS )
+    {
+        p_dec->p_sys->b_packetizer = VLC_TRUE;
+        p_dec->fmt_out.i_codec = VLC_FOURCC('s','p','x',' ');
+    }
 
     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
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function must be fed with ogg packets.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void *DecodeBlock( decoder_t *p_dec, block_t **pp_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;
+    if( !pp_block ) return NULL;
+
+    if( *pp_block )
+    {
+        /* Block to Ogg packet */
+        oggpacket.packet = (*pp_block)->p_buffer;
+        oggpacket.bytes = (*pp_block)->i_buffer;
+    }
+    else
+    {
+        if( p_sys->b_packetizer ) return NULL;
+
+        /* Block to Ogg packet */
+        oggpacket.packet = NULL;
+        oggpacket.bytes = 0;
+    }
+
     oggpacket.granulepos = -1;
     oggpacket.b_o_s = 0;
     oggpacket.e_o_s = 0;
@@ -217,23 +202,13 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         if( ProcessHeader( p_dec, &oggpacket ) != VLC_SUCCESS )
         {
             msg_Err( p_dec, "Initial Speex header is corrupted" );
-            block_Release( p_block );
-            return VLC_EGENERIC;
+            block_Release( *pp_block );
+            return NULL;
         }
 
         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;
-        }
+        return ProcessPacket( p_dec, &oggpacket, pp_block );
     }
 
     if( p_sys->i_headers == 1 )
@@ -242,40 +217,10 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         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;
-        }
+        return ProcessPacket( p_dec, &oggpacket, pp_block );
     }
 
-    i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
-    block_Release( p_block );
-    return i_ret;
+    return ProcessPacket( p_dec, &oggpacket, pp_block );
 }
 
 /*****************************************************************************
@@ -330,27 +275,6 @@ static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
              ( 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 );
@@ -370,20 +294,14 @@ static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
         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 =
+    /* Setup the format */
+    p_dec->fmt_out.audio.i_physical_channels =
+        p_dec->fmt_out.audio.i_original_channels =
             pi_channels_maps[p_header->nb_channels];
-    p_sys->aout_format.i_rate = p_header->rate;
+    p_dec->fmt_out.audio.i_channels = p_header->nb_channels;
+    p_dec->fmt_out.audio.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;
-    }
+    aout_DateInit( &p_sys->end_date, p_header->rate );
 
     return VLC_SUCCESS;
 }
@@ -391,72 +309,89 @@ static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
 /*****************************************************************************
  * ProcessPacket: processes a Speex packet.
  *****************************************************************************/
-static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
-                          mtime_t i_pts )
+static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
+                            block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block = *pp_block;
 
     /* Date management */
-    if( i_pts > 0 && i_pts != aout_DateGet( &p_sys->end_date ) )
+    if( p_block && p_block->i_pts > 0 &&
+        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
     {
-        aout_DateSet( &p_sys->end_date, i_pts );
+        aout_DateSet( &p_sys->end_date, p_block->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_block ) block_Release( p_block );
+        return NULL;
     }
 
+    *pp_block = NULL; /* To avoid being fed the same packet again */
+
     if( p_sys->b_packetizer )
     {
-        return SendPacket( p_dec, p_oggpacket );
+         return SendPacket( p_dec, p_oggpacket, p_block );
     }
     else
     {
-        return DecodePacket( p_dec, p_oggpacket );
+        aout_buffer_t *p_aout_buffer;
+
+        if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )
+            p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
+        else
+            p_aout_buffer = NULL; /* Skip headers */
+
+        if( p_block )
+        {
+            block_Release( p_block );
+        }
+        return p_aout_buffer;
     }
 }
 
 /*****************************************************************************
  * DecodePacket: decodes a Speex packet.
  *****************************************************************************/
-static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
+static aout_buffer_t *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 );
+    if( p_oggpacket->bytes )
+    {
+        /* Copy Ogg packet to Speex bitstream */
+        speex_bits_read_from( &p_sys->bits, p_oggpacket->packet,
+                              p_oggpacket->bytes );
+        p_sys->i_frame_in_packet = 0;
+    }
 
-    /* Decode each frame of the packet */
-    for( j = 0; j != p_sys->p_header->frames_per_packet; j++ )
+    /* Decode one frame at a time */
+    if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet )
     {
         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 );
+        p_aout_buffer =
+            p_dec->pf_aout_buffer_new( p_dec, p_sys->p_header->frame_size );
         if( !p_aout_buffer )
         {
-            msg_Err( p_dec, "cannot get aout buffer" );
-            return VLC_SUCCESS;
+            return NULL;
         }
 
         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 == -1 ) return NULL; /* End of stream */
         if( i_ret== -2 )
         {
             msg_Warn( p_dec, "Decoding error: corrupted stream?" );
-            break;
+            return NULL;
         }
 
         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 )
@@ -468,45 +403,36 @@ static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
         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 );
-    }
+        p_sys->i_frame_in_packet++;
 
-    return VLC_SUCCESS;
+        return p_aout_buffer;
+    }
+    else
+    {
+        return NULL;
+    }
 }
 
 /*****************************************************************************
  * SendPacket: send an ogg packet to the stream output.
  *****************************************************************************/
-static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
+static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
+                            block_t *p_block )
 {
     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 );
+    p_block->i_dts = p_block->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 =
+        p_block->i_length =
             aout_DateIncrement( &p_sys->end_date,
                                 p_sys->p_header->frame_size ) -
-            p_sout_buffer->i_pts;
+            p_block->i_pts;
     else
-        p_sout_buffer->i_length = 0;
+        p_block->i_length = 0;
 
-    sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer );
-
-    return VLC_SUCCESS;
+    return p_block;
 }
 
 /*****************************************************************************
@@ -552,22 +478,13 @@ static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket )
 }
 
 /*****************************************************************************
- * EndDecoder: speex decoder destruction
+ * CloseDecoder: speex decoder destruction
  *****************************************************************************/
-static int EndDecoder( decoder_t * p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t * p_dec = (decoder_t *)p_this;
     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 );
@@ -576,6 +493,4 @@ static int EndDecoder( decoder_t * p_dec )
 
     if( p_sys->p_header ) free( p_sys->p_header );
     free( p_sys );
-
-    return VLC_SUCCESS;
 }
index 162c3c8..ee91f93 100644 (file)
@@ -2,7 +2,7 @@
  * spudec.c : SPU decoder thread
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: spudec.c,v 1.26 2003/11/06 16:36:41 nitrox Exp $
+ * $Id: spudec.c,v 1.27 2003/11/16 21:07:31 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -61,8 +61,8 @@ 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','u',' ')
-         && p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','u','b') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','u',' ')
+         && p_dec->fmt_in.i_codec != VLC_FOURCC('s','p','u','b') )
     {
         return VLC_EGENERIC;
     }
index bc56ea2..566a31d 100644 (file)
@@ -2,7 +2,7 @@
  * subsdec.c : text subtitles decoder
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: subsdec.c,v 1.6 2003/11/15 15:40:19 hartman Exp $
+ * $Id: subsdec.c,v 1.7 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *          Samuel Hocevar <sam@zoy.org>
@@ -56,10 +56,9 @@ struct decoder_sys_t
  * Local prototypes
  *****************************************************************************/
 static int  OpenDecoder   ( vlc_object_t * );
+static void CloseDecoder  ( vlc_object_t * );
 
-static int  InitDecoder   ( decoder_t * );
-static int  RunDecoder    ( decoder_t *, block_t * );
-static int  EndDecoder    ( decoder_t * );
+static void DecodeBlock   ( decoder_t *, block_t ** );
 
 static void ParseText     ( decoder_t *, block_t *, vout_thread_t * );
 
@@ -103,7 +102,7 @@ static char *ppsz_justification_text[] = {N_("Center"),N_("Left"),N_("Right")};
 vlc_module_begin();
     set_description( _("text subtitles decoder") );
     set_capability( "decoder", 50 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
 
     add_category_hint( N_("Subtitles"), NULL, VLC_FALSE );
     add_integer( "subsdec-align", 0, NULL, ALIGN_TEXT, ALIGN_LONGTEXT,
@@ -125,37 +124,25 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+    vlc_value_t val;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','u','b','t') && 
-        p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','s','a',' ') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('s','u','b','t') && 
+        p_dec->fmt_in.i_codec != VLC_FOURCC('s','s','a',' ') )
     {
         return VLC_EGENERIC;
     }
 
-    p_dec->pf_init = InitDecoder;
-    p_dec->pf_decode = RunDecoder;
-    p_dec->pf_end = EndDecoder;
+    p_dec->pf_decode_sub = DecodeBlock;
 
     /* Allocate the memory needed to store the decoder's structure */
-    if( ( p_dec->p_sys =
+    if( ( p_dec->p_sys = p_sys =
           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
         msg_Err( p_dec, "out of memory" );
         return VLC_EGENERIC;
     }
 
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    subtitle_data_t *p_demux_data = (subtitle_data_t *)p_dec->p_fifo->p_demux_data;
-    vlc_value_t val;
-
     var_Create( p_dec, "subsdec-align", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
     var_Get( p_dec, "subsdec-align", &val );
     p_sys->i_align = val.i_int;
@@ -183,6 +170,7 @@ static int InitDecoder( decoder_t *p_dec )
 
     if( val.psz_string ) free( val.psz_string );
 #else
+
     msg_Dbg( p_dec, "No iconv support available" );
 #endif
 
@@ -195,11 +183,11 @@ static int InitDecoder( decoder_t *p_dec )
 }
 
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function must be fed with complete subtitles units.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     vout_thread_t *p_vout;
 
@@ -208,20 +196,18 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
     if( !p_vout )
     {
         msg_Warn( p_dec, "couldn't find a video output, trashing subtitle" );
-        return VLC_SUCCESS;
     }
 
-    ParseText( p_dec, p_block, p_vout );
+    ParseText( p_dec, *pp_block, p_vout );
     vlc_object_release( p_vout );
-
-    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
- * EndDecoder: clean up the decoder
+ * CloseDecoder: clean up the decoder
  *****************************************************************************/
-static int EndDecoder( decoder_t *p_dec )
+static void CloseDecoder( vlc_object_t *p_this )
 {
+    decoder_t *p_dec = (decoder_t *)p_this;
     decoder_sys_t *p_sys = p_dec->p_sys;
     vout_thread_t *p_vout;
 
@@ -253,8 +239,6 @@ static int EndDecoder( decoder_t *p_dec )
 #endif
 
     free( p_sys );
-
-    return VLC_SUCCESS;
 }
 
 /*****************************************************************************
index 1c6b82c..9ed2a34 100644 (file)
@@ -2,7 +2,7 @@
  * tarkin.c: tarkin decoder module making use of libtarkin.
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: tarkin.c,v 1.6 2003/10/25 00:49:13 sam Exp $
+ * $Id: tarkin.c,v 1.7 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -105,7 +105,7 @@ 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('t','a','r','k') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','a','r','k') )
     {
         return VLC_EGENERIC;
     }
index 2f81c71..48ffd2c 100644 (file)
@@ -2,7 +2,7 @@
  * theora.c: theora decoder module making use of libtheora.
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: theora.c,v 1.13 2003/10/25 00:49:13 sam Exp $
+ * $Id: theora.c,v 1.14 2003/11/16 21:07:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
 #include <string.h>                                    /* memcpy(), memset() */
 
 #include <vlc/vlc.h>
-#include <vlc/vout.h>
 #include <vlc/decoder.h>
 #include <vlc/input.h>
-#include <vlc/sout.h>
-#include <input_ext-dec.h>
 
 #include <ogg/ogg.h>
 
@@ -59,17 +56,6 @@ struct decoder_sys_t
     theora_state     td;                   /* theora bitstream user comments */
 
     /*
-     * Output properties
-     */
-    vout_thread_t *p_vout;
-
-    /*
-     * Packetizer output properties
-     */
-    sout_packetizer_input_t *p_sout_input;
-    sout_format_t           sout_format;
-
-    /*
      * Common properties
      */
     mtime_t i_pts;
@@ -78,16 +64,14 @@ struct decoder_sys_t
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int OpenDecoder   ( vlc_object_t * );
-static int OpenPacketizer( vlc_object_t * );
+static int  OpenDecoder   ( vlc_object_t * );
+static int  OpenPacketizer( vlc_object_t * );
+static void CloseDecoder  ( vlc_object_t * );
 
-static int InitDecoder   ( decoder_t * );
-static int RunDecoder    ( decoder_t *, block_t * );
-static int EndDecoder    ( decoder_t * );
+static void *DecodeBlock  ( decoder_t *, block_t ** );
+static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
 
-static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t );
-static int DecodePacket  ( decoder_t *, ogg_packet * );
-static int SendPacket    ( decoder_t *, ogg_packet * );
+static picture_t *DecodePacket( decoder_t *, ogg_packet * );
 
 static void ParseTheoraComments( decoder_t * );
 static void theora_CopyPicture( decoder_t *, picture_t *, yuv_buffer * );
@@ -103,18 +87,18 @@ static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
 vlc_module_begin();
     set_description( _("Theora video decoder") );
     set_capability( "decoder", 100 );
-    set_callbacks( OpenDecoder, NULL );
+    set_callbacks( OpenDecoder, CloseDecoder );
     add_shortcut( "theora" );
 
     add_submodule();
     set_description( _("Theora video packetizer") );
     set_capability( "packetizer", 100 );
-    set_callbacks( OpenPacketizer, NULL );
+    set_callbacks( OpenPacketizer, CloseDecoder );
     add_shortcut( "theora" );
 
     add_submodule();
     set_description( _("Theora video encoder") );
-    set_capability( "video encoder", 100 );
+    set_capability( "encoder", 100 );
     set_callbacks( OpenEncoder, CloseEncoder );
     add_shortcut( "theora" );
 vlc_module_end();
@@ -125,18 +109,15 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
 
-    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('t','h','e','o') )
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('t','h','e','o') )
     {
         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 =
+    if( ( p_dec->p_sys = p_sys =
           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
     {
         msg_Err( p_dec, "out of memory" );
@@ -144,6 +125,24 @@ static int OpenDecoder( vlc_object_t *p_this )
     }
     p_dec->p_sys->b_packetizer = VLC_FALSE;
 
+    p_sys->i_pts = 0;
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
+
+    /* Set callbacks */
+    p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
+        DecodeBlock;
+
+    /* Init supporting Theora structures needed in header parsing */
+    theora_comment_init( &p_sys->tc );
+    theora_info_init( &p_sys->ti );
+
+    p_sys->i_headers = 0;
+
     return VLC_SUCCESS;
 }
 
@@ -153,48 +152,29 @@ static int OpenPacketizer( vlc_object_t *p_this )
 
     int i_ret = OpenDecoder( p_this );
 
-    if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
+    if( i_ret == VLC_SUCCESS )
+    {
+        p_dec->p_sys->b_packetizer = VLC_TRUE;
+        p_dec->fmt_out.i_codec = VLC_FOURCC( 't', 'h', 'e', 'o' );
+    }
 
     return i_ret;
 }
 
-/*****************************************************************************
- * InitDecoder: Initalize the decoder
- *****************************************************************************/
-static int InitDecoder( decoder_t *p_dec )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    p_sys->i_pts = 0;
-
-    p_sys->p_sout_input = NULL;
-    p_sys->sout_format.i_cat = VIDEO_ES;
-    p_sys->sout_format.i_fourcc = VLC_FOURCC( 't', 'h', 'e', 'o' );
-    p_sys->sout_format.i_width  = 0;
-    p_sys->sout_format.i_height = 0;
-    p_sys->sout_format.i_bitrate     = 0;
-    p_sys->sout_format.i_extra_data  = 0;
-    p_sys->sout_format.p_extra_data  = NULL;
-
-    /* Init supporting Theora structures needed in header parsing */
-    theora_comment_init( &p_sys->tc );
-    theora_info_init( &p_sys->ti );
-
-    p_sys->i_headers = 0;
-
-    return VLC_SUCCESS;
-}
-
 /****************************************************************************
- * RunDecoder: the whole thing
+ * DecodeBlock: the whole thing
  ****************************************************************************
  * This function must be fed with ogg packets.
  ****************************************************************************/
-static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
     ogg_packet oggpacket;
-    int i_ret;
+
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
 
     /* Block to Ogg packet */
     oggpacket.packet = p_block->p_buffer;
@@ -211,55 +191,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
         if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
         {
-            msg_Err( p_dec->p_fifo, "This bitstream does not contain Theora "
+            msg_Err( p_dec, "This bitstream does not contain Theora "
                      "video data" );
             block_Release( p_block );
-            return VLC_EGENERIC;
+            return NULL;
         }
         p_sys->i_headers++;
 
+        /* Set output properties */
+        p_dec->fmt_out.video.i_width = p_sys->ti.width;
+        p_dec->fmt_out.video.i_height = p_sys->ti.height;
 
-        if( p_sys->b_packetizer )
-        {
-            /* add a input for the stream ouput */
-            p_sys->sout_format.i_width  = p_sys->ti.width;
-            p_sys->sout_format.i_height = p_sys->ti.height;
-
-            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" );
-                block_Release( p_block );
-                return VLC_EGENERIC;
-            }
-        }
+        if( p_sys->ti.aspect_denominator )
+            p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
+                p_sys->ti.aspect_numerator / p_sys->ti.aspect_denominator;
         else
-        {
-            /* Initialize video output */
-            int i_chroma, i_aspect;
-
-            if( p_sys->ti.aspect_denominator )
-                i_aspect = VOUT_ASPECT_FACTOR * p_sys->ti.aspect_numerator /
-                    p_sys->ti.aspect_denominator;
-            else
-                i_aspect = VOUT_ASPECT_FACTOR *
-                    p_sys->ti.frame_width / p_sys->ti.frame_height;
-
-            i_chroma = VLC_FOURCC('Y','V','1','2');
-
-            p_sys->p_vout =
-                vout_Request( p_dec, NULL,
-                              p_sys->ti.frame_width, p_sys->ti.frame_height,
-                              i_chroma, i_aspect );
-            if( p_sys->p_vout == NULL )
-            {
-                msg_Err( p_dec, "failed to create video output" );
-                block_Release( p_block );
-                return VLC_EGENERIC;
-            }
-        }
+            p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
+                p_sys->ti.frame_width / p_sys->ti.frame_height;
 
         msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content "
                  "is %dx%d with offset (%d,%d)",
@@ -268,17 +216,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
                  p_sys->ti.frame_width, p_sys->ti.frame_height,
                  p_sys->ti.offset_x, p_sys->ti.offset_y );
 
-        if( p_sys->b_packetizer )
-        {
-            i_ret = SendPacket( p_dec, &oggpacket );
-            block_Release( p_block );
-            return i_ret;
-        }
-        else
-        {
-            block_Release( p_block );
-            return VLC_SUCCESS;
-        }
+        return ProcessPacket( p_dec, &oggpacket, pp_block );
     }
 
     if( p_sys->i_headers == 1 )
@@ -287,23 +225,13 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
         {
             msg_Err( p_dec, "2nd Theora header is corrupted" );
-            return VLC_EGENERIC;
+            return NULL;
         }
         p_sys->i_headers++;
 
         ParseTheoraComments( p_dec );
 
-        if( p_sys->b_packetizer )
-        {
-            i_ret = SendPacket( p_dec, &oggpacket );
-            block_Release( p_block );
-            return i_ret;
-        }
-        else
-        {
-            block_Release( p_block );
-            return VLC_SUCCESS;
-        }
+        return ProcessPacket( p_dec, &oggpacket, pp_block );
     }
 
     if( p_sys->i_headers == 2 )
@@ -314,7 +242,7 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
         if( theora_decode_header( &p_sys->ti, &p_sys->tc, &oggpacket ) < 0 )
         {
             msg_Err( p_dec, "3rd Theora header is corrupted" );
-            return VLC_EGENERIC;
+            return NULL;
         }
         p_sys->i_headers++;
 
@@ -324,115 +252,84 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block )
             theora_decode_init( &p_sys->td, &p_sys->ti );
         }
 
-        if( p_sys->b_packetizer )
-        {
-            i_ret = SendPacket( p_dec, &oggpacket );
-            block_Release( p_block );
-            return i_ret;
-        }
-        else
-        {
-            block_Release( p_block );
-            return VLC_SUCCESS;
-        }
+        return ProcessPacket( p_dec, &oggpacket, pp_block );
     }
 
-    i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
-    block_Release( p_block );
-    return i_ret;
+    return ProcessPacket( p_dec, &oggpacket, pp_block );
 }
 
 /*****************************************************************************
- * ProcessPacket: processes a Vorbis packet.
+ * ProcessPacket: processes a theora packet.
  *****************************************************************************/
-static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
-                          mtime_t i_pts )
+static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
+                            block_t **pp_block )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block = *pp_block;
+    void *p_buf;
 
     /* Date management */
-    if( i_pts > 0 && i_pts != p_sys->i_pts )
+    if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
     {
-        p_sys->i_pts = i_pts;
+        p_sys->i_pts = p_block->i_pts;
     }
 
     if( p_sys->b_packetizer )
     {
-        return SendPacket( p_dec, p_oggpacket );
+        /* Date management */
+        p_block->i_dts = p_block->i_pts = p_sys->i_pts;
+
+        if( p_sys->i_headers >= 3 )
+            p_block->i_length = p_sys->i_pts - p_block->i_pts;
+        else
+            p_block->i_length = 0;
+
+        p_buf = p_block;
     }
     else
     {
-        return DecodePacket( p_dec, p_oggpacket );
-    }
-}
-
-/*****************************************************************************
- * DecodePacket: decodes a Theora packet.
- *****************************************************************************/
-static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
-{
-    picture_t *p_pic;
-    yuv_buffer yuv;
-
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    theora_decode_packetin( &p_sys->td, p_oggpacket );
-
-    /* Decode */
-    theora_decode_YUVout( &p_sys->td, &yuv );
+        if( p_sys->i_headers >= 3 )
+            p_buf = DecodePacket( p_dec, p_oggpacket );
+        else
+            p_buf = NULL;
 
-    /* Get a new picture */
-    while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
-    {
-        if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
+        if( p_block )
         {
-            return VLC_EGENERIC;
+            block_Release( p_block );
+            *pp_block = NULL;
         }
-        msleep( VOUT_OUTMEM_SLEEP );
     }
-    if( !p_pic ) return VLC_EGENERIC;
-
-    theora_CopyPicture( p_dec, p_pic, &yuv );
-
-    vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts );
-    vout_DisplayPicture( p_sys->p_vout, p_pic );
 
     /* Date management */
     p_sys->i_pts += ( I64C(1000000) * p_sys->ti.fps_denominator /
                       p_sys->ti.fps_numerator ); /* 1 frame per packet */
 
-    return VLC_SUCCESS;
+    return p_buf;
 }
 
 /*****************************************************************************
- * SendPacket: send an ogg packet to the stream output.
+ * DecodePacket: decodes a Theora packet.
  *****************************************************************************/
-static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
+static picture_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
+    picture_t *p_pic;
+    yuv_buffer yuv;
 
-    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;
+    theora_decode_packetin( &p_sys->td, p_oggpacket );
 
-    p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
-                             p_oggpacket->packet,
-                             p_oggpacket->bytes );
+    /* Decode */
+    theora_decode_YUVout( &p_sys->td, &yuv );
 
-    /* Date management */
-    p_sout_buffer->i_dts = p_sout_buffer->i_pts = p_sys->i_pts;
-    p_sys->i_pts += ( I64C(1000000) * p_sys->ti.fps_denominator /
-                      p_sys->ti.fps_numerator ); /* 1 frame per packet */
+    /* Get a new picture */