diff -uNr ffmpeg.orig/configure ffmpeg/configure
--- ffmpeg.orig/configure	2007-12-25 11:42:45.000000000 +0100
+++ ffmpeg/configure	2007-12-26 19:55:57.000000000 +0100
@@ -88,6 +88,7 @@
   echo "  --enable-libfaac         enable FAAC support via libfaac [default=no]"
   echo "  --enable-libfaad         enable FAAD support via libfaad [default=no]"
   echo "  --enable-libfaadbin      open libfaad.so.0 at runtime [default=no]"
+  echo "  --enable-libg729a        enable G.729A support via libg729a [default=no]"
   echo "  --enable-libgsm          enable GSM support via libgsm [default=no]"
   echo "  --enable-libmp3lame      enable MP3 encoding via libmp3lame [default=no]"
   echo "  --enable-libnut          enable NUT (de)muxing via libnut,"
@@ -622,6 +623,7 @@
     libfaac
     libfaad
     libfaadbin
+    libg729a
     libgsm
     libmp3lame
     libnut
@@ -781,6 +783,8 @@
 libfaac_encoder_deps="libfaac"
 libfaad_decoder_deps="libfaad"
 libfaadbin_decoder_extralibs='$ldl'
+g729a_decoder_deps="libg729a"
+g729a_encoder_deps="libg729a"
 libgsm_decoder_deps="libgsm"
 libgsm_encoder_deps="libgsm"
 libgsm_ms_decoder_deps="libgsm"
@@ -794,6 +798,8 @@
 
 # demuxers / muxers
 ac3_demuxer_deps="ac3_parser"
+act_muxer_deps="g729a_encoder"
+act_demuxer_deps="g729a_decoder"
 audio_beos_demuxer_deps="audio_beos"
 audio_beos_demuxer_extralibs="-lmedia -lbe"
 audio_beos_muxer_deps="audio_beos"
@@ -1608,6 +1614,7 @@
 enabled libdc1394  && require  libdc1394 libdc1394/dc1394_control.h dc1394_create_handle -ldc1394_control -lraw1394
 enabled libfaac    && require2 libfaac "stdint.h faac.h" faacEncGetVersion -lfaac
 enabled libfaad    && require2 libfaad faad.h faacDecOpen -lfaad
+enabled libg729a   && require  libg729a g729a.h g729a_encoder_init -lg729a
 enabled libgsm     && require  libgsm gsm.h gsm_create -lgsm
 enabled libmp3lame && require  LAME lame/lame.h lame_init -lmp3lame -lm
 enabled libnut     && require  libnut libnut.h nut_demuxer_init -lnut
@@ -1868,6 +1875,7 @@
 echo "libfaac enabled           ${libfaac-no}"
 echo "libfaad enabled           ${libfaad-no}"
 echo "libfaad dlopened          ${libfaadbin-no}"
+echo "libg729a enabled          ${libg729a-no}"
 echo "libgsm enabled            ${libgsm-no}"
 echo "libmp3lame enabled        ${libmp3lame-no}"
 echo "libnut enabled            ${libnut-no}"
diff -uNr ffmpeg.orig/libavcodec/adpcm.c ffmpeg/libavcodec/adpcm.c
--- ffmpeg.orig/libavcodec/adpcm.c	2007-11-06 22:51:04.000000000 +0100
+++ ffmpeg/libavcodec/adpcm.c	2007-12-26 20:04:43.000000000 +0100
@@ -149,6 +149,8 @@
 typedef struct ADPCMContext {
     int channel; /* for stereo MOVs, decode left, then decode right, then tell it's decoded */
     ADPCMChannelStatus status[6];
+    int extra_amv_samples; //number of samples to put into next frame
+    int samples_written;
 } ADPCMContext;
 
 /* XXX: implement encoding */
@@ -183,6 +185,16 @@
         }
         avctx->frame_size = 512 * (avctx->sample_rate / 11025);
         break;
+    case CODEC_ID_ADPCM_IMA_AMV:
+        if (avctx->channels != 1){
+            av_log(avctx, AV_LOG_ERROR, "Only mono sound is supported\n");
+            return -1;
+        }
+        if (avctx->sample_rate != 22050){
+            av_log(avctx, AV_LOG_ERROR, "Only 22050 sample rate is supported\n");
+            return -1;
+        }
+        break;        
     default:
         return -1;
         break;
@@ -295,7 +307,7 @@
     nodes[0]->step = c->step_index;
     nodes[0]->sample1 = c->sample1;
     nodes[0]->sample2 = c->sample2;
-    if((version == CODEC_ID_ADPCM_IMA_WAV) || (version == CODEC_ID_ADPCM_SWF))
+    if((version == CODEC_ID_ADPCM_IMA_WAV) || (version == CODEC_ID_ADPCM_SWF) || (version == CODEC_ID_ADPCM_IMA_AMV))
         nodes[0]->sample1 = c->prev_sample;
     if(version == CODEC_ID_ADPCM_MS)
         nodes[0]->step = c->idelta;
@@ -366,7 +378,7 @@
                     next_##NAME:;
                     STORE_NODE(ms, FFMAX(16, (AdaptationTable[nibble] * step) >> 8));
                 }
