]> git.sesse.net Git - vlc/commitdiff
* modules/codec/vorbis.c: fixed vorbis encoding.
authorGildas Bazin <gbazin@videolan.org>
Mon, 27 Oct 2003 17:50:54 +0000 (17:50 +0000)
committerGildas Bazin <gbazin@videolan.org>
Mon, 27 Oct 2003 17:50:54 +0000 (17:50 +0000)
* modules/codec/ffmpeg/*: fixed ffmpeg encoding.
* modules/stream_out/transcode.c: transcoding is working again.

modules/codec/ffmpeg/encoder.c
modules/codec/ffmpeg/ffmpeg.c
modules/codec/vorbis.c
modules/stream_out/transcode.c

index 199cd042256b2564da66a426283b366d797f1499..9cae62ff6fa79be1ea72ff6c716b9fb96337562e 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.1 2003/10/27 01:04:38 gbazin Exp $
+ * $Id: encoder.c,v 1.2 2003/10/27 17:50:54 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
@@ -80,17 +80,21 @@ struct encoder_sys_t
     /*
      * Common properties
      */
-    int i_last_block_size;
-    int i_samples_delay;
-    mtime_t i_pts;
+    char *p_buffer;
+    char *p_buffer_out;
 
+    /*
+     * Videoo properties
+     */
     mtime_t i_last_ref_pts;
     mtime_t i_buggy_pts_detect;
 
+    /*
+     * Audio properties
+     */
     int i_frame_size;
-
-    char *p_buffer;
-    char *p_buffer_out;
+    int i_samples_delay;
+    mtime_t i_pts;
 };
 
 /*****************************************************************************
@@ -102,24 +106,31 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this )
     encoder_sys_t *p_sys = p_enc->p_sys;
     AVCodecContext  *p_context;
     AVCodec *p_codec;
-    int i_ff_codec;
+    int i_codec_id, i_cat;
+    char *psz_namecodec;
 
-    /* find encoder */
-    i_ff_codec = E_(GetFfmpegCodec)( p_enc->i_fourcc, 0, 0, 0 );
-    if( !i_ff_codec )
+    if( !E_(GetFfmpegCodec)( p_enc->i_fourcc, &i_cat, &i_codec_id,
+                             &psz_namecodec ) )
     {
         return VLC_EGENERIC;
     }
 
-    p_codec = avcodec_find_encoder( i_ff_codec );
-    if( !p_codec )
+    if( i_cat != VIDEO_ES )
     {
+        msg_Err( p_enc, "\"%s\" is not a video encoder", psz_namecodec );
         return VLC_EGENERIC;
     }
 