-            } else if((version == CODEC_ID_ADPCM_IMA_WAV)|| (version == CODEC_ID_ADPCM_SWF)) {
+            } else if((version == CODEC_ID_ADPCM_IMA_WAV)|| (version == CODEC_ID_ADPCM_SWF)|| (version == CODEC_ID_ADPCM_IMA_AMV)) {
 #define LOOP_NODES(NAME, STEP_TABLE, STEP_INDEX)\
                 const int predictor = nodes[j]->sample1;\
                 const int div = (sample - predictor) * 4 / STEP_TABLE;\
@@ -1585,7 +1597,7 @@
 ADPCM_DECODER(CODEC_ID_ADPCM_EA_R2, adpcm_ea_r2);
 ADPCM_DECODER(CODEC_ID_ADPCM_EA_R3, adpcm_ea_r3);
 ADPCM_DECODER(CODEC_ID_ADPCM_EA_XAS, adpcm_ea_xas);
-ADPCM_DECODER(CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv);
+ADPCM_CODEC  (CODEC_ID_ADPCM_IMA_AMV, adpcm_ima_amv);
 ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK3, adpcm_ima_dk3);
 ADPCM_DECODER(CODEC_ID_ADPCM_IMA_DK4, adpcm_ima_dk4);
 ADPCM_DECODER(CODEC_ID_ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
diff -uNr ffmpeg.orig/libavcodec/allcodecs.c ffmpeg/libavcodec/allcodecs.c
--- ffmpeg.orig/libavcodec/allcodecs.c	2007-12-20 10:57:16.000000000 +0100
+++ ffmpeg/libavcodec/allcodecs.c	2007-12-26 19:55:58.000000000 +0100
@@ -61,7 +61,7 @@
 
     /* video codecs */
     REGISTER_DECODER (AASC, aasc);
-    REGISTER_DECODER (AMV, amv);
+    REGISTER_ENCDEC  (AMV, amv);
     REGISTER_ENCDEC  (ASV1, asv1);
     REGISTER_ENCDEC  (ASV2, asv2);
     REGISTER_DECODER (AVS, avs);
@@ -179,6 +179,7 @@
     REGISTER_DECODER (DCA, dca);
     REGISTER_DECODER (DSICINAUDIO, dsicinaudio);
     REGISTER_ENCDEC  (FLAC, flac);
+    REGISTER_ENCDEC  (G729A, g729a);
     REGISTER_DECODER (IMC, imc);
     REGISTER_DECODER (MACE3, mace3);
     REGISTER_DECODER (MACE6, mace6);
@@ -242,7 +243,7 @@
     REGISTER_DECODER (ADPCM_EA_R3, adpcm_ea_r3);
     REGISTER_DECODER (ADPCM_EA_XAS, adpcm_ea_xas);
     REGISTER_ENCDEC  (ADPCM_G726, adpcm_g726);
-    REGISTER_DECODER (ADPCM_IMA_AMV, adpcm_ima_amv);
+    REGISTER_ENCDEC  (ADPCM_IMA_AMV, adpcm_ima_amv);
     REGISTER_DECODER (ADPCM_IMA_DK3, adpcm_ima_dk3);
     REGISTER_DECODER (ADPCM_IMA_DK4, adpcm_ima_dk4);
     REGISTER_DECODER (ADPCM_IMA_EA_EACS, adpcm_ima_ea_eacs);
diff -uNr ffmpeg.orig/libavcodec/avcodec.h ffmpeg/libavcodec/avcodec.h
--- ffmpeg.orig/libavcodec/avcodec.h	2007-12-21 17:43:20.000000000 +0100
+++ ffmpeg/libavcodec/avcodec.h	2007-12-26 19:55:58.000000000 +0100
@@ -274,6 +274,7 @@
     CODEC_ID_APE,
     CODEC_ID_NELLYMOSER,
     CODEC_ID_MUSEPACK8,
+    CODEC_ID_G729A,
 
     /* subtitle codecs */
     CODEC_ID_DVD_SUBTITLE= 0x17000,
diff -uNr ffmpeg.orig/libavcodec/g729dec.c ffmpeg/libavcodec/g729dec.c
--- ffmpeg.orig/libavcodec/g729dec.c	1970-01-01 01:00:00.000000000 +0100
+++ ffmpeg/libavcodec/g729dec.c	2007-12-26 19:55:58.000000000 +0100
@@ -0,0 +1,209 @@
+/*
+ * G.729 Annex A codec wrapper (around reference ITU's source)
+ * Copyright (c) 2007 Vladimir Voroshilov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avcodec.h"
+
+#include "bitstream.h"
+
+#include <g729a.h>
+
+typedef struct
+{
+    unsigned char format;
+#ifdef DEBUG_DUMP
+    FILE* f;
+    FILE* f2;
+#endif
+    void* priv;
+} G729Context;
+
+#define MAX_FORMATS 2
+
+#define MP1 11
+
+
+#ifdef G729_UNPACKED_LSP
+#define VECTOR_SIZE 15
+#define DEF_VECTOR(L0,L1,L2,L3,P1,P0,C1,S1,GA1,GB1,P2,C2,S2,GA2,GB2) {L0,L1,L2,L3,P1,P0,C1,S1,GA1,GB1,P2,C2,S2,GA2,GB2}
+#else
+#define VECTOR_SIZE 11
+#define DEF_VECTOR(L0,L1,L2,L3,P1,P0,C1,S1,GA1,GB1,P2,C2,S2,GA2,GB2) {(L0+L1),(L2+L3),P1,P0,C1,S1,(GA1+GB1),P2,C2,S2,(GA2+GB2)}
+#endif
+
+
+#define DEF_FRAME(frames, L0,L1,L2,L3,P1,P0,C1,S1,GA1,GB1,P2,C2,S2,GA2,GB2) (frames),(frames*(L1+L0+L1+L2+L3+P1+P0+C1+S1+GA1+GB1+P2+C2+S2+GA2+GB2)/8),DEF_VECTOR(L0,L1,L2,L3,P1,P0,C1,S1,GA1,GB1,P2,C2,S2,GA2,GB2) 
+
+static const struct{
+    char* name;
+    int sample_rate;
+    int frames;
+    short frame_size;
+    char vector_bits[VECTOR_SIZE];
+    char silence_compression;
+} formats[MAX_FORMATS]={
+  {"8Kb/s",   8000, DEF_FRAME(1, 1,7,5,5,8,1,13, 4,3,4,5,13, 4,3,4), 0},
+#ifdef G729_SUPPORT_4400
+  {"4.4Kb/s", 4400, DEF_FRAME(2, 1,7,5,5,8,1,12, 9,3,4,5,12, 9,3,4), 0},
+#endif //G729_SUPPORT_4400
+  { NULL,     0,    DEF_FRAME(0,0,0,0,0,0,0, 0, 0,0,0,0, 0, 0,0,0), 0}
+};
+
+#ifdef CONFIG_ENCODERS
+static int ff_g729a_encoder_init(AVCodecContext * avctx)
+{
+    G729Context *ctx=avctx->priv_data;
+
+    ctx->priv=g729a_encoder_init();
+
+    if(avctx->channels!=1)
+    {
+        av_log(avctx, AV_LOG_ERROR, "Only one channel is suported\n");
+        return -1;
+    }
+    for(ctx->format=0; formats[ctx->format].name; ctx->format++)
+        if(formats[ctx->format].sample_rate==avctx->sample_rate)
+            break;
+    if(!formats[ctx->format].name){
+        av_log(avctx, AV_LOG_ERROR, "Sample rate %d is not supported\n", avctx->sample_rate);
+        return -1;
+    }
+
+    avctx->frame_size=formats[ctx->format].frame_size*8;
+    avctx->block_align=avctx->frame_size;
+
+    avctx->coded_frame = avcodec_alloc_frame();
+    if (!avctx->coded_frame)
+        return AVERROR(ENOMEM);
+    avctx->coded_frame->key_frame = 1;
+
+    return 0;
+}
+
+static int ff_g729a_encode_frame(AVCodecContext *avctx,
+                            uint8_t *dst, int buf_size, void *data)
+{
+    G729Context *ctx=avctx->priv_data;
+    uint16_t serial[200];
+    PutBitContext pb;
+    int idx=2,i,k;
+
+    g729a_encode_frame(ctx->priv, data, 0/* not used yet*/, serial, buf_size);
+
+    init_put_bits(&pb, dst, buf_size*8);
+    for(i=0;i<formats[ctx->format].frame_size;i++)
+        for(k=0; k<8; k++){
+            put_bits(&pb, 1, serial[idx++]==0x81?1:0);
+        }
+
+    return (put_bits_count(&pb)+7)/8;
+}
+#endif //CONFIG_ENCODERS
+
+static int ff_g729a_decoder_init(AVCodecContext * avctx)
+{
+    G729Context *ctx=avctx->priv_data;
+
+    for(ctx->format=0; formats[ctx->format].name; ctx->format++)
+        if(formats[ctx->format].sample_rate==avctx->sample_rate)
+            break;
+    if(!formats[ctx->format].name){
+        av_log(avctx, AV_LOG_ERROR, "Sample rate %d is not supported\n", avctx->sample_rate);
+        return -1;
+    }
+
+    ctx->priv=g729a_decoder_init();
+#ifdef DEBUG_DUMP
+ctx->f=fopen("test2.bit","wb");
+ctx->f2=fopen("test2.raw","wb");
+#endif
+
+    avctx->frame_size=10;
+    return 0;
+}
+
+static int ff_g729a_close(AVCodecContext *avctx)
+{
+    G729Context *ctx=avctx->priv_data;
+#ifdef DEBUG_DUMP
+    if(ctx->f) fclose(ctx->f);
+    if(ctx->f2) fclose(ctx->f2);
+#endif
+    g729a_decoder_uninit(ctx->priv);
+    ctx->priv=NULL;
+    return 0;
+}
+
+static int ff_g729a_decode_frame(AVCodecContext *avctx,
+                             void *data, int *data_size,
+                             uint8_t *buf, int buf_size)
+{
+    G729Context *ctx=avctx->priv_data;
+    GetBitContext gb;
+    int i,j,k;
+    int l_frame=formats[ctx->format].frame_size*8;
+    uint16_t serial[200];
+
+    init_get_bits(&gb, buf, buf_size);
+
+    *data_size=0;
+    for(j=0; j<formats[ctx->format].frames; j++){
+        int dst=0;
+        serial[dst++]=0x6b21;
+        serial[dst++]=80;
+        
+        for(i=0;i<FFMIN((200-2)/8, buf_size);i++)
+            for(k=0; k<8; k++){
+                serial[dst++]=get_bits1(&gb)?0x81:0x7f;
+            }
+#ifdef DEBUG_DUMP
+        fwrite(serial,sizeof(uint16_t),l_frame+2,ctx->f);
+#endif
+        g729a_decode_frame(ctx->priv,serial, 0/*not used yet*/,(short*)data+j*l_frame, l_frame);
+        *data_size+=2*l_frame;
+    }
+#ifdef DEBUG_DUMP
+    fwrite(data,1,*data_size,ctx->f2);
+#endif
+    return buf_size;
+}
+
+#ifdef CONFIG_ENCODERS
+AVCodec g729a_encoder = {
+    "g729a",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_G729A,
+    sizeof(G729Context),
+    ff_g729a_encoder_init,
+    ff_g729a_encode_frame,
+    ff_g729a_close,
+};
+#endif //CONFIG_ENCODERS
+
+AVCodec g729a_decoder = {
+    "g729a",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_G729A,
+    sizeof(G729Context),
+    ff_g729a_decoder_init,
+    NULL,
+    ff_g729a_close,
+    ff_g729a_decode_frame,
+};
diff -uNr ffmpeg.orig/libavcodec/Makefile ffmpeg/libavcodec/Makefile
--- ffmpeg.orig/libavcodec/Makefile	2007-12-20 10:57:15.000000000 +0100
+++ ffmpeg/libavcodec/Makefile	2007-12-26 19:55:58.000000000 +0100
@@ -81,6 +81,9 @@
 OBJS-$(CONFIG_FLV_ENCODER)             += mpegvideo_enc.o motion_est.o ratecontrol.o h263.o
 OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
 OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o huffman.o