-    /* libavcodec needs to be initialized */
+    /* 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 )
     {
@@ -169,7 +180,7 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this )
     }
 #endif
 
-    if( i_ff_codec == CODEC_ID_RAWVIDEO )
+    if( i_codec_id == CODEC_ID_RAWVIDEO )
     {
         p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->i_fourcc );
     }
@@ -193,6 +204,8 @@ int E_(OpenVideoEncoder)( vlc_object_t *p_this )
     p_sys->i_last_ref_pts = 0;
     p_sys->i_buggy_pts_detect = 0;
 
+    msg_Dbg( p_enc, "found encoder %s", psz_namecodec );
+
     return VLC_SUCCESS;
 }
 
@@ -229,7 +242,8 @@ 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 = 0;//in->i_length;
+            p_block->i_length = I64C(1000000) * p_enc->i_frame_rate_base /
+                                  p_enc->i_frame_rate;
             p_block->i_pts    = p_sys->p_context->coded_frame->pts;
 
             if( !p_sys->p_context->delay ||
@@ -257,7 +271,8 @@ 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 = 0;//in->i_length;
+            p_block->i_length = I64C(1000000) * p_enc->i_frame_rate_base /
+                                  p_enc->i_frame_rate;
             p_block->i_dts = p_block->i_pts = p_pict->date;
         }
 
@@ -287,28 +302,34 @@ void E_(CloseVideoEncoder)( vlc_object_t *p_this )
 int E_(OpenAudioEncoder)( 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;
+    encoder_sys_t *p_sys;
+    AVCodecContext *p_context;
     AVCodec *p_codec;
-    int i_ff_codec;
+    int i_codec_id, i_cat;
+    char *psz_namecodec;
 
-    i_ff_codec = E_(GetFfmpegCodec)( p_enc->i_fourcc, 0, 0, 0 );
-    if( i_ff_codec == 0 )
+    if( !E_(GetFfmpegCodec)( p_enc->i_fourcc, &i_cat, &i_codec_id,
+                             &psz_namecodec ) )
     {
-        msg_Err( p_enc, "cannot find encoder id" );
         return VLC_EGENERIC;
     }
 
-    p_codec = avcodec_find_encoder( i_ff_codec );
-    if( !p_codec )
+    if( i_cat != AUDIO_ES )
     {
-        msg_Err( p_enc, "cannot find encoder (avcodec)" );
+        msg_Err( p_enc, "\"%s\" is not an audio encoder", psz_namecodec );
         return VLC_EGENERIC;
     }
 
-    /* libavcodec needs to be initialized */
+    /* 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 )
     {
@@ -333,18 +354,13 @@ int E_(OpenAudioEncoder)( vlc_object_t *p_this )
     p_context->extradata = NULL;
     p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
 
-    p_sys->i_samples_delay = 0;
-    p_sys->i_last_block_size = 0;
-    p_sys->i_pts = 0;
-
-    if( avcodec_open( p_context, p_sys->p_codec ) )
+    if( avcodec_open( p_context, p_codec ) < 0 )
     {
-#if 0
         if( p_context->channels > 2 )
         {
             p_context->channels = 2;
-            id->f_dst.i_channels   = 2;
-            if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
+            //id->f_dst.i_channels   = 2;
+            if( avcodec_open( p_context, p_codec ) < 0 )
             {
                 msg_Err( p_enc, "cannot open encoder" );
                 return VLC_EGENERIC;
@@ -356,26 +372,24 @@ int E_(OpenAudioEncoder)( vlc_object_t *p_this )
             msg_Err( p_enc, "cannot open encoder" );
             return VLC_EGENERIC;
         }
-#endif
     }
 
     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->p_buffer = malloc( p_context->frame_size * 2 *
-                              p_context->channels * 2 );
-
+    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 );
 
-    p_sys->i_frame_size = p_sys->p_context->frame_size * 2 *
-                            p_context->channels;
+    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 );
 
-    /* Hack for mp3 transcoding support */
-    if( p_enc->i_fourcc == VLC_FOURCC( 'm','p','3',' ' ) )
-    {
-        p_enc->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
-    }
+    p_sys->i_samples_delay = 0;
+    p_sys->i_pts = 0;
+
+    msg_Dbg( p_enc, "found encoder %s", psz_namecodec );
 
     return VLC_SUCCESS;
 }
@@ -387,6 +401,7 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
 {
     encoder_sys_t *p_sys = p_enc->p_sys;
     block_t *p_block, *p_chain = NULL;
+
     char *p_buffer = p_aout_buf->p_buffer;
     int i_samples = p_aout_buf->i_nb_samples;
     int i_samples_delay = p_sys->i_samples_delay;
@@ -412,7 +427,7 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
             p_samples = (int16_t *)p_sys->p_buffer;
             memcpy( p_sys->p_buffer + i_delay_size, p_buffer, i_size );
             p_buffer -= i_delay_size;
-           i_samples += i_samples_delay;
+            i_samples += i_samples_delay;
             i_samples_delay = 0;
         }
         else
@@ -423,14 +438,17 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
         i_out = avcodec_encode_audio( p_sys->p_context, p_sys->p_buffer_out,
                                       2 * AVCODEC_MAX_AUDIO_FRAME_SIZE,
                                       p_samples );
-        if( i_out <= 0 )
-        {
-            break;
-        }
+
+#if 0
+        msg_Warn( p_enc, "avcodec_encode_audio: %d", i_out );
+#endif
+        if( i_out < 0 ) break;
 
         p_buffer += p_sys->i_frame_size;
         p_sys->i_samples_delay -= p_sys->p_context->frame_size;
-       i_samples = p_sys->p_context->frame_size;
+        i_samples -= p_sys->p_context->frame_size;
+
+        if( i_out == 0 ) continue;
 
         p_block = block_New( p_enc, i_out );
         memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
@@ -447,7 +465,7 @@ static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
     }
 
     /* Backup the remaining raw samples */
-    if( p_sys->i_samples_delay > 0 )
+    if( i_samples )
     {
         memcpy( p_sys->p_buffer, p_buffer + i_samples_delay,
                 i_samples * 2 * p_sys->p_context->channels );
index 19a7a0ab56b88d086cea14f0399d066929ab8ce3..81199574dbf501ec937a63a854e64ebe05cd90f1 100644 (file)
@@ -2,7 +2,7 @@
  * ffmpeg.c: video decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ffmpeg.c,v 1.55 2003/10/27 01:04:38 gbazin Exp $
+ * $Id: ffmpeg.c,v 1.56 2003/10/27 17:50:54 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
@@ -136,10 +136,21 @@ vlc_module_end();
 static int OpenDecoder( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*) p_this;
-    int i_cat;
+    int i_cat, i_codec_id;
+    char *psz_namecodec;
+
+    if( !E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc, &i_cat, &i_codec_id,
+                             &psz_namecodec ) )
+    {
+        return VLC_EGENERIC;
+    }
 
-    if( !E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc, &i_cat, NULL, NULL ) )
+    /* Initialization must be done before avcodec_find_decoder() */
+    E_(InitLibavcodec)(p_this);
+
+    if( !avcodec_find_decoder( i_codec_id ) )
     {
+        msg_Err( p_dec, "codec not found (%s)", psz_namecodec );
         return VLC_EGENERIC;
     }
 
@@ -160,8 +171,6 @@ static int InitDecoder( decoder_t *p_dec )
     AVCodecContext *p_context;
     AVCodec        *p_codec;
 
-    E_(InitLibavcodec)( VLC_OBJECT(p_dec->p_fifo) );
-
     /* *** determine codec type *** */
     E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc,
                         &i_cat, &i_codec_id, &psz_namecodec );
@@ -620,6 +629,13 @@ int E_(GetFfmpegCodec)( vlc_fourcc_t i_fourcc, int *pi_cat,
         psz_name = "A52 Audio (aka AC3)";
         break;
 
+    /* AAC audio */
+    case VLC_FOURCC('m','p','4','a'):
+        i_cat    = AUDIO_ES;
+        i_codec  = CODEC_ID_AAC;
+        psz_name = "MPEG AAC Audio";
+        break;
+
     default:
         i_cat = UNKNOWN_ES;
         i_codec = CODEC_ID_NONE;
@@ -632,10 +648,10 @@ int E_(GetFfmpegCodec)( vlc_fourcc_t i_fourcc, int *pi_cat,
         if( pi_cat ) *pi_cat = i_cat;
         if( pi_ffmpeg_codec ) *pi_ffmpeg_codec = i_codec;
         if( ppsz_name ) *ppsz_name = psz_name;
-        return( VLC_TRUE );
+        return VLC_TRUE;
     }
 
-    return( VLC_FALSE );
+    return VLC_FALSE;
 }
 
 int E_(GetFfmpegChroma)( vlc_fourcc_t i_chroma )
index 34da93bf1fdb06bfa05434dfe9142918333fc187..417694817bda6074fdd668af02f2c84acfe3f16a 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * vorbis.c: vorbis decoder module making use of libvorbis.
+ * vorbis.c: vorbis decoder/encoder/packetizer module making use of libvorbis.
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: vorbis.c,v 1.20 2003/10/27 01:04:38 gbazin Exp $
+ * $Id: vorbis.c,v 1.21 2003/10/27 17:50:54 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -630,6 +630,7 @@ struct encoder_sys_t
 
     int i_last_block_size;
     int i_samples_delay;
+    int i_channels;
 
     /*
      * Packetizer output properties
@@ -649,7 +650,7 @@ struct encoder_sys_t
 static int OpenEncoder( vlc_object_t *p_this )
 {
     encoder_t *p_enc = (encoder_t *)p_this;
-    encoder_sys_t *p_sys = p_enc->p_sys;
+    encoder_sys_t *p_sys;
 
     if( p_enc->i_fourcc != VLC_FOURCC('v','o','r','b') )
     {
@@ -685,6 +686,7 @@ static int OpenEncoder( vlc_object_t *p_this )
     vorbis_analysis_init( &p_sys->vd, &p_sys->vi );
     vorbis_block_init( &p_sys->vd, &p_sys->vb );
 
+    p_sys->i_channels = aout_FormatNbChannels( &p_enc->format.audio );
     p_sys->i_last_block_size = 0;
     p_sys->i_samples_delay = 0;
     p_sys->i_headers = 0;
@@ -701,7 +703,7 @@ static int OpenEncoder( vlc_object_t *p_this )
 static block_t *Headers( encoder_t *p_enc )
 {
     encoder_sys_t *p_sys = p_enc->p_sys;
-    block_t *p_block, **pp_block = NULL;
+    block_t *p_block, *p_chain = NULL;
 
     /* Create theora headers */
     if( !p_sys->i_headers )