+OBJS-$(CONFIG_G729A_DECODER)           += g729dec.o
+
+
 OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
 OBJS-$(CONFIG_GIF_ENCODER)             += gif.o
 OBJS-$(CONFIG_H261_DECODER)            += h261dec.o h261.o
@@ -273,6 +276,7 @@
 OBJS-$(CONFIG_ADPCM_G726_DECODER)      += g726.o
 OBJS-$(CONFIG_ADPCM_G726_ENCODER)      += g726.o
 OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER)   += adpcm.o
+OBJS-$(CONFIG_ADPCM_IMA_AMV_ENCODER)   += adpcm.o
 OBJS-$(CONFIG_ADPCM_IMA_DK3_DECODER)   += adpcm.o
 OBJS-$(CONFIG_ADPCM_IMA_DK4_DECODER)   += adpcm.o
 OBJS-$(CONFIG_ADPCM_IMA_EA_EACS_DECODER) += adpcm.o
diff -uNr ffmpeg.orig/libavcodec/mjpegenc.c ffmpeg/libavcodec/mjpegenc.c
--- ffmpeg.orig/libavcodec/mjpegenc.c	2007-07-24 15:20:30.000000000 +0200
+++ ffmpeg/libavcodec/mjpegenc.c	2007-12-26 19:55:58.000000000 +0100
@@ -200,6 +200,9 @@
 
     put_marker(&s->pb, SOI);
 