@@ -718,14 +720,12 @@ static block_t *Headers( encoder_t *p_enc )
 
             p_block->i_dts = p_block->i_pts = p_block->i_length = 0;
 
-            block_ChainAppend( pp_block, p_block );
+            block_ChainAppend( &p_chain, p_block );
         }
         p_sys->i_headers = 3;
-
-        return *pp_block;
     }
 
-    return NULL;
+    return p_chain;
 }
 
 /****************************************************************************
@@ -739,16 +739,15 @@ static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
     ogg_packet oggpacket;
     block_t *p_block, *p_chain = NULL;
     float **buffer;
-    int i_samples;
+    int i, j;
 
     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;
 
-    i_samples = p_aout_buf->i_nb_samples;
-    p_sys->i_samples_delay += i_samples;
+    p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
 
-    buffer = vorbis_analysis_buffer( &p_sys->vd, i_samples );
+    buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );
 
 #if 0
     if( id->ff_dec_c->channels != id->ff_enc_c->channels )
@@ -765,22 +764,24 @@ static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
             }
         }
     }
+#endif
 
     /* convert samples to float and uninterleave */
-    for( i = 0; i < id->f_dst.i_channels; i++ )
+    for( i = 0; i < p_sys->i_channels; i++ )
     {
-        for( j = 0 ; j < i_samples ; j++ )
+        for( j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
         {
-            buffer[i][j]= ((float)( ((int16_t *)id->p_buffer)
-                                    [j*id->f_src.i_channels + i ] ))/ 32768.f;
+            buffer[i][j]= ((float)( ((int16_t *)p_aout_buf->p_buffer )
+                                    [j * p_sys->i_channels + i ] )) / 32768.f;
         }
     }
-#endif
 
-    vorbis_analysis_wrote( &p_sys->vd, i_samples );
+    vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );
 
     while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
     {
+        int i_samples;
+
         vorbis_analysis( &p_sys->vb, NULL );
         vorbis_bitrate_addblock( &p_sys->vb );
 
index 9b24835a5bd5f62e6293ce4b2a06ebb04f4fe335..3a868af1fac6baa6301ce91d5fdb1aba4d70d138 100644 (file)
@@ -2,7 +2,7 @@
  * transcode.c
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: transcode.c,v 1.44 2003/10/27 01:04:38 gbazin Exp $
+ * $Id: transcode.c,v 1.45 2003/10/27 17:50:54 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
@@ -334,10 +334,6 @@ struct sout_stream_id_t
     mtime_t         i_dts;
     mtime_t         i_length;
 
-    int             i_buffer_in;
-    int             i_buffer_in_pos;
-    uint8_t         *p_buffer_in;
-
     int             i_buffer;
     int             i_buffer_pos;
     uint8_t         *p_buffer;
@@ -652,10 +648,6 @@ static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream,
         }
     }
 
-    id->i_buffer_in      = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
-    id->i_buffer_in_pos = 0;
-    id->p_buffer_in      = malloc( id->i_buffer_in );
-
     id->i_buffer     = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
     id->i_buffer_pos = 0;
     id->p_buffer     = malloc( id->i_buffer );
@@ -680,7 +672,7 @@ static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream,
     if( !id->p_encoder->p_module )
     {
         vlc_object_destroy( id->p_encoder );
-       id->p_encoder = NULL;
+        id->p_encoder = NULL;
     }
 
     id->b_enc_inited = VLC_FALSE;
@@ -688,6 +680,12 @@ static int transcode_audio_ffmpeg_new( sout_stream_t *p_stream,
     id->f_dst.i_extra_data = id->p_encoder->i_extra_data;
     id->f_dst.p_extra_data = id->p_encoder->p_extra_data;
 
+    /* Hack for mp3 transcoding support */
+    if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','3',' ' ) )
+    {
+        id->f_dst.i_fourcc = VLC_FOURCC( 'm','p','g','a' );
+    }
+
     return VLC_SUCCESS;
 }
 
@@ -703,7 +701,6 @@ static void transcode_audio_ffmpeg_close( sout_stream_t *p_stream,
     module_Unneed( id->p_encoder, id->p_encoder->p_module );
     vlc_object_destroy( id->p_encoder );
 
-    free( id->p_buffer_in );
     free( id->p_buffer );
 }
 
@@ -712,205 +709,159 @@ static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream,
                                            sout_buffer_t *in,
                                            sout_buffer_t **out )
 {
-    vlc_bool_t b_again = VLC_FALSE;
     aout_buffer_t aout_buf;
     block_t *p_block;
+    int i_buffer = in->i_size;
+    char *p_buffer = in->p_buffer;
+    id->i_dts = in->i_dts;
     *out = NULL;
 
-    /* gather data into p_buffer_in */
-    id->i_dts = in->i_dts -
-                (mtime_t)1000000 *
-                (mtime_t)(id->i_buffer_pos / 2 / id->ff_dec_c->channels )/
-                (mtime_t)id->ff_dec_c->sample_rate;
-
-    if( id->i_buffer_in_pos + (int)in->i_size > id->i_buffer_in )
+    while( i_buffer )
     {
-        /* extend buffer_in */
-        id->i_buffer_in = id->i_buffer_in_pos + in->i_size + 1024;
-        id->p_buffer_in = realloc( id->p_buffer_in, id->i_buffer_in );
-    }
-    memcpy( &id->p_buffer_in[id->i_buffer_in_pos],
-            in->p_buffer, in->i_size );
-    id->i_buffer_in_pos += in->i_size;
+        id->i_buffer_pos = 0;
 
-    do
-    {
         /* decode as much data as possible */
         if( id->ff_dec )
         {
-            for( ;; )
-            {
-                int i_buffer_size;
-                int i_used;
+            int i_used;
 
-                i_used = avcodec_decode_audio( id->ff_dec_c,
-                         (int16_t*)&id->p_buffer,
-                         &i_buffer_size, id->p_buffer_in,
-                         id->i_buffer_in_pos );
+            i_used = avcodec_decode_audio( id->ff_dec_c,
+                         (int16_t*)id->p_buffer, &id->i_buffer_pos,
+                         p_buffer, i_buffer );
 
-#if 0
-                msg_Warn( p_stream, "avcodec_decode_audio: %d used on %d",
-                          i_used, id->i_buffer_in_pos );
+#if 1
+            msg_Warn( p_stream, "avcodec_decode_audio: %d used on %d",
+                      i_used, i_buffer );
 #endif
-
-                id->i_buffer_pos += i_buffer_size;
-
-                if( i_used < 0 )
-                {
-                    msg_Warn( p_stream, "error audio decoding");
-                    id->i_buffer_in_pos = 0;
-                    break;
-                }
-                else if( i_used < id->i_buffer_in_pos )
-                {
-                    memmove( id->p_buffer_in,
-                             &id->p_buffer_in[i_used],
-                             id->i_buffer_in - i_used );
-                    id->i_buffer_in_pos -= i_used;
-                }
-                else
-                {
-                    id->i_buffer_in_pos = 0;
-                    break;
-                }
-
-                if( id->i_buffer_pos >= AVCODEC_MAX_AUDIO_FRAME_SIZE )
-                {
-                    /* buffer full */
-                    b_again = VLC_TRUE;
-                    break;
-                }
+            if( i_used < 0 )
+            {
+                msg_Warn( p_stream, "error audio decoding");
+                break;
             }
+
+            i_buffer -= i_used;
+            p_buffer += i_used;
         }
         else
         {
-            int16_t *sout  = (int16_t*)&id->p_buffer[id->i_buffer_pos];
-            int     i_used = 0;
+            int16_t *sout = (int16_t*)id->p_buffer;
 
-            if( id->f_src.i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) )
-            {
-                int8_t *sin = (int8_t*)id->p_buffer_in;
-                int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
-                                           / 2, id->i_buffer_in_pos );
-                i_used = i_samples;
-                while( i_samples > 0 )
-                {
-                    *sout++ = ( *sin++ ) << 8;
-                    i_samples--;
-                }
-            }
-            else if( id->f_src.i_fourcc == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
+            if( id->f_src.i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) ||
+                id->f_src.i_fourcc == VLC_FOURCC( 'u', '8', ' ', ' ' ) )
             {
-                int8_t *sin = (int8_t*)id->p_buffer_in;
-                int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
-                                           / 2, id->i_buffer_in_pos );
-                i_used = i_samples;
-                while( i_samples > 0 )
-                {
-                    *sout++ = ( *sin++ - 128 ) << 8;
-                    i_samples--;
-                }
+                int8_t *sin = (int8_t*)p_buffer;
+                int i_used = __MIN( id->i_buffer/2, i_buffer );
+                int i_samples = i_used;
+
+                if( id->f_src.i_fourcc == VLC_FOURCC( 's', '8', ' ', ' ' ) )
+                    while( i_samples > 0 )
+                    {
+                        *sout++ = ( *sin++ ) << 8;
+                        i_samples--;
+                    }
+                else
+                    while( i_samples > 0 )
+                    {
+                        *sout++ = ( *sin++ - 128 ) << 8;
+                        i_samples--;
+                    }
+
+                i_buffer -= i_used;
+                p_buffer += i_used;
+                id->i_buffer_pos = i_used * 2;
             }
-            else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'l' ) )
+            else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'l' ) ||
+                     id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'b' ) )
             {
-                int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
-                                           / 2, id->i_buffer_in_pos / 2);
-#ifdef WORDS_BIGENDIAN
-                uint8_t *sin = (uint8_t*)id->p_buffer_in;
-                i_used = i_samples * 2;
-                while( i_samples > 0 )
-                {
-                    uint8_t tmp[2];
-
-                    tmp[1] = *sin++;
-                    tmp[0] = *sin++;
-                    *sout++ = *(int16_t*)tmp;
-                    i_samples--;
-                }
+                int16_t *sin = (int16_t*)p_buffer;
+                int i_used = __MIN( id->i_buffer, i_buffer );
+                int i_samples = i_used / 2;
+                int b_invert_indianness;
 