+    // hack for AMV mjpeg format
+    if(s->avctx->codec_id == CODEC_ID_AMV) return;
+
     jpeg_put_comments(s);
 
     jpeg_table_header(s);
@@ -446,6 +449,28 @@
     }
 }
 
+// maximum over s->mjpeg_vsample[i]
+#define V_MAX 2
+int amv_encode_picture(AVCodecContext *avctx,
+                       unsigned char *buf, int buf_size, void *data)
+{
+
+    AVFrame* pic=data;
+    MpegEncContext *s = avctx->priv_data;
+    int i;
+
+    //CODEC_FLAG_EMU_EDGE have to be cleared
+    if(s->avctx->flags & CODEC_FLAG_EMU_EDGE)
+        return -1;
+
+    //picture should be flipped upside-down
+    for(i=0; i < 3; i++) {
+        pic->data[i] += (pic->linesize[i] * (s->mjpeg_vsample[i] * (8 * s->mb_height -((s->height/V_MAX)&7)) - 1 ));
+        pic->linesize[i] *= -1;
+    }
+    return MPV_encode_picture(avctx,buf, buf_size, pic);
+}
+
 AVCodec mjpeg_encoder = {
     "mjpeg",
     CODEC_TYPE_VIDEO,
@@ -456,3 +481,14 @@
     MPV_encode_end,
     .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, -1},
 };
+
+AVCodec amv_encoder = {
+    "amv",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_AMV,
+    sizeof(MpegEncContext),
+    MPV_encode_init,
+    amv_encode_picture,
+    MPV_encode_end,
+    .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, -1},
+};
diff -uNr ffmpeg.orig/libavcodec/mpegvideo_enc.c ffmpeg/libavcodec/mpegvideo_enc.c
--- ffmpeg.orig/libavcodec/mpegvideo_enc.c	2007-11-24 15:05:16.000000000 +0100
+++ ffmpeg/libavcodec/mpegvideo_enc.c	2007-12-26 19:55:58.000000000 +0100
@@ -248,6 +248,7 @@
         break;
     case CODEC_ID_LJPEG:
     case CODEC_ID_MJPEG:
+    case CODEC_ID_AMV:
         if(avctx->pix_fmt != PIX_FMT_YUVJ420P && avctx->pix_fmt != PIX_FMT_YUVJ422P &&
            ((avctx->pix_fmt != PIX_FMT_YUV420P && avctx->pix_fmt != PIX_FMT_YUV422P) || avctx->strict_std_compliance>FF_COMPLIANCE_INOFFICIAL)){
             av_log(avctx, AV_LOG_ERROR, "colorspace not supported in jpeg\n");
@@ -488,6 +489,11 @@
     if(s->codec_id==CODEC_ID_MJPEG){
         s->intra_quant_bias= 1<<(QUANT_BIAS_SHIFT-1); //(a + x/2)/x
         s->inter_quant_bias= 0;
+    }else if(s->codec_id==CODEC_ID_AMV){
+        s->intra_quant_bias= 0;
+        s->inter_quant_bias= 0;
+        s->fixed_qscale = 1;
+        s->adaptive_quant = 0;
     }else if(s->mpeg_quant || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO){
         s->intra_quant_bias= 3<<(QUANT_BIAS_SHIFT-3); //(a + x*3/8)/x
         s->inter_quant_bias= 0;
@@ -501,6 +507,8 @@
     if(avctx->inter_quant_bias != FF_DEFAULT_QUANT_BIAS)
         s->inter_quant_bias= avctx->inter_quant_bias;
 
+    av_log(avctx, AV_LOG_DEBUG, "intra_quant_bias = %d inter_quant_bias = %d\n",s->intra_quant_bias,s->inter_quant_bias);
+
     avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, &chroma_v_shift);
 
     if(avctx->codec_id == CODEC_ID_MPEG4 && s->avctx->time_base.den > (1<<16)-1){
@@ -523,6 +531,7 @@
         break;
     case CODEC_ID_LJPEG:
     case CODEC_ID_MJPEG:
+    case CODEC_ID_AMV:
         s->out_format = FMT_MJPEG;
         s->intra_only = 1; /* force intra only for jpeg */
         s->mjpeg_vsample[0] = 2;
@@ -1731,6 +1740,7 @@
             h263_encode_mb(s, s->block, motion_x, motion_y);
         break;
     case CODEC_ID_MJPEG:
+    case CODEC_ID_AMV:
         if (ENABLE_MJPEG_ENCODER)
             ff_mjpeg_encode_mb(s, s->block);
         break;
diff -uNr ffmpeg.orig/libavformat/act.c ffmpeg/libavformat/act.c
--- ffmpeg.orig/libavformat/act.c	1970-01-01 01:00:00.000000000 +0100
+++ ffmpeg/libavformat/act.c	2007-12-26 19:55:58.000000000 +0100
@@ -0,0 +1,253 @@
+/*
+ * ACT file format muxer/demuxer
+ * Copyright (c) 2007 Vladimir Voroshilov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include "riff.h"
+
+#define CHUNK_SIZE 512
+#define RIFF_TAG MKTAG('R','I','F','F')
+#define WAVE_TAG MKTAG('W','A','V','E')
+
+typedef  struct{
+    uint8_t tag;    //??? 0x84
+    uint16_t msec;  ///< duration msec
+    uint8_t  sec;   ///< duration sec
+    uint32_t minutes;   ///< Duration min
+} ACTHeader;
+
+typedef struct{
+    int bytes_left_in_chunk;
+    ACTHeader hdr;
+    offset_t data;
+    offset_t riff;
+    int frames;
+} ACTContext;
+
+#ifdef CONFIG_MUXERS
+static int act_write_header(AVFormatContext *s)
+{
+    ACTContext* ctx = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    AVCodecContext *enc = s->streams[0]->codec;
+    offset_t tmp;
+    int i;
+
+    if (enc->codec_id != CODEC_ID_G729A)
+        return -1;
+
+    ctx->riff=start_tag(pb, "RIFF");       /* magic number */
+    put_buffer(pb, "WAVE",4);
+    tmp=start_tag(pb, "fmt ");
+    put_le16(pb, 0x01);
+    put_le16(pb, 0x01);
+    put_le32(pb, enc->sample_rate);
+    put_le32(pb, enc->sample_rate*2);
+    put_le16(pb, 2);
+    put_le16(pb, 16);
+    end_tag(pb, tmp);    
+    ctx->data=start_tag(pb, "data");
+    tmp=url_ftell(pb);
+    for(i=0;i<512-tmp;i++)
+        put_byte(pb, 0);
+
+    ctx->frames=0;
+    put_flush_packet(pb);
+    return 0;
+}
+
+static int act_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    ACTContext* ctx = s->priv_data;
+    uint8_t *data=pkt->data;
+    int i;
+
+    if(!ctx->bytes_left_in_chunk)
+        ctx->bytes_left_in_chunk=CHUNK_SIZE;
+
+    put_byte(&s->pb, data[1]);
+    put_byte(&s->pb, data[3]);
+    put_byte(&s->pb, data[5]);
+    put_byte(&s->pb, data[7]);
+    put_byte(&s->pb, data[9]);
+    put_byte(&s->pb, data[0]);
+    put_byte(&s->pb, data[2]);
+    put_byte(&s->pb, data[4]);
+    put_byte(&s->pb, data[6]);
+    put_byte(&s->pb, data[8]);
+
+    ctx->bytes_left_in_chunk-=pkt->size;
+    
+    if(ctx->bytes_left_in_chunk<pkt->size)
+        for(; ctx->bytes_left_in_chunk; ctx->bytes_left_in_chunk--)
+            put_byte(&s->pb, 0);
+
+    put_flush_packet(&s->pb);
+    ctx->frames++;
+    return 0;
+}
+static int act_write_trailer(AVFormatContext *s)
+{
+    ACTContext* ctx = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    AVCodecContext *enc = s->streams[0]->codec;
+    int duration;
+    offset_t tmp;
+
+    tmp=url_ftell(pb);
+    tmp%=512;
+    for(; tmp<512; tmp++)
+        put_byte(pb, 0);
+
+    end_tag(pb, ctx->data);
+    end_tag(pb, ctx->riff);
+    duration=av_rescale(ctx->frames, 1000*enc->frame_size, enc->sample_rate);
+av_log(s, AV_LOG_ERROR, "Duration %d\n", duration);
+
+    url_fseek(pb, 256, SEEK_SET);
+    put_byte(pb, 0x84);
+    put_le16(pb, duration % 1000); //milliseconds
+    duration/=1000;
+    put_byte(pb, duration %60); //seconds
+    duration/=60;
+    put_le32(pb, duration); //minutes
+    
+    put_flush_packet(pb);
+    return 0;
+}
+#endif //CONFIG_MUXERS
+
+static int act_probe(AVProbeData *p)
+{
+    ACTHeader* hdr=(ACTHeader*)&p->buf[256];
+
+    if ((AV_RL32(&p->buf[0]) != RIFF_TAG) ||
+        (AV_RL32(&p->buf[8]) != WAVE_TAG) ||
+        (AV_RL32(&p->buf[16]) != 16))
+    return 0;
+
+    if(hdr->tag!=0x84)
+        return 0;
+
+    return AVPROBE_SCORE_MAX;
+}
+
+static int act_read_header(AVFormatContext *s,
+                           AVFormatParameters *ap)
+{
+    ACTContext* ctx = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    int size;
+    AVStream* st;
+
+    st=av_new_stream(s, 0);
+    if (!st)
+        return AVERROR(ENOMEM);
+    url_fskip(pb, 16);
+    size=get_le32(pb);
+    get_wav_header(pb, st->codec, size);
+
+    url_fseek(pb, 256, SEEK_SET);
+    if (get_buffer(pb, (char*)&ctx->hdr, sizeof(ctx->hdr))!=sizeof(ctx->hdr))
+        return AVERROR(EIO);
+
+
+    st->codec->codec_tag = 0;
+    st->codec->codec_id=CODEC_ID_G729A;
+    st->codec->frame_size=10;
+
+    st->duration=(ctx->hdr.minutes*60+ctx->hdr.sec)*100+ctx->hdr.msec/10;
+
+    av_set_pts_info(st, 64, 1, 800);
+
+    if(st->codec->sample_rate!=8000 && st->codec->sample_rate!=4400)
+    {
+        av_log(s, AV_LOG_ERROR, "Sample rate %d is not supported\n", st->codec->sample_rate);
+        return -1;
+    }
+
+
+    ctx->bytes_left_in_chunk=CHUNK_SIZE;
+
+    url_fseek(pb, 512, SEEK_SET);
+    return 0;
+}
+
+
+static int act_read_packet(AVFormatContext *s,
+                          AVPacket *pkt)
+{
+    ACTContext* ctx = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    uint8_t bFrame[22];
+    uint8_t *pkt_buf;
+    int i, bytes_read;
+    int frame_size=s->streams[0]->codec->frame_size;
+    
+    bytes_read = get_buffer(pb, bFrame, frame_size);
+
+    if(bytes_read != frame_size || av_new_packet(pkt, frame_size))
+        return AVERROR(EIO);
+
+    pkt_buf=(uint16_t*)pkt->data;
+
+    pkt_buf[1]=bFrame[0];
+    pkt_buf[3]=bFrame[1];
+    pkt_buf[5]=bFrame[2];
+    pkt_buf[7]=bFrame[3];
+    pkt_buf[9]=bFrame[4];
+    pkt_buf[0]=bFrame[5];
+    pkt_buf[2]=bFrame[6];
+    pkt_buf[4]=bFrame[7];
+    pkt_buf[6]=bFrame[8];
+    pkt_buf[8]=bFrame[9];
+
+    ctx->bytes_left_in_chunk -= frame_size;
+
+    if(ctx->bytes_left_in_chunk < frame_size)
+    {
+        url_fskip(pb, ctx->bytes_left_in_chunk);
+        ctx->bytes_left_in_chunk=CHUNK_SIZE;
+    }
+
+    return 0;
+}
+#ifdef CONFIG_MUXERS
+AVOutputFormat act_muxer = {
+    "act",
+    "ACT",
+    "audio/act",
+    "act",
+    sizeof(ACTContext),
+    CODEC_ID_G729A,
+    CODEC_ID_NONE,
+    act_write_header,
+    act_write_packet,
+    act_write_trailer,
+};
+#endif //CONFIG_MUXERS
+
+AVInputFormat act_demuxer = {
+    "act",
+    "ACT Voice file format",
+    sizeof(ACTContext),
+    act_probe,
+    act_read_header,
+    act_read_packet
+};
diff -uNr ffmpeg.orig/libavformat/allformats.c ffmpeg/libavformat/allformats.c
--- ffmpeg.orig/libavformat/allformats.c	2007-11-24 15:05:20.000000000 +0100
+++ ffmpeg/libavformat/allformats.c	2007-12-26 19:55:58.000000000 +0100
@@ -52,9 +52,11 @@
     /* (de)muxers */
     REGISTER_DEMUXER  (AAC, aac);
     REGISTER_MUXDEMUX (AC3, ac3);