+                if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'l' ) )
+#ifdef WORDS_BIGENDIAN
+                    b_invert_indianness = 1;
 #else
-                memcpy( sout, id->p_buffer_in, i_samples * 2 );
-                sout += i_samples;
-                i_used = i_samples * 2;
+                    b_invert_indianness = 0;
 #endif
-            }
-            else if( id->f_src.i_fourcc == VLC_FOURCC( 's', '1', '6', 'b' ) )
-            {
-                int     i_samples = __MIN( ( id->i_buffer - id->i_buffer_pos )
-                                           / 2, id->i_buffer_in_pos / 2);
+                else
 #ifdef WORDS_BIGENDIAN
-                memcpy( sout, id->p_buffer_in, i_samples * 2 );
-                sout += i_samples;
-                i_used = i_samples * 2;
+                    b_invert_indianness = 0;
 #else
-                uint8_t *sin = (uint8_t*)id->p_buffer_in;
-                i_used = i_samples * 2;
-                while( i_samples > 0 )
-                {
-                    uint8_t tmp[2];
+                    b_invert_indianness = 1;
+#endif
 
-                    tmp[1] = *sin++;
-                    tmp[0] = *sin++;
-                    *sout++ = *(int16_t*)tmp;
-                    i_samples--;
+                if( b_invert_indianness )
+                {
+                    while( i_samples > 0 )
+                    {
+                        uint8_t tmp[2];
+
+                        tmp[1] = *sin++;
+                        tmp[0] = *sin++;
+                        *sout++ = *(int16_t*)tmp;
+                        i_samples--;
+                    }
+                }
+                else
+                {
+                    memcpy( sout, sin, i_used );
+                    sout += i_samples;
                 }
-#endif
-            }
 
-            id->i_buffer_pos = (uint8_t*)sout - id->p_buffer;
-            if( i_used < id->i_buffer_in_pos )
-            {
-                memmove( id->p_buffer_in,
-                         &id->p_buffer_in[i_used],
-                         id->i_buffer_in - i_used );
+                i_buffer -= i_used;
+                p_buffer += i_used;
+                id->i_buffer_pos = i_used;
             }
-            id->i_buffer_in_pos -= i_used;
         }
 
         if( id->i_buffer_pos == 0 ) continue;
 
         /* Encode as much data as possible */
-       if( id->b_enc_inited )
-       {
-            while( id->p_encoder->pf_header &&
-                  (p_block = id->p_encoder->pf_header( id->p_encoder )) )
-            {
-                sout_buffer_t *p_out;
-                p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
-                memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
-                p_out->i_dts = in->i_dts;
-                p_out->i_pts = in->i_dts;
-                sout_BufferChain( out, p_out );
-            }
+        if( !id->b_enc_inited && id->p_encoder->pf_header )
+        {
+           p_block = id->p_encoder->pf_header( id->p_encoder );
+           while( p_block )
+           {
+               sout_buffer_t *p_out;
+               block_t *p_prev_block = p_block;
+
+               p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
+               memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
+               p_out->i_dts = p_out->i_pts = in->i_dts;
+               p_out->i_length = 0;
+               sout_BufferChain( out, p_out );
+
+               p_block = p_block->p_next;
+               block_Release( p_prev_block );
+           }
 
             id->b_enc_inited = VLC_TRUE;
-       }
+        }
 
         aout_buf.p_buffer = id->p_buffer;
         aout_buf.i_nb_bytes = id->i_buffer_pos;
-        aout_buf.i_nb_samples = id->i_buffer_pos / 2 / id->ff_dec_c->channels;
+        aout_buf.i_nb_samples = id->i_buffer_pos / 2 / id->f_src.i_channels;
         aout_buf.start_date = id->i_dts;
         aout_buf.end_date = id->i_dts;
 
-       p_block = id->p_encoder->pf_encode_audio( id->p_encoder, &aout_buf );
-       while( p_block )
-       {
-           sout_buffer_t *p_out;
-           block_t *p_prev_block = p_block;
-
-           p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
-           memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
-           p_out->i_dts = p_block->i_dts;
-           p_out->i_pts = p_block->i_pts;
-           p_out->i_length = p_block->i_length;
-           sout_BufferChain( out, p_out );
-
-           p_block = p_block->p_next;
-           block_Release( p_prev_block );
-       }
-       id->i_buffer_pos = 0;
-
-    } while( b_again );
+        p_block = id->p_encoder->pf_encode_audio( id->p_encoder, &aout_buf );
+        while( p_block )
+        {
+            sout_buffer_t *p_out;
+            block_t *p_prev_block = p_block;
+
+            p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
+            memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
+            p_out->i_dts = p_block->i_dts;
+            p_out->i_pts = p_block->i_pts;
+            p_out->i_length = p_block->i_length;
+            sout_BufferChain( out, p_out );
+
+            p_block = p_block->p_next;
+            block_Release( p_prev_block );
+        }
+    }
 
     return VLC_SUCCESS;
 }
@@ -1013,12 +964,12 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream,
     if( id->p_encoder->format.video.i_width <= 0 )
     {
         id->p_encoder->format.video.i_width = id->f_dst.i_width =
-           id->ff_dec_c->width - p_sys->i_crop_left - p_sys->i_crop_right;
+            id->ff_dec_c->width - p_sys->i_crop_left - p_sys->i_crop_right;
     }
     if( id->p_encoder->format.video.i_height <= 0 )
     {
         id->p_encoder->format.video.i_height = id->f_dst.i_height =
-           id->ff_dec_c->height - p_sys->i_crop_top - p_sys->i_crop_bottom;
+            id->ff_dec_c->height - p_sys->i_crop_top - p_sys->i_crop_bottom;
     }
 
     id->p_ff_pic         = avcodec_alloc_frame();
@@ -1064,7 +1015,7 @@ static int transcode_video_ffmpeg_new( sout_stream_t *p_stream,
 }
 
 static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream,