+    REGISTER_MUXDEMUX (ACT, act);
     REGISTER_MUXER    (ADTS, adts);
     REGISTER_MUXDEMUX (AIFF, aiff);
     REGISTER_MUXDEMUX (AMR, amr);
+    REGISTER_MUXER    (AMV, amv);
     REGISTER_DEMUXER  (APC, apc);
     REGISTER_DEMUXER  (APE, ape);
     REGISTER_MUXDEMUX (ASF, asf);
diff -uNr ffmpeg.orig/libavformat/amvenc.c ffmpeg/libavformat/amvenc.c
--- ffmpeg.orig/libavformat/amvenc.c	1970-01-01 01:00:00.000000000 +0100
+++ ffmpeg/libavformat/amvenc.c	2007-12-26 19:55:58.000000000 +0100
@@ -0,0 +1,422 @@
+/*
+ * AMV muxer
+ * Copyright (c) 2000 Fabrice Bellard.
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "avformat.h"
+#include "amv.h"
+#include "riff.h"
+
+/*
+ * TODO:
+ *  - fill all fields if non streamed (nb_frames for example)
+ */
+
+#ifdef CONFIG_AMV_MUXER
+
+
+typedef struct {
+    offset_t riff_start, movi_list, odml_list;
+    offset_t frames_hdr_all, frames_hdr_strm[MAX_STREAMS];
+    offset_t hours, minutes, seconds;
+    int audio_strm_length[MAX_STREAMS];
+    int riff_id;
+    int packet_count[MAX_STREAMS];
+    int last_stream_index;
+} AMVContext;
+
+static offset_t avi_start_new_riff(AMVContext *avi, ByteIOContext *pb,
+                                   const char* riff_tag, const char* list_tag)
+{
+    offset_t loff;
+
+    avi->riff_id++;
+
+    avi->riff_start = start_tag(pb, "RIFF");
+    put_tag(pb, riff_tag);
+    loff = start_tag(pb, "LIST");
+    put_tag(pb, list_tag);
+    return loff;
+}
+
+static char* avi_stream2fourcc(char* tag, int index, enum CodecType type)
+{
+    tag[0] = '0';
+    tag[1] = '0' + index;
+    if (type == CODEC_TYPE_VIDEO) {
+        tag[2] = 'd';
+        tag[3] = 'c';
+    } else {
+        tag[2] = 'w';
+        tag[3] = 'b';
+    }
+    tag[4] = '\0';
+    return tag;
+}
+
+static int avi_write_counters(AVFormatContext* s, int riff_id)
+{
+    ByteIOContext *pb = &s->pb;
+    AMVContext *avi = s->priv_data;
+    int n, au_byterate, au_ssize, au_scale, nb_frames = 0;
+    offset_t file_size;
+    AVCodecContext* stream;
+
+    file_size = url_ftell(pb);
+    for(n = 0; n < s->nb_streams; n++) {
+        assert(avi->frames_hdr_strm[n]);
+        stream = s->streams[n]->codec;
+        url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET);
+        ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
+        if(au_ssize == 0) {
+            put_le32(pb, avi->packet_count[n]);
+        } else {
+            put_le32(pb, avi->audio_strm_length[n] / au_ssize);
+        }
+        if(stream->codec_type == CODEC_TYPE_VIDEO)
+            nb_frames = FFMAX(nb_frames, avi->packet_count[n]);
+    }
+    if(riff_id == 1) {
+        assert(avi->frames_hdr_all);
+        url_fseek(pb, avi->frames_hdr_all, SEEK_SET);
+        put_le32(pb, nb_frames);
+        
+        // HACK !
+        int duration_seconds = nb_frames/s->streams[0]->codec->time_base.den;
+        assert(avi->seconds);
+        url_fseek(pb, avi->seconds, SEEK_SET);
+        put_byte(pb,duration_seconds%60);
+        assert(avi->minutes);
+        url_fseek(pb, avi->minutes, SEEK_SET);
+        put_byte(pb,duration_seconds/60);
+        assert(avi->hours);
+        url_fseek(pb, avi->hours, SEEK_SET);
+        put_le16(pb,duration_seconds/3600);
+    }
+    url_fseek(pb, file_size, SEEK_SET);
+
+    return 0;
+}
+
+static int avi_write_header(AVFormatContext *s)
+{
+    AMVContext *avi = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale;
+    AVCodecContext *stream, *video_enc;
+    offset_t list1, list2, strh, strf;
+
+    avi->last_stream_index=1;
+
+    /* header list */
+    avi->riff_id = 0;
+    list1 = avi_start_new_riff(avi, pb, "AMV ", "hdrl");
+
+    /* avi header */
+    put_tag(pb, "amvh");
+    put_le32(pb, 14 * 4);
+    bitrate = 0;
+
+    video_enc = NULL;
+    for(n=0;n<s->nb_streams;n++) {
+        stream = s->streams[n]->codec;
+        bitrate += stream->bit_rate;
+        if (stream->codec_type == CODEC_TYPE_VIDEO)
+            video_enc = stream;
+    }
+
+    nb_frames = 0;
+
+    if(video_enc){
+        put_le32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den));
+    } else {
+        put_le32(pb, 0);
+    }
+    put_le32(pb, bitrate / 8); /* XXX: not quite exact */
+    put_le32(pb, 0); /* padding */
+    if (url_is_streamed(pb))
+        put_le32(pb, AMVF_TRUSTCKTYPE | AMVF_ISINTERLEAVED); /* flags */
+    else
+        put_le32(pb, AMVF_TRUSTCKTYPE | AMVF_HASINDEX | AMVF_ISINTERLEAVED); /* flags */
+    avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */
+    put_le32(pb, nb_frames); /* nb frames, filled later */
+    put_le32(pb, 0); /* initial frame */
+    put_le32(pb, s->nb_streams); /* nb streams */
+    put_le32(pb, 1024 * 1024); /* suggested buffer size */
+    if(video_enc){
+        put_le32(pb, video_enc->width);
+        put_le32(pb, video_enc->height);
+    } else {
+        put_le32(pb, 0);
+        put_le32(pb, 0);
+    }
+
+    put_le32(pb, video_enc->time_base.den); // edited from AVI: framerate instead of reserved
+    put_le32(pb, 1); // This is always 1 in a real AMV
+    put_le32(pb, 0); /* reserved */
+    
+    avi->seconds = url_ftell(pb); /* remember this offset to fill later */
+    put_byte(pb,0);
+    avi->minutes = url_ftell(pb); /* remember this offset to fill later */
+    put_byte(pb,0);
+    avi->hours = url_ftell(pb); /* remember this offset to fill later */
+    put_le16(pb, 0);     // duration minutes (filled in later)
+
+    /* stream list */
+    for(i=0;i<n;i++) {
+        list2 = start_tag(pb, "LIST");
+        put_tag(pb, "strl");
+
+        stream = s->streams[i]->codec;
+
+        /* stream generic header */
+        strh = start_tag(pb, "strh");
+        switch(stream->codec_type) {
+        case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); break;
+        case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); break;
+        }
+        if(stream->codec_type == CODEC_TYPE_VIDEO)
+            put_le32(pb, stream->codec_tag);
+        else
+            put_le32(pb, 1);
+        put_le32(pb, 0); /* flags */
+        put_le16(pb, 0); /* priority */
+        put_le16(pb, 0); /* language */
+        put_le32(pb, 0); /* initial frame */
+
+        if(stream->codec_type==CODEC_TYPE_AUDIO && i==1)
+        {
+            au_ssize=2;
+            au_scale=s->streams[0]->time_base.num;
+            au_byterate=s->streams[0]->time_base.den;
+        }else
+        ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale);
+
+        put_le32(pb, au_scale); /* scale */
+        put_le32(pb, au_byterate); /* rate */
+        av_set_pts_info(s->streams[i], 64, au_scale, au_byterate);
+
+        put_le32(pb, 0); /* start */
+        avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */
+        if (url_is_streamed(pb))
+            put_le32(pb, AMV_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */
+        else
+            put_le32(pb, 0); /* length, XXX: filled later */
+
+        /* suggested buffer size */ //FIXME set at the end to largest chunk
+        if(stream->codec_type == CODEC_TYPE_VIDEO) {
+            put_le32(pb, 1024 * 1024);
+            put_le32(pb, -1); /* quality */
+        } else if(stream->codec_type == CODEC_TYPE_AUDIO) {
+            //put_le32(pb, 12 * 1024);
+        } else 
+            put_le32(pb, 0);
+        put_le32(pb, au_ssize); /* sample size */
+        put_le32(pb, 0);
+        put_le16(pb, stream->width);
+        put_le16(pb, stream->height);
+        end_tag(pb, strh);
+
+      if(stream->codec_type != CODEC_TYPE_DATA){
+        strf = start_tag(pb, "strf");
+        switch(stream->codec_type) {
+        case CODEC_TYPE_VIDEO:
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            put_le32(pb, 0);
+            break;
+        case CODEC_TYPE_AUDIO:
+            if (put_wav_header(pb, stream) < 0) {
+                av_free(avi);
+                return -1;
+            }
+	    put_le32(pb, 0);
+            break;
+        default:
+            return -1;
+        }
+        end_tag(pb, strf);
+      }
+
+        end_tag(pb, list2);
+    }
+
+    end_tag(pb, list1);
+
+    avi->movi_list = start_tag(pb, "LIST");
+    put_tag(pb, "movi");
+
+    put_flush_packet(pb);
+
+    /*
+     HACK!!!
+     Set correct frame_size for audio stream
+    */
+    if(s->nb_streams > 1 && s->streams[1]->codec->codec_type == CODEC_TYPE_AUDIO) {
+	    s->streams[1]->codec->frame_size=av_rescale(
+		    s->streams[1]->codec->sample_rate,
+		    s->streams[0]->codec->time_base.num,
+		    s->streams[0]->codec->time_base.den);
+    }
+
+    return 0;
+}
+
+
+static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    AMVContext *avi = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    unsigned char tag[5];
+    unsigned int flags=0;
+    const int stream_index= pkt->stream_index;
+    AVCodecContext *enc= s->streams[stream_index]->codec;
+    int size= pkt->size;
+
+//    av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index);
+    while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avi->packet_count[stream_index]){
+        AVPacket empty_packet;
+
+        av_init_packet(&empty_packet);
+        empty_packet.size= 0;
+        empty_packet.data= NULL;
+        empty_packet.stream_index= stream_index;
+        avi_write_packet(s, &empty_packet);
+//        av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]);
+    }
+    avi->packet_count[stream_index]++;
+
+    avi_stream2fourcc(&tag[0], stream_index, enc->codec_type);
+    if(pkt->flags&PKT_FLAG_KEY)
+        flags = 0x10;
+    if (enc->codec_type == CODEC_TYPE_AUDIO) {
+       avi->audio_strm_length[stream_index] += size;
+    }
+
+    put_buffer(pb, tag, 4);
+    put_le32(pb, size);
+    put_buffer(pb, pkt->data, size);
+    //Data in AMV files are not aligned by 2 bytes
+//    if (size & 1) put_byte(pb, 0);
+
+    put_flush_packet(pb);
+    return 0;
+}
+
+static int avi_write_trailer(AVFormatContext *s)
+{
+    AMVContext *avi = s->priv_data;
+    ByteIOContext *pb = &s->pb;
+    int res = 0;
+
+    if (!url_is_streamed(pb)){
+        if (avi->riff_id == 1) {
+            end_tag(pb, avi->movi_list);
+            put_tag(pb, "AMV_END_");	// Added by Tom from AMV compatibility
+            end_tag(pb, avi->riff_start);
+        }
+    }
+    avi_write_counters(s, avi->riff_id);
+    put_flush_packet(pb);
+
+    return res;
+}
+
+static void amv_queue_packet(AVPacket *pkt, AVPacketList** ppktl){
+    AVPacketList* pktl, **next_point;
+
+    pktl = av_mallocz(sizeof(AVPacketList));
+    pktl->pkt= *pkt;
+
+//        assert(pkt->destruct != av_destruct_packet); //FIXME
+
+    if(pkt->destruct == av_destruct_packet)
+        pkt->destruct= NULL; // non shared -> must keep original from being freed
+    else
+        av_dup_packet(&pktl->pkt);  //shared -> must dup
+
+    next_point = ppktl;
+    while(*next_point){
+        next_point= &(*next_point)->next;
+    }
+    pktl->next= *next_point;
+    *next_point= pktl;
+}
+
+static AVPacket amv_dequeue_packet(AVPacketList** ppktl){
+    AVPacketList* pktl;
+    AVPacket pkt;
+
+    pktl=*ppktl;
+    *ppktl=pktl->next;
+    pkt=pktl->pkt;
+    av_freep(&pktl);
+    return pkt;
+}
+
+static int amv_interleave_packet(struct AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
+{
+    AVPacketList *pktl;
+    AMVContext* amv=s->priv_data;
+
+    if(pkt)
+        amv_queue_packet(pkt,&s->packet_buffer);
+
+    if(s->packet_buffer && s->packet_buffer->pkt.stream_index!=amv->last_stream_index){
+        *out=amv_dequeue_packet(&s->packet_buffer);
+	amv->last_stream_index=out->stream_index;
+        return 1;
+    }
+    pktl= s->packet_buffer;
+    while(pktl && pktl->next){
+        if(pktl->next->pkt.stream_index!=amv->last_stream_index)
+            break;
+        pktl=pktl->next;
+    }
+
+    if(pktl && pktl->next){
+        *out=amv_dequeue_packet(&pktl->next);
+	amv->last_stream_index=out->stream_index;
+        return 1;
+    }else{
+        av_init_packet(out);
+        return 0;
+    }
+}
+
+AVOutputFormat amv_muxer = {
+    "amv",
+    "amv format",
+    "video/amv",
+    "amv",
+    sizeof(AMVContext),
+    CODEC_ID_ADPCM_IMA_AMV,
+    CODEC_ID_AMV,
+    avi_write_header,
+    avi_write_packet,
+    avi_write_trailer,
+    .interleave_packet=amv_interleave_packet,
+    .codec_tag= (const AVCodecTag*[]){codec_bmp_tags, codec_wav_tags, 0},
+};
+#endif //CONFIG_AMV_MUXER
diff -uNr ffmpeg.orig/libavformat/amv.h ffmpeg/libavformat/amv.h
--- ffmpeg.orig/libavformat/amv.h	1970-01-01 01:00:00.000000000 +0100
+++ ffmpeg/libavformat/amv.h	2007-12-26 19:55:58.000000000 +0100
@@ -0,0 +1,39 @@
+/*
+ * copyright (c) 2001 Fabrice Bellard
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFMPEG_AMV_H
+#define FFMPEG_AMV_H
+
+#include "avcodec.h"
+
+#define AMVF_HASINDEX           0x00000010        // Index at end of file?
+#define AMVF_MUSTUSEINDEX       0x00000020
+#define AMVF_ISINTERLEAVED      0x00000100
+#define AMVF_TRUSTCKTYPE        0x00000800        // Use CKType to find key frames?
+#define AMVF_WASCAPTUREFILE     0x00010000
+#define AMVF_COPYRIGHTED        0x00020000
+
+#define AMV_MAX_RIFF_SIZE       0x40000000LL
+#define AMV_MASTER_INDEX_SIZE   256
+
+/* index flags */
+#define AMVIF_INDEX             0x10
+
+#endif /* FFMPEG_AMV_H */
diff -uNr ffmpeg.orig/libavformat/Makefile ffmpeg/libavformat/Makefile
--- ffmpeg.orig/libavformat/Makefile	2007-11-24 15:05:20.000000000 +0100
+++ ffmpeg/libavformat/Makefile	2007-12-26 19:55:58.000000000 +0100
@@ -13,12 +13,15 @@
 # muxers/demuxers
 OBJS-$(CONFIG_AAC_DEMUXER)               += raw.o
 OBJS-$(CONFIG_AC3_DEMUXER)               += raw.o
+OBJS-$(CONFIG_ACT_DEMUXER)               += act.o
+OBJS-$(CONFIG_ACT_MUXER)                 += act.o
 OBJS-$(CONFIG_AC3_MUXER)                 += raw.o
 OBJS-$(CONFIG_ADTS_MUXER)                += adtsenc.o
 OBJS-$(CONFIG_AIFF_DEMUXER)              += aiff.o riff.o raw.o
 OBJS-$(CONFIG_AIFF_MUXER)                += aiff.o riff.o
 OBJS-$(CONFIG_AMR_DEMUXER)               += amr.o
 OBJS-$(CONFIG_AMR_MUXER)                 += amr.o
+OBJS-$(CONFIG_AMV_MUXER)                 += amvenc.o
 OBJS-$(CONFIG_APC_DEMUXER)               += apc.o
 OBJS-$(CONFIG_APE_DEMUXER)               += ape.o
 OBJS-$(CONFIG_ASF_DEMUXER)               += asf.o asfcrypt.o riff.o
diff -uNr ffmpeg.orig/libavformat/riff.c ffmpeg/libavformat/riff.c
--- ffmpeg.orig/libavformat/riff.c	2007-10-27 13:18:05.000000000 +0200
+++ ffmpeg/libavformat/riff.c	2007-12-26 19:55:58.000000000 +0100
@@ -188,6 +188,7 @@
     { CODEC_ID_PCM_MULAW, 0x07 },
     { CODEC_ID_ADPCM_MS, 0x02 },
     { CODEC_ID_ADPCM_IMA_WAV, 0x11 },
+    { CODEC_ID_ADPCM_IMA_AMV, 0x01 },
     { CODEC_ID_ADPCM_YAMAHA, 0x20 },
     { CODEC_ID_ADPCM_G726, 0x45 },
     { CODEC_ID_ADPCM_IMA_DK4, 0x61 },  /* rogue format number */