-                                          sout_stream_id_t *id )
+                                           sout_stream_id_t *id )
 {
     /* Close decoder */
     if( id->ff_dec )
@@ -1189,21 +1140,28 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
             id->p_encoder->i_extra_data = 0;
             id->p_encoder->p_extra_data = NULL;
 
-           id->p_encoder->p_module =
-               module_Need( id->p_encoder, "video encoder", NULL );
-           if( !id->p_encoder->p_module )
-           {
-               vlc_object_destroy( id->p_encoder );
-               msg_Err( p_stream, "cannot find encoder" );
-               return VLC_EGENERIC;
-           }
+            id->p_encoder->p_module =
+                module_Need( id->p_encoder, "video encoder", NULL );
+            if( !id->p_encoder->p_module )
+            {
+                vlc_object_destroy( id->p_encoder );
+                msg_Err( p_stream, "cannot find encoder" );
+                return VLC_EGENERIC;
+            }
 
             id->f_dst.i_extra_data = id->p_encoder->i_extra_data;
             id->f_dst.p_extra_data = id->p_encoder->p_extra_data;
 
+            /* Hack for mp2v/mp1v transcoding support */
+            if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','1','v' ) ||
+                id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','2','v' ) )
+            {
+                id->f_dst.i_fourcc = VLC_FOURCC( 'm','p','g','v' );
+            }
+
             if( !( id->id =
                      p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
-                                                    &id->f_dst ) ) )
+                                                     &id->f_dst ) ) )
             {
                 msg_Err( p_stream, "cannot add this stream" );
                 transcode_video_ffmpeg_close( p_stream, id );
@@ -1212,7 +1170,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
             }
 
             while( id->p_encoder->pf_header &&
-                  (p_block = id->p_encoder->pf_header( id->p_encoder )) )
+                   (p_block = id->p_encoder->pf_header( id->p_encoder )) )
             {
                 sout_buffer_t *p_out;
                 p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
@@ -1331,41 +1289,41 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
               id->ff_dec_c->frame_rate_base / (2 * id->ff_dec_c->frame_rate);
         }
 
-       /* Encoding */
-       block_t *p_block;
-       picture_t pic;
-       int i_plane;
-
-       vout_InitPicture( VLC_OBJECT(p_stream), &pic,
-                         id->p_encoder->format.video.i_chroma,
-                         id->f_dst.i_width, id->f_dst.i_height,
-                         id->f_dst.i_width * VOUT_ASPECT_FACTOR /
-                         id->f_dst.i_height );
-
-       for( i_plane = 0; i_plane < pic.i_planes; i_plane++ )
-       {
-           pic.p[i_plane].p_pixels = frame->data[i_plane];
-           pic.p[i_plane].i_pitch = frame->linesize[i_plane];
-       }
-
-       pic.date = frame->pts;
-
-       p_block = id->p_encoder->pf_encode_video( id->p_encoder, &pic );
-       while( p_block )
-       {
-           sout_buffer_t *p_out;
-           block_t *p_prev_block = p_block;
-
-           p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
-           memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
-           p_out->i_dts = p_block->i_dts;
-           p_out->i_pts = p_block->i_pts;
-           p_out->i_length = p_block->i_length;
-           sout_BufferChain( out, p_out );
-
-           p_block = p_block->p_next;
-           block_Release( p_prev_block );
-       }
+        /* Encoding */
+        block_t *p_block;
+        picture_t pic;
+        int i_plane;
+
+        vout_InitPicture( VLC_OBJECT(p_stream), &pic,
+                          id->p_encoder->format.video.i_chroma,
+                          id->f_dst.i_width, id->f_dst.i_height,
+                          id->f_dst.i_width * VOUT_ASPECT_FACTOR /
+                          id->f_dst.i_height );
+
+        for( i_plane = 0; i_plane < pic.i_planes; i_plane++ )
+        {
+            pic.p[i_plane].p_pixels = frame->data[i_plane];
+            pic.p[i_plane].i_pitch = frame->linesize[i_plane];
+        }
+
+        pic.date = frame->pts;
+
+        p_block = id->p_encoder->pf_encode_video( id->p_encoder, &pic );
+        while( p_block )
+        {
+            sout_buffer_t *p_out;
+            block_t *p_prev_block = p_block;
+
+            p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
+            memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
+            p_out->i_dts = p_block->i_dts;
+            p_out->i_pts = p_block->i_pts;
+            p_out->i_length = p_block->i_length;
+            sout_BufferChain( out, p_out );
+
+            p_block = p_block->p_next;
+            block_Release( p_prev_block );
+        }
 
         if( i_data <= 0 )
         {