[FFmpeg-cvslog] r20839 - trunk/libavformat/id3v2.c

Michael Niedermayer michaelni
Mon Dec 14 12:23:39 CET 2009


On Mon, Dec 14, 2009 at 07:54:49AM +0100, Reimar D?ffinger wrote:
> On Mon, Dec 14, 2009 at 02:53:48AM +0100, Michael Niedermayer wrote:
> > whats left currently is: (note i manually edited the diff so i cant gurantee
> > that the stat is completely correctly, iam not sure how good diffstat is at
> > manually edited diffs)
> 
> Can you just dump that diff somewhere? I think the gxf and s302m stuff is "mine",
> though I expect I might lack samples for them.

attached, but keep in mind these are my work in progress diffs they are
hand edited with hunks and lines removed that where merged or that i
considered not worth the work merging (too much work / bikeshed / things
appearing incomplete or buggy). Its possible i also removed changes by
mistake from them!

speaking about s302, libavformat/s302m.c is libavformat/daud.c in svn
and thus something i droped, only the libavcodec side is left in the diff.

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Frequently ignored awnser#1 FFmpeg bugs should be sent to our bugtracker. User
questions about the command line tools should be sent to the ffmpeg-user ML.
And questions about how to use libav* should be sent to the libav-user ML.
-------------- next part --------------
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/ffmpeg.c	2009-12-13 14:15:18.000000000 +0100
+++ ./ffmpeg.c	2009-11-15 04:50:19.000000000 +0100
@@ -81,6 +81,16 @@
     int sync_stream_index;
 } AVStreamMap;
 
+/* select an audio channel to extract */
+typedef struct AVAudioChannelMap {
+    int file_index;
+    int stream_index;
+    int channel_index;
+    int out_file_index;
+    int out_stream_index;
+    int out_channel_index;
+} AVAudioChannelMap;
+
 /** select an input file for an output file */
 typedef struct AVMetaDataMap {
     int out_file;
@@ -104,6 +114,11 @@
 static int nb_output_files = 0;
 static int nb_ocodecs;
 
+#define MAX_AUDIO_CHANNEL_MAPS 8
+
+static AVAudioChannelMap audio_channel_maps[MAX_AUDIO_CHANNEL_MAPS];
+static int nb_audio_channel_maps;
+
 static AVStreamMap stream_maps[MAX_FILES*MAX_STREAMS];
 static int nb_stream_maps;
 
@@ -163,6 +178,7 @@
 static float mux_max_delay= 0.7;
 
 static int64_t recording_time = INT64_MAX;
+static int seek_requested;
 static int64_t start_time = 0;
 static int64_t rec_timestamp = 0;
 static int64_t input_ts_offset = 0;
@@ -187,7 +203,7 @@
 static char *vstats_filename;
 static FILE *vstats_file;
 static int opt_programid = 0;
-static int copy_initial_nonkeyframes = 0;
+static int copy_initial_nonkeyframes = 1;
 
 static int rate_emu = 0;
 
@@ -232,10 +248,20 @@
 
 struct AVInputStream;
 
+typedef struct {
+    uint8_t *buf;
+    unsigned buf_size;
+    unsigned last_sample_pos; /* last valid sample pos in buf */
+    unsigned buf_index[MAX_AUDIO_CHANNEL_MAPS];
+    uint8_t sample_size; /* size of one sample */
+    uint8_t out_channels;
+} AudioMergeContext;
+
 typedef struct AVOutputStream {
     int file_index;          /* file index */
     int index;               /* stream index in the output file */
-    int source_index;        /* AVInputStream index */
+    int source_index[MAX_AUDIO_CHANNEL_MAPS]; /* AVInputStream index */
+    int nb_source_indexes;   /* number of source indexes */
     AVStream *st;            /* stream in the output file */
     int encoding_needed;     /* true if encoding needed for this stream */
     int frame_number;
@@ -277,12 +303,21 @@
     int padright;
 
     /* audio only */
+    AVAudioChannelMap *audio_channel_maps[MAX_AUDIO_CHANNEL_MAPS];
+    int nb_audio_channel_maps;
+    uint8_t *audio_merge_buf;
+    AudioMergeContext audiomerge;
+
     int audio_resample;
     ReSampleContext *resample; /* for audio resampling */
     int reformat_pair;
     AVAudioConvert *reformat_ctx;
     AVFifoBuffer *fifo;     /* for compression: one audio fifo per codec */
     FILE *logfile;
+
+    /* stream copy */
+    int got_key; /* got a keyframe for this stream,
+                    used with copy_initial_nonkeyframes */
 } AVOutputStream;
 
 typedef struct AVInputStream {
@@ -294,9 +329,13 @@
     int64_t sample_index;      /* current sample */
 
     int64_t       start;     /* time when read started */
-    int64_t       next_pts;  /* synthetic pts for cases where pkt.pts
-                                is not defined */
+    int64_t       last_dts;  /* dts of the previous frame, used when no pts */
+    int64_t       dts;       /* current dts */
     int64_t       pts;       /* current pts */
+    int           has_pts;   /* stream has pts */
+    int64_t       next_pts;  /* computed pts of the next frame */
+    int64_t       next_dts;  /* only used in video stream copy */
+    int broken_pts;
     int is_start;            /* is 1 at the start and after a discontinuity */
 } AVInputStream;
 
@@ -514,7 +553,9 @@
 get_sync_ipts(const AVOutputStream *ost)
 {
     const AVInputStream *ist = ost->sync_ist;
-    return (double)(ist->pts - start_time)/AV_TIME_BASE;
+    if (ist->pts != AV_NOPTS_VALUE)
+        return (double)(ist->pts - start_time)/AV_TIME_BASE;
+    return NAN;
 }
 
 static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
@@ -549,6 +590,78 @@
     }
 }
 
+static int audiomerge_init(AudioMergeContext *a, uint8_t out_channels,
+                           uint8_t sample_size, unsigned samples)
+{
+    int i;
+
+    a->out_channels = out_channels;
+    a->sample_size = sample_size;
+
+    if (out_channels*sample_size >= UINT_MAX / samples)
+        return -1;
+    a->buf_size = out_channels*sample_size*samples;
+    a->buf = av_malloc(a->buf_size);
+    if (!a->buf)
+        return -1;
+
+    for (i = 0; i < out_channels; i++)
+        a->buf_index[i] = i*sample_size;
+
+    return 0;
+}
+
+static int audiomerge_add_channel(AudioMergeContext *a, uint8_t *input,
+                                  unsigned in_channel, unsigned out_channel,
+                                  unsigned in_channels, unsigned samples)
+{
+    if (out_channel >= a->out_channels)
+        return -1;
+
+    //fprintf(stderr, "in channel %d out channel %d samples %d\n", in_channel, out_channel, samples);
+
+    if (a->buf_index[out_channel] +
+        (int64_t)samples*a->sample_size*a->out_channels >= a->buf_size)
+        return -1;
+
+    input += a->sample_size*in_channel;
+    while (samples--) {
+        memcpy(a->buf + a->buf_index[out_channel], input, a->sample_size);
+        a->buf_index[out_channel] += a->sample_size*a->out_channels;
+        input += a->sample_size*in_channels;
+    }
+
+    a->last_sample_pos = FFMAX(a->buf_index[out_channel], a->last_sample_pos);
+
+    return 0;
+}
+
+
+static unsigned audiomerge_complete_size(AudioMergeContext *a)
+{
+    int i, min = INT_MAX;
+    int align = a->out_channels*a->sample_size;
+
+    for (i = 0; i < a->out_channels; i++)
+        min = FFMIN(a->buf_index[i], min);
+    return (min / align) * align;
+}
+
+static void audiomerge_drain_complete_size(AudioMergeContext *a)
+{
+    int i;
+    unsigned complete_size = audiomerge_complete_size(a);
+
+    if (!complete_size)
+        return;
+
+    memmove(a->buf, a->buf + complete_size,
+            a->last_sample_pos - complete_size);
+    a->last_sample_pos -= complete_size;
+    for (i = 0; i < a->out_channels; i++)
+        a->buf_index[i] -= complete_size;
+}
+
 #define MAX_AUDIO_PACKET_SIZE (128 * 1024)
 
 static void do_audio_out(AVFormatContext *s,
@@ -564,6 +677,7 @@
     AVCodecContext *dec= ist->st->codec;
     int osize= av_get_bits_per_sample_format(enc->sample_fmt)/8;
     int isize= av_get_bits_per_sample_format(dec->sample_fmt)/8;
+    int out_channels;
 
     /* SC: dynamic allocation of buffers */
     if (!audio_buf)
@@ -573,20 +687,25 @@
     if (!audio_buf || !audio_out)
         return;               /* Should signal an error ! */
 
-    if (enc->channels != dec->channels)
+    if (ost->nb_audio_channel_maps > 0)
+        out_channels = dec->channels; // do not mix channels
+    else
+        out_channels = enc->channels;
+
+    if (out_channels != dec->channels)
         ost->audio_resample = 1;
 
     if (ost->audio_resample && !ost->resample) {
         if (dec->sample_fmt != SAMPLE_FMT_S16)
             fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n");
-        ost->resample = av_audio_resample_init(enc->channels,    dec->channels,
+        ost->resample = av_audio_resample_init(out_channels,    dec->channels,
                                                enc->sample_rate, dec->sample_rate,
                                                enc->sample_fmt,  dec->sample_fmt,
                                                16, 10, 0, 0.8);
         if (!ost->resample) {
             fprintf(stderr, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n",
                     dec->channels, dec->sample_rate,
-                    enc->channels, enc->sample_rate);
+                    out_channels, enc->sample_rate);
             av_exit(1);
         }
     }
@@ -611,12 +730,17 @@
         ost->reformat_pair=MAKE_SFMT_PAIR(enc->sample_fmt,dec->sample_fmt);
     }
 
+    if(!isnan(get_sync_ipts(ost))) {
     if(audio_sync_method){
         double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts
                 - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2);
         double idelta= delta*ist->st->codec->sample_rate / enc->sample_rate;
         int byte_delta= ((int)idelta)*2*ist->st->codec->channels;
 
+        if (verbose > 3)
+            fprintf(stderr, "adelta:%f ost->sync_opts:%lld, ost->sync_ipts:%f, size:%d, stream:#%d.%d\n",
+                    delta, ost->sync_opts, get_sync_ipts(ost), size, ist->file_index, ist->index);
+
         //FIXME resample delay
         if(fabs(delta) > 50){
             if(ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate){
@@ -657,13 +781,14 @@
     }else
         ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
                         - av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2); //FIXME wrong
+    }
 
     if (ost->audio_resample) {
         buftmp = audio_buf;
         size_out = audio_resample(ost->resample,
                                   (short *)buftmp, (short *)buf,
                                   size / (ist->st->codec->channels * isize));
-        size_out = size_out * enc->channels * osize;
+        size_out = size_out * out_channels * osize;
     } else {
         buftmp = buf;
         size_out = size;
@@ -685,6 +810,28 @@
         size_out = len*osize;
     }
 
+    if (ost->nb_audio_channel_maps > 0) {
+        int j;
+        for (j = 0; j < ost->nb_audio_channel_maps; j++) {
+            if (ost->audio_channel_maps[j]->file_index == ist->file_index &&
+                ost->audio_channel_maps[j]->stream_index == ist->index) {
+                if (audiomerge_add_channel(&ost->audiomerge, buftmp,
+                                           ost->audio_channel_maps[j]->channel_index,
+                                           ost->audio_channel_maps[j]->out_channel_index,
+                                           dec->channels,
+                                           size_out/(osize*dec->channels)) < 0) {
+                    fprintf(stderr, "audiomerge failed\n");
+                    av_exit(1);
+                }
+            }
+        }
+
+        buftmp = ost->audiomerge.buf;
+        size_out = audiomerge_complete_size(&ost->audiomerge);
+        if (!size_out)
+            return; // no complete frame
+    }
+
     /* now encode as many frames as possible */
     if (enc->frame_size > 1) {
         /* output resampled raw samples */
@@ -750,6 +897,9 @@
         pkt.flags |= PKT_FLAG_KEY;
         write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
     }
+
+    if (ost->nb_audio_channel_maps > 0)
+        audiomerge_drain_complete_size(&ost->audiomerge);
 }
 
 static void pre_process_video_frame(AVInputStream *ist, AVPicture *picture, void **bufp)
@@ -883,31 +1033,33 @@
 
     *frame_size = 0;
 
+    if(!isnan(get_sync_ipts(ost))) {
     if(video_sync_method>0 || (video_sync_method && av_q2d(enc->time_base) > 0.001)){
         double vdelta;
         vdelta = get_sync_ipts(ost) / av_q2d(enc->time_base) - ost->sync_opts;
-        //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
-        if (vdelta < -1.1)
+        if (vdelta<=-0.6)
             nb_frames = 0;
-        else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){
+        else if (video_sync_method == 2){
             if(vdelta<=-0.6){
                 nb_frames=0;
             }else if(vdelta>0.6)
-            ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
-        }else if (vdelta > 1.1)
-            nb_frames = lrintf(vdelta);
-//fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n", vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames);
+                ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
+        }else if (vdelta>0.6)
+            nb_frames += lrintf(vdelta);
+        if (verbose>3)
+            fprintf(stderr, "vdelta:%f, ost->sync_opts:%"PRId64", ost->sync_ipts:%f nb_frames:%d\n",
+                    vdelta, ost->sync_opts, get_sync_ipts(ost), nb_frames);
         if (nb_frames == 0){
             ++nb_frames_drop;
-            if (verbose>2)
+            if (verbose>0)
                 fprintf(stderr, "*** drop!\n");
         }else if (nb_frames > 1) {
-            nb_frames_dup += nb_frames;
-            if (verbose>2)
+            nb_frames_dup += nb_frames-1;
+            if (verbose>0)
                 fprintf(stderr, "*** %d dup!\n", nb_frames-1);
         }
-    }else
-        ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
+    }
+    }
 
     nb_frames= FFMIN(nb_frames, max_frames[CODEC_TYPE_VIDEO] - ost->frame_number);
     if (nb_frames <= 0)
@@ -1218,7 +1370,7 @@
             "size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
             (double)total_size / 1024, ti1, bitrate);
 
-        if (verbose > 1)
+        if (nb_frames_dup || nb_frames_drop)
           snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
                   nb_frames_dup, nb_frames_drop);
 
@@ -1247,7 +1399,7 @@
 {
     AVFormatContext *os;
     AVOutputStream *ost;
-    int ret, i;
+    int ret, i, j;
     uint8_t *data_buf;
     int data_size, got_picture;
     AVFrame picture;
@@ -1258,9 +1410,6 @@
     AVPacket avpkt;
     int bps = av_get_bits_per_sample_format(ist->st->codec->sample_fmt)>>3;
 
-    if(ist->next_pts == AV_NOPTS_VALUE)
-        ist->next_pts= ist->pts;
-
     if (pkt == NULL) {
         /* EOF handling */
         av_init_packet(&avpkt);
@@ -1271,18 +1420,19 @@
         avpkt = *pkt;
     }
 
+    ist->last_dts = ist->dts;
+
     if(pkt->dts != AV_NOPTS_VALUE)
-        ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
+        ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
+    else
+        ist->dts = AV_NOPTS_VALUE;
 
     //while we have more to decode or while the decoder did output something on EOF
-    while (avpkt.size > 0 || (!pkt && ist->next_pts != ist->pts)) {
+    while (avpkt.size > 0 || !pkt) {
     handle_eof:
-        ist->pts= ist->next_pts;
-
         if(avpkt.size && avpkt.size != pkt->size &&
            !(ist->st->codec->codec->capabilities & CODEC_CAP_SUBFRAMES) && verbose>0)
             fprintf(stderr, "Multiple frames in a packet from stream %d\n", pkt->stream_index);
-
         /* decode the packet if needed */
         data_buf = NULL; /* fail safe */
         data_size = 0;
@@ -1306,19 +1456,44 @@
                 avpkt.size -= ret;
                 /* Some bug in mpeg audio decoder gives */
                 /* data_size < 0, it seems they are overflows */
-                if (data_size <= 0) {
+                /* let's try to catch it by failing if it still happens */
+                if (data_size < 0)
+                    goto fail_decode;
+                if (!data_size) {
                     /* no audio frame */
-                    continue;
+                    if (avpkt.size > 0)
+                        continue;
+                    else
+                        goto discard_packet;
                 }
                 data_buf = (uint8_t *)samples;
-                ist->next_pts += ((int64_t)AV_TIME_BASE/bps * data_size) /
-                    (ist->st->codec->sample_rate * ist->st->codec->channels);
+
+                if (pkt && pkt->pts != AV_NOPTS_VALUE)
+                    ist->pts = av_rescale_q(pkt->pts, ist->st->time_base,
+                                            AV_TIME_BASE_Q);
+                else
+                    ist->pts = ist->dts;
+                if (ist->pts == AV_NOPTS_VALUE)
+                    ist->pts = ist->next_pts;
+                ist->next_pts = ist->pts;
+
+                if (ist->next_pts != AV_NOPTS_VALUE) {
+                    ist->next_pts += ((int64_t)AV_TIME_BASE/bps * data_size) /
+                        (ist->st->codec->sample_rate * ist->st->codec->channels);
+                }
                 break;}
             case CODEC_TYPE_VIDEO:
                     data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
                     /* XXX: allocate picture correctly */
                     avcodec_get_frame_defaults(&picture);
 
+                    if (pkt && pkt->pts != AV_NOPTS_VALUE && !ist->broken_pts) {
+                        ist->st->codec->reordered_opaque =
+                            av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
+                        ist->has_pts = 1;
+                    } else
+                        ist->st->codec->reordered_opaque = AV_NOPTS_VALUE;
+
                     ret = avcodec_decode_video2(ist->st->codec,
                                                 &picture, &got_picture, &avpkt);
                     ist->st->quality= picture.quality;
@@ -1328,10 +1503,50 @@
                         /* no picture yet */
                         goto discard_packet;
                     }
+
+                    /* check for broken youtube flv having pts == dts */
+                    if (!ist->broken_pts &&
+                        picture.reordered_opaque != AV_NOPTS_VALUE &&
+                        pkt && pkt->pts == pkt->dts &&
+                        picture.reordered_opaque < ist->pts) {
+                        ist->broken_pts = 1;
+                        ist->has_pts = 0;
+                        fprintf(stderr, "stream #%d.%d broken pts, pts:%lld < last:%lld\n",
+                                ist->file_index, ist->index, picture.reordered_opaque, ist->pts);
+                    }
+
+                    if (ist->broken_pts) {
+                        ist->pts = AV_NOPTS_VALUE;
+                    } else {
+                        if (picture.reordered_opaque != AV_NOPTS_VALUE) {
+                            if (!ist->pts && !picture.reordered_opaque) {
+                                fprintf(stderr,
+                                        "stream #%d.%d decoder does not set reordered opaque\n",
+                                        ist->file_index, ist->index);
+                                ist->broken_pts = 1; // decoder does not set reordered opaque
+                            }
+                        }
+                        ist->pts = picture.reordered_opaque;
+                    }
+
+                    /* it is preferable to use dts for avi since next pts computation
+                       might slightly diverge for real timestamp */
+                    if (!ist->has_pts || ist->broken_pts) {
+                        if (ist->st->codec->has_b_frames)
+                            ist->pts = ist->last_dts;
+                        else
+                            ist->pts = ist->dts;
+                    }
+                    /* unset last dts to avoid using dts twice */
+                    ist->last_dts = AV_NOPTS_VALUE;
+                    if (ist->pts == AV_NOPTS_VALUE)
+                        ist->pts = ist->next_pts;
+                    ist->next_pts = ist->pts;
+
                     if (ist->st->codec->time_base.num != 0) {
                         int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
                         ist->next_pts += ((int64_t)AV_TIME_BASE *
-                                          ist->st->codec->time_base.num * ticks) /
+                                     ist->st->codec->time_base.num * ticks) /
                             ist->st->codec->time_base.den;
                     }
                     avpkt.size = 0;
@@ -1353,14 +1568,29 @@
         } else {
             switch(ist->st->codec->codec_type) {
             case CODEC_TYPE_AUDIO:
-                ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
-                    ist->st->codec->sample_rate;
+                /* assuming pts == dts for audio */
+                if (pkt->pts != AV_NOPTS_VALUE)
+                    ist->dts = av_rescale_q(pkt->pts, ist->st->time_base,
+                                            AV_TIME_BASE_Q);
+                if (ist->dts == AV_NOPTS_VALUE)
+                    ist->dts = ist->next_pts;
+                ist->pts = ist->dts;
+                ist->next_pts = ist->dts;
+
+                if (ist->next_pts != AV_NOPTS_VALUE) {
+                    ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
+                        ist->st->codec->sample_rate;
+                }
                 break;
             case CODEC_TYPE_VIDEO:
-                if (ist->st->codec->time_base.num != 0) {
+                if (ist->dts == AV_NOPTS_VALUE)
+                    ist->dts = ist->next_dts;
+                ist->next_dts = ist->dts;
+                if (ist->st->codec->time_base.num != 0 &&
+                    ist->next_dts != AV_NOPTS_VALUE) {
                     int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
-                    ist->next_pts += ((int64_t)AV_TIME_BASE *
-                                      ist->st->codec->time_base.num * ticks) /
+                    ist->next_dts += ((int64_t)AV_TIME_BASE *
+                                 ist->st->codec->time_base.num * ticks) /
                         ist->st->codec->time_base.den;
                 }
                 break;
@@ -1406,7 +1636,12 @@
                 int frame_size;
 
                 ost = ost_table[i];
-                if (ost->source_index == ist_index) {
+                for(j=0;j<ost->nb_source_indexes;j++) {
+                    if (ost->source_index[j] == ist_index)
+                        break;
+                }
+
+                if (j < ost->nb_source_indexes) {
                     os = output_files[ost->file_index];
 
                     /* set the input output pts pairs */
@@ -1433,11 +1668,36 @@
                         AVFrame avframe; //FIXME/XXX remove this
                         AVPacket opkt;
                         int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base);
+                        int got_key = 1;
 
                         av_init_packet(&opkt);
 
-                        if ((!ost->frame_number && !(pkt->flags & PKT_FLAG_KEY)) && !copy_initial_nonkeyframes)
+                        if (!ost->frame_number && !copy_initial_nonkeyframes) {
+                            if (seek_requested) {
+                                /* if seek was requested we wait until all streams get a keyframe,
+                                   because not all demuxers seeks on keyframes */
+                                if (pkt->flags & PKT_FLAG_KEY)
+                                    ost->got_key = 1;
+                                for (j = 0; j < nb_ostreams; j++) {
+                                    if (ost_table[j]->file_index == ost->file_index &&
+                                        !ost_table[j]->encoding_needed &&
+                                        ost_table[j]->st->codec->codec_type == CODEC_TYPE_VIDEO &&
+                                        !ost_table[j]->got_key) {
+                                        got_key = 0;
+                                        break;
+                                    }
+                                }
+                            } else if (pkt->flags & PKT_FLAG_KEY) {
+                                got_key = 1;
+                            }
+                        }
+
+                        if (!ost->frame_number && !copy_initial_nonkeyframes && !got_key) {
+                            if (verbose > 0)
+                                fprintf(stderr, "copy in stream %d dropping frame %d\n",
+                                        ost->index, ost->frame_number);
                             continue;
+                        }
 
                         /* no reencoding needed : output the packet directly */
                         /* force the input stream PTS */
@@ -1453,17 +1713,32 @@
                             ost->sync_opts++;
                         }
 
+                        if (verbose > 3) {
+                            fprintf(stderr, "copy in stream %d pts %lld dts %lld "
+                                    "duration %d start time %lld delay %d\n",
+                                    ost->index, pkt->pts, pkt->dts, pkt->duration,
+                                    ost_tb_start_time, ost->st->codec->has_b_frames);
+                        }
+
                         opkt.stream_index= ost->index;
                         if(pkt->pts != AV_NOPTS_VALUE)
                             opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
                         else
                             opkt.pts= AV_NOPTS_VALUE;
 
-                        if (pkt->dts == AV_NOPTS_VALUE)
-                            opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
-                        else
+                        if (pkt->dts != AV_NOPTS_VALUE)
                             opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
-                        opkt.dts -= ost_tb_start_time;
+                        else
+                            opkt.dts = AV_NOPTS_VALUE;
+
+                        if (opkt.pts == AV_NOPTS_VALUE && opkt.dts == AV_NOPTS_VALUE &&
+                            ist->dts != AV_NOPTS_VALUE) {
+                            opkt.dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ost->st->time_base);
+                            fprintf(stderr, "copy in dts %lld ist dts %lld\n", opkt.dts, ist->dts);
+                        }
+
+                        if (opkt.dts != AV_NOPTS_VALUE)
+                            opkt.dts-= ost_tb_start_time;
 
                         opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
                         opkt.flags= pkt->flags;
@@ -1505,7 +1780,13 @@
 
         for(i=0;i<nb_ostreams;i++) {
             ost = ost_table[i];
-            if (ost->source_index == ist_index) {
+
+            for(j=0;j<ost->nb_source_indexes;j++) {
+                if (ost->source_index[j] == ist_index)
+                    break;
+            }
+
+            if (j < ost->nb_source_indexes) {
                 AVCodecContext *enc= ost->st->codec;
                 os = output_files[ost->file_index];
 
@@ -1722,6 +2003,30 @@
         }
     }
 
+    /* Sanity check audio channel mapping */
+    for(i=0;i<nb_audio_channel_maps;i++) {
+        int fi = audio_channel_maps[i].file_index;
+        int si = audio_channel_maps[i].stream_index;
+        int ci = audio_channel_maps[i].channel_index;
+        int fo = audio_channel_maps[i].out_file_index;
+        int so = audio_channel_maps[i].out_stream_index;
+
+        if (fi < 0 || fi > nb_input_files - 1 ||
+            si < 0 || si > file_table[fi].nb_streams - 1) {
+            fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si);
+            exit(1);
+        }
+        if (ci < 0 || ci >= input_files[fi]->streams[si]->codec->channels) {
+            fprintf(stderr,"Could not find audio channel #%d.%d:%d\n", fi, si, ci);
+            exit(1);
+        }
+        if (fo < 0 || fo > nb_output_files - 1 ||
+            so < 0 || so > output_files[fo]->nb_streams - 1) {
+            fprintf(stderr,"Could not find output stream #%d.%d\n", fo, so);
+            exit(1);
+        }
+    }
+
     ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams);
     if (!ost_table)
         goto fail;
@@ -1741,12 +2046,14 @@
             ost->file_index = k;
             ost->index = i;
             ost->st = os->streams[i];
+            ist = NULL;
             if (nb_stream_maps > 0) {
-                ost->source_index = file_table[stream_maps[n].file_index].ist_index +
+                ost->source_index[0] = file_table[stream_maps[n].file_index].ist_index +
                     stream_maps[n].stream_index;
+                ost->nb_source_indexes = 1;
 
                 /* Sanity check that the stream types match */
-                if (ist_table[ost->source_index]->st->codec->codec_type != ost->st->codec->codec_type) {
+                if (ist_table[ost->source_index[0]]->st->codec->codec_type != ost->st->codec->codec_type) {
                     int i= ost->file_index;
                     dump_format(output_files[i], i, output_files[i]->filename, 1);
                     fprintf(stderr, "Codec type mismatch for mapping #%d.%d -> #%d.%d\n",
@@ -1754,13 +2061,35 @@
                         ost->file_index, ost->index);
                     av_exit(1);
                 }
-
+            } else if (ost->st->codec->codec_type == CODEC_TYPE_AUDIO && nb_audio_channel_maps > 0) {
+                for(j=0;j<nb_audio_channel_maps;j++) {
+                    AVAudioChannelMap *m = &audio_channel_maps[j];
+                    if (ost->file_index == m->out_file_index &&
+                        ost->index == m->out_stream_index) {
+                        ost->source_index[ost->nb_source_indexes++] =
+                            file_table[m->file_index].ist_index + m->stream_index;
+                        ost->audio_channel_maps[ost->nb_audio_channel_maps++] = m;
+                        if (m->out_channel_index == -1)
+                            m->out_channel_index = ost->audiomerge.out_channels;
+                        ost->audiomerge.out_channels++;
+                    }
+                }
+                /* Sanity check out audio channel number */
+                for(j=0;j<ost->nb_audio_channel_maps;j++) {
+                    AVAudioChannelMap *m = ost->audio_channel_maps[j];
+                    if (m->out_channel_index >= ost->audiomerge.out_channels) {
+                        fprintf(stderr, "Channel number %d does not exist: channels %d\n",
+                                m->out_channel_index, ost->audiomerge.out_channels);
+                        av_exit(1);
+                    }
+                }
             } else {
                 if(opt_programid) {
                     found = 0;
                     j = stream_index_from_inputs(input_files, nb_input_files, file_table, ist_table, ost->st->codec->codec_type, opt_programid);
                     if(j != -1) {
-                        ost->source_index = j;
+                        ost->source_index[0] = j;
+                        ost->nb_source_indexes = 1;
                         found = 1;
                     }
                 } else {
@@ -1770,7 +2099,8 @@
                         ist = ist_table[j];
                         if (ist->discard &&
                             ist->st->codec->codec_type == ost->st->codec->codec_type) {
-                            ost->source_index = j;
+                            ost->source_index[0] = j;
+                            ost->nb_source_indexes = 1;
                             found = 1;
                             break;
                         }
@@ -1783,7 +2113,8 @@
                         for(j=0;j<nb_istreams;j++) {
                             ist = ist_table[j];
                             if (ist->st->codec->codec_type == ost->st->codec->codec_type) {
-                                ost->source_index = j;
+                                ost->source_index[0] = j;
+                                ost->nb_source_indexes = 1;
                                 found = 1;
                             }
                         }
@@ -1797,11 +2128,18 @@
                     }
                 }
             }
-            ist = ist_table[ost->source_index];
-            ist->discard = 0;
+            for(j=0;j<ost->nb_source_indexes;j++) {
+                ist = ist_table[ost->source_index[j]];
+                ist->discard = 0;
+            }
+            if (!ist) {
+                fprintf(stderr, "Could not find input stream matching output stream #%d.%d\n",
+                        ost->file_index, ost->index);
+                av_exit(1);
+            }
             ost->sync_ist = (nb_stream_maps > 0) ?
                 ist_table[file_table[stream_maps[n].sync_file_index].ist_index +
-                         stream_maps[n].sync_stream_index] : ist;
+                          stream_maps[n].sync_stream_index] : ist_table[ost->source_index[0]];
         }
     }
 
@@ -1810,20 +2148,24 @@
         AVMetadataTag *lang;
         ost = ost_table[i];
         os = output_files[ost->file_index];
-        ist = ist_table[ost->source_index];
+        ist = ist_table[ost->source_index[0]];
 
         codec = ost->st->codec;
         icodec = ist->st->codec;
 
-        if ((lang=av_metadata_get(ist->st->metadata, "language", NULL, 0))
-            &&   !av_metadata_get(ost->st->metadata, "language", NULL, 0))
-            av_metadata_set(&ost->st->metadata, "language", lang->value);
+        if ((lang=av_metadata_get(ist->st->metadata, "language", 0))
+            &&   !av_metadata_get(ost->st->metadata, "language", 0))
+            av_metadata_set_string(&ost->st->metadata,
+                                   "language", lang->value, 0);
 
         ost->st->disposition = ist->st->disposition;
         codec->bits_per_raw_sample= icodec->bits_per_raw_sample;
         codec->chroma_sample_location = icodec->chroma_sample_location;
 
         if (ost->st->stream_copy) {
+            /* generate dts and pts for source file */
+            input_files[ist->file_index]->flags |= AVFMT_FLAG_GENPTS;
+
             /* if stream_copy is selected, no need to decode or encode */
             codec->codec_id = icodec->codec_id;
             codec->codec_type = icodec->codec_type;
@@ -1841,6 +2183,8 @@
             if(av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000){
                 codec->time_base = icodec->time_base;
                 codec->time_base.num *= icodec->ticks_per_frame;
+                av_reduce(&codec->time_base.num, &codec->time_base.den,
+                          codec->time_base.num, codec->time_base.den, INT_MAX);
             }else
                 codec->time_base = ist->st->time_base;
             switch(codec->codec_type) {
@@ -1852,6 +2196,7 @@
                 codec->channel_layout = icodec->channel_layout;
                 codec->sample_rate = icodec->sample_rate;
                 codec->channels = icodec->channels;
+                codec->sample_fmt = icodec->sample_fmt;
                 codec->frame_size = icodec->frame_size;
                 codec->block_align= icodec->block_align;
                 if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3)
@@ -1881,8 +2226,17 @@
                 ost->reformat_pair = MAKE_SFMT_PAIR(SAMPLE_FMT_NONE,SAMPLE_FMT_NONE);
                 ost->audio_resample = codec->sample_rate != icodec->sample_rate || audio_sync_method > 1;
                 icodec->request_channels = codec->channels;
-                ist->decoding_needed = 1;
+                for (j = 0; j < ost->nb_source_indexes; j++) {
+                    ist = ist_table[ost->source_index[j]];
+                    ist->decoding_needed = 1;
+                }
                 ost->encoding_needed = 1;
+                if (ost->audiomerge.out_channels > 0) {
+                    codec->channels = ost->audiomerge.out_channels; // update channels to merged channels
+                    audiomerge_init(&ost->audiomerge, ost->audiomerge.out_channels,
+                                    av_get_bits_per_sample_format(ost->st->codec->sample_fmt)/8,
+                                    48000); // one sec at 48khz
+                }
                 break;
             case CODEC_TYPE_VIDEO:
                 if (ost->st->codec->pix_fmt == PIX_FMT_NONE) {
@@ -2022,13 +2376,13 @@
                 snprintf(error, sizeof(error), "Encoder (codec id %d) not found for output stream #%d.%d",
                          ost->st->codec->codec_id, ost->file_index, ost->index);
                 ret = AVERROR(EINVAL);
-                goto dump_format;
+                goto fail;
             }
             if (avcodec_open(ost->st->codec, codec) < 0) {
                 snprintf(error, sizeof(error), "Error while opening encoder for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height",
                         ost->file_index, ost->index);
                 ret = AVERROR(EINVAL);
-                goto dump_format;
+                goto fail;
             }
             extra_size += ost->st->codec->extradata_size;
         }
@@ -2045,13 +2399,13 @@
                 snprintf(error, sizeof(error), "Decoder (codec id %d) not found for input stream #%d.%d",
                         ist->st->codec->codec_id, ist->file_index, ist->index);
                 ret = AVERROR(EINVAL);
-                goto dump_format;
+                goto fail;
             }
             if (avcodec_open(ist->st->codec, codec) < 0) {
                 snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d",
                         ist->file_index, ist->index);
                 ret = AVERROR(EINVAL);
-                goto dump_format;
+                goto fail;
             }
             //if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO)
             //    ist->st->codec->flags |= CODEC_FLAG_REPEAT_FIELD;
@@ -2061,8 +2415,8 @@
     /* init pts */
     for(i=0;i<nb_istreams;i++) {
         ist = ist_table[i];
-        ist->pts = 0;
-        ist->next_pts = AV_NOPTS_VALUE;
+        ist->dts = AV_NOPTS_VALUE;
+        ist->pts = AV_NOPTS_VALUE;
         ist->is_start = 1;
     }
 
@@ -2070,7 +2424,6 @@
     for (i=0;i<nb_meta_data_maps;i++) {
         AVFormatContext *out_file;
         AVFormatContext *in_file;
-        AVMetadataTag *mtag;
 
         int out_file_index = meta_data_maps[i].out_file;
         int in_file_index = meta_data_maps[i].in_file;
@@ -2078,24 +2431,21 @@
             snprintf(error, sizeof(error), "Invalid output file index %d map_meta_data(%d,%d)",
                      out_file_index, out_file_index, in_file_index);
             ret = AVERROR(EINVAL);
-            goto dump_format;
+            goto fail;
         }
         if (in_file_index < 0 || in_file_index >= nb_input_files) {
             snprintf(error, sizeof(error), "Invalid input file index %d map_meta_data(%d,%d)",
                      in_file_index, out_file_index, in_file_index);
             ret = AVERROR(EINVAL);
-            goto dump_format;
+            goto fail;
         }
 
         out_file = output_files[out_file_index];
         in_file = input_files[in_file_index];
 
-
-        mtag=NULL;
-        while((mtag=av_metadata_get(in_file->metadata, "", mtag, AV_METADATA_IGNORE_SUFFIX)))
-            av_metadata_set(&out_file->metadata, mtag->key, mtag->value);
-        av_metadata_conv(out_file, out_file->oformat->metadata_conv,
-                                    in_file->iformat->metadata_conv);
+        av_metadata_conv_generic(&out_file->metadata, in_file->metadata,
+                                 out_file->oformat->metadata_conv,
+                                 in_file->iformat->metadata_conv);
     }
 
     /* open files and write file headers */
@@ -2104,14 +2454,13 @@
         if (av_write_header(os) < 0) {
             snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
             ret = AVERROR(EINVAL);
-            goto dump_format;
+            goto fail;
         }
         if (strcmp(output_files[i]->oformat->name, "rtp")) {
             want_sdp = 0;
         }
     }
 
- dump_format:
     /* dump the file output parameters - cannot be done before in case
        of stream copy */
     for(i=0;i<nb_output_files;i++) {
@@ -2123,16 +2472,23 @@
         fprintf(stderr, "Stream mapping:\n");
         for(i=0;i<nb_ostreams;i++) {
             ost = ost_table[i];
+            for(j=0;j<ost->nb_source_indexes;j++) {
             fprintf(stderr, "  Stream #%d.%d -> #%d.%d",
-                    ist_table[ost->source_index]->file_index,
-                    ist_table[ost->source_index]->index,
+                    ist_table[ost->source_index[j]]->file_index,
+                    ist_table[ost->source_index[j]]->index,
                     ost->file_index,
                     ost->index);
-            if (ost->sync_ist != ist_table[ost->source_index])
+            if (ost->nb_audio_channel_maps > 0) {
+                fprintf(stderr, " [channel: %d -> %d]",
+                        ost->audio_channel_maps[j]->channel_index,
+                        ost->audio_channel_maps[j]->out_channel_index);
+            }
+            if (ost->sync_ist != ist_table[ost->source_index[0]])
                 fprintf(stderr, " [sync #%d.%d]",
                         ost->sync_ist->file_index,
                         ost->sync_ist->index);
             fprintf(stderr, "\n");
+            }
         }
     }
 
@@ -2179,9 +2535,10 @@
             double ipts, opts;
             ost = ost_table[i];
             os = output_files[ost->file_index];
-            ist = ist_table[ost->source_index];
+            for(j=0;j<ost->nb_source_indexes;j++) {
+            ist = ist_table[ost->source_index[j]];
             if(no_packet[ist->file_index])
-                continue;
+                break;
             if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO)
                 opts = ost->sync_opts * av_q2d(ost->st->codec->time_base);
             else
@@ -2190,20 +2547,23 @@
             if (!file_table[ist->file_index].eof_reached){
                 if(ipts < ipts_min) {
                     ipts_min = ipts;
-                    if(input_sync ) file_index = ist->file_index;
+                    if(input_sync || ost->nb_source_indexes > 1) file_index = ist->file_index;
                 }
                 if(opts < opts_min) {
                     opts_min = opts;
                     if(!input_sync) file_index = ist->file_index;
                 }
             }
+
             if(ost->frame_number >= max_frames[ost->st->codec->codec_type]){
                 file_index= -1;
-                break;
+                goto out;
+            }
             }
         }
         /* if none, if is finished */
         if (file_index < 0) {
+        out:
             if(no_packet_count){
                 no_packet_count=0;
                 memset(no_packet, 0, sizeof(no_packet));
@@ -2264,12 +2624,13 @@
                 pkt.dts *= input_files_ts_scale[file_index][pkt.stream_index];
         }
 
-//        fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type);
-        if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE
+        //fprintf(stderr, "st:%d ist:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", pkt.stream_index,
+        //        ist->dts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type);
+        if (pkt.dts != AV_NOPTS_VALUE && ist->dts != AV_NOPTS_VALUE
             && (is->iformat->flags & AVFMT_TS_DISCONT)) {
             int64_t pkt_dts= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
-            int64_t delta= pkt_dts - ist->next_pts;
-            if((FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE || pkt_dts+1<ist->pts)&& !copy_ts){
+            int64_t delta= pkt_dts - ist->dts;
+            if (FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE && !copy_ts) {
                 input_files_ts_offset[ist->file_index]-= delta;
                 if (verbose > 2)
                     fprintf(stderr, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, input_files_ts_offset[ist->file_index]);
@@ -2359,6 +2720,7 @@
                 av_fifo_free(ost->fifo); /* works even if fifo is not
                                              initialized but set to zero */
                 av_free(ost->pict_tmp.data[0]);
+                av_free(ost->audiomerge.buf);
                 if (ost->video_resample)
                     sws_freeContext(ost->img_resample_ctx);
                 if (ost->resample)
@@ -2721,6 +3083,46 @@
         subtitle_codec_tag= arg[0] + (arg[1]<<8) + (arg[2]<<16) + (arg[3]<<24);
 }
 
+static void opt_map_audio_channel(const char *arg)
+{
+    AVAudioChannelMap *m;
+    char *p;
+
+    if (nb_audio_channel_maps == MAX_AUDIO_CHANNEL_MAPS) {
+        fprintf(stderr, "Only %d channels mappings are supported\n", MAX_AUDIO_CHANNEL_MAPS);
+        exit(1);
+    }
+
+    m = &audio_channel_maps[nb_audio_channel_maps++];
+
+    m->file_index = strtol(arg, &p, 0);
+    if (*p) p++;
+    else goto syntax_error;
+
+    m->stream_index = strtol(p, &p, 0);
+    if (*p) {
+        p++;
+        m->channel_index = strtol(p, &p, 0);
+        if (*p) {
+            p++;
+            m->out_file_index = strtol(p, &p, 0);
+            if (*p) p++;
+            else goto syntax_error;
+            m->out_stream_index = strtol(p, &p, 0);
+            if (*p) {
+                p++;
+                m->out_channel_index = strtol(p, &p, 0);
+            } else
+                m->out_channel_index = -1;
+        } else
+            goto syntax_error;
+    } else {
+    syntax_error:
+        fprintf(stderr, "Syntax error, usage: file:stream:channel:outfile:stream[:outchannel]\n");
+        exit(1);
+    }
+}
+
 static void opt_map(const char *arg)
 {
     AVStreamMap *m;
@@ -2800,6 +3202,42 @@
     return 0;
 }
 
+static void opt_timecode(const char *arg)
+{
+    int hours, minutes, seconds, frames, time_code, fps, drop = 0;
+    char *p;
+    char buf[16];
+
+    hours   = strtol(arg,   &p, 10);
+    if (*p != ':') goto syntax_error;
+    minutes = strtol(p + 1, &p, 10);
+    if (*p != ':') goto syntax_error;
+    seconds = strtol(p + 1, &p, 10);
+    if (*p == ';')
+        drop = 1;
+    else if (*p != ':')
+        goto syntax_error;
+    frames  = strtol(p + 1, &p, 10);
+
+    fps = (frame_rate.num + frame_rate.den / 2) / frame_rate.den;
+    time_code = (hours * 3600 + minutes * 60 + seconds) * fps + frames;
+    if (drop) { /* adjust */
+        int tminutes = 60 * hours + minutes;
+        if (fps != 30) {
+            fprintf(stderr, "Drop frame timecode only supported with 29.97 fps\n");
+            exit(1);
+        }
+        time_code -= 2 * (tminutes - tminutes / 10);
+        opt_default("flags2", "+drop_frame_timecode");
+    }
+    snprintf(buf, 16, "%d", time_code);
+    opt_default("timecode_frame_start", buf);
+    return;
+ syntax_error:
+    fprintf(stderr, "Syntax error, usage: hours:minutes:seconds[:;]frames\n");
+    exit(1);
+}
+
 static enum CodecID find_codec_or_die(const char *name, int type, int encoder)
 {
     const char *codec_string = encoder ? "encoder" : "decoder";
@@ -2821,12 +3259,24 @@
     return codec->id;
 }
 
+static const AVRational frame_rate_tab[] = {
+    {24000, 1001},
+    {   24,    1},
+    {   25,    1},
+    {30000, 1001},
+    {   30,    1},
+    {   50,    1},
+    {60000, 1001},
+    {   60,    1},
+    {    0,    0},
+};
+
 static void opt_input_file(const char *filename)
 {
     AVFormatContext *ic;
     AVFormatParameters params, *ap = ¶ms;
     AVInputFormat *file_iformat = NULL;
-    int err, i, ret, rfps, rfps_base;
+    int err, i, ret;
     int64_t timestamp;
 
     if (last_asked_format) {
@@ -2908,11 +3358,13 @@
         }
         /* reset seek info */
         start_time = 0;
+        seek_requested = 1;
     }
 
     /* update the current parameters so that they match the one of the input stream */
@@ -2926,50 +3378,53 @@
                 frame_aspect_ratio = enc->sample_aspect_ratio;
             frame_aspect_ratio = av_mul_q(frame_aspect_ratio, (AVRational){ enc->width, enc->height });
             frame_pix_fmt = enc->pix_fmt;
-            rfps      = ic->streams[i]->r_frame_rate.num;
-            rfps_base = ic->streams[i]->r_frame_rate.den;
+
             if(enc->lowres) enc->flags |= CODEC_FLAG_EMU_EDGE;
             if(me_threshold)
                 enc->debug |= FF_DEBUG_MV;
 
-            if (enc->time_base.den != rfps || enc->time_base.num != rfps_base) {
-
-                if (verbose >= 0)
-                    fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n",
-                            i, (float)enc->time_base.den / enc->time_base.num, enc->time_base.den, enc->time_base.num,
-
-                    (float)rfps / rfps_base, rfps, rfps_base);
+            if (enc->time_base.num &&
+                enc->time_base.den <= 120L*enc->time_base.num &&
+                enc->time_base.den >= 5L*enc->time_base.num) {
+                frame_rate.num = enc->time_base.den;
+                frame_rate.den = enc->time_base.num*enc->ticks_per_frame;
+            } else {
+                /* update the current frame rate to match the stream frame rate */
+                frame_rate = st->r_frame_rate;
+                if (!frame_rate.num && st->time_base.num &&
+                    st->time_base.den <= 60L*st->time_base.num &&
+                    st->time_base.den >= 5L*st->time_base.num) {
+                    frame_rate.num = st->time_base.den;
+                    frame_rate.den = st->time_base.num;
+                }
             }
-            /* update the current frame rate to match the stream frame rate */
-            frame_rate.num = rfps;
-            frame_rate.den = rfps_base;
+            //fprintf(stderr, "frame rate %d/%d\n", frame_rate.num, frame_rate.den);
 
             input_codecs[nb_icodecs++] = avcodec_find_decoder_by_name(video_codec_name);
             if(video_disable)
@@ -3243,11 +3712,10 @@
     nb_ocodecs++;
     audio_enc->sample_rate = audio_sample_rate;
     audio_enc->time_base= (AVRational){1, audio_sample_rate};
-    if (audio_language) {
-        av_metadata_set(&st->metadata, "language", audio_language);
-        av_free(audio_language);
-        audio_language = NULL;
-    }
+
+    av_metadata_set_string(&st->metadata, "language",
+                           audio_language, AV_METADATA_NONCONST_VALUE);
+    audio_language = NULL;
 
     /* reset some key parameters */
     audio_disable = 0;
@@ -3285,11 +3753,9 @@
     }
     nb_ocodecs++;
 
-    if (subtitle_language) {
-        av_metadata_set(&st->metadata, "language", subtitle_language);
-        av_free(subtitle_language);
-        subtitle_language = NULL;
-    }
+    av_metadata_set_string(&st->metadata, "language",
+                           subtitle_language, AV_METADATA_NONCONST_VALUE);
+    subtitle_language = NULL;
 
     subtitle_disable = 0;
     av_freep(&subtitle_codec_name);
@@ -3418,10 +3884,14 @@
         oc->timestamp = rec_timestamp;
 
         for(; metadata_count>0; metadata_count--){
-            av_metadata_set(&oc->metadata, metadata[metadata_count-1].key,
-                                           metadata[metadata_count-1].value);
+            av_metadata_set_string(&oc->metadata,
+                                   metadata[metadata_count-1].key,
+                                   metadata[metadata_count-1].value,
+                                   AV_METADATA_NONCONST_KEY |
+                                   AV_METADATA_NONCONST_VALUE);
+            metadata[metadata_count-1].key = NULL;
+            metadata[metadata_count-1].value = NULL;
         }
-        av_metadata_conv(oc, oc->oformat->metadata_conv, NULL);
     }
 
     output_files[nb_output_files++] = oc;
@@ -3546,13 +4016,17 @@
     vfprintf(stdout, fmt, vl);
 }
 
+static void show_usage(void)
+{
+    printf("\n");
+    printf("Hyper fast Audio and Video encoder\n");
+    printf("usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...\n");
+}
+
 static void show_help(void)
 {
     av_log_set_callback(log_callback_help);
-    printf("usage: ffmpeg [[infile options] -i infile]... {[outfile options] outfile}...\n"
-           "Hyper fast Audio and Video encoder\n");
-    printf("\n");
-    show_help_options(options, "Main options:\n",
+    show_help_options(options, "\nMain options:\n",
                       OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB, 0);
     show_help_options(options, "\nAdvanced options:\n",
                       OPT_EXPERT | OPT_AUDIO | OPT_VIDEO | OPT_SUBTITLE | OPT_GRAB,
@@ -3581,6 +4055,7 @@
     av_opt_show(avformat_opts, NULL);
     printf("\n");
     av_opt_show(sws_opts, NULL);
+    show_usage();
 }
 
 static void opt_target(const char *arg)
@@ -3833,6 +4308,7 @@
     { "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
     { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
     { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
+    { "map_audio_channel", HAS_ARG | OPT_EXPERT, {(void*)opt_map_audio_channel}, "set audio channel extraction on stream", "file:stream:channel[:outfile:stream]" },
     { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
     { "t", OPT_FUNC2 | HAS_ARG, {(void*)opt_recording_time}, "record or transcode \"duration\" seconds of audio/video", "duration" },
     { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, //
@@ -3896,6 +4372,7 @@
     { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" },
     { "deinterlace", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_deinterlace},
       "deinterlace pictures" },
+    { "timecode", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_timecode}, "set timecode value", "timecode" },
     { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
     { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
     { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
@@ -3956,6 +4433,13 @@
     int i;
     int64_t ti;
 
+    show_banner();
+
+    if (argc == 1) {
+        show_usage();
+        exit(1);
+    }
+
     avcodec_register_all();
     avdevice_register_all();
     av_register_all();
@@ -3971,8 +4455,6 @@
     avformat_opts = avformat_alloc_context();
     sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
 
-    show_banner();
-
     /* parse options */
     parse_options(argc, argv, options, opt_output_file);
 
-------------- next part --------------
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/allcodecs.c ./allcodecs.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/allcodecs.c	2009-12-13 14:13:19.000000000 +0100
+++ ./allcodecs.c	2009-11-15 04:50:19.000000000 +0100
@@ -153,6 +153,7 @@
     REGISTER_ENCDEC  (RV20, rv20);
     REGISTER_DECODER (RV30, rv30);
     REGISTER_DECODER (RV40, rv40);
+    REGISTER_DECODER (S302M, s302m);
     REGISTER_ENCDEC  (SGI, sgi);
     REGISTER_DECODER (SMACKER, smacker);
     REGISTER_DECODER (SMC, smc);
@@ -255,7 +256,6 @@
     REGISTER_ENCDEC  (PCM_S16LE, pcm_s16le);
     REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar);
     REGISTER_ENCDEC  (PCM_S24BE, pcm_s24be);
-    REGISTER_ENCDEC  (PCM_S24DAUD, pcm_s24daud);
     REGISTER_ENCDEC  (PCM_S24LE, pcm_s24le);
     REGISTER_ENCDEC  (PCM_S32BE, pcm_s32be);
     REGISTER_ENCDEC  (PCM_S32LE, pcm_s32le);
@@ -353,6 +353,7 @@
     REGISTER_BSF     (DUMP_EXTRADATA, dump_extradata);
     REGISTER_BSF     (H264_MP4TOANNEXB, h264_mp4toannexb);
     REGISTER_BSF     (IMX_DUMP_HEADER, imx_dump_header);
+    REGISTER_BSF     (IMX_REMOVE_KLV, imx_remove_klv);
     REGISTER_BSF     (MJPEGA_DUMP_HEADER, mjpega_dump_header);
     REGISTER_BSF     (MP3_HEADER_COMPRESS, mp3_header_compress);
     REGISTER_BSF     (MP3_HEADER_DECOMPRESS, mp3_header_decompress);
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/alpha and ./alpha
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/arm and ./arm
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/avcodec.h ./avcodec.h
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/avcodec.h	2009-12-13 14:15:18.000000000 +0100
+++ ./avcodec.h	2009-11-15 04:50:19.000000000 +0100
@@ -217,7 +217,7 @@
     CODEC_ID_PCM_S24BE,
     CODEC_ID_PCM_U24LE,
     CODEC_ID_PCM_U24BE,
-    CODEC_ID_PCM_S24DAUD,
+    CODEC_ID_S302M,
     CODEC_ID_PCM_ZORK,
     CODEC_ID_PCM_S16LE_PLANAR,
     CODEC_ID_PCM_DVD,
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/cavsdec.c ./cavsdec.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/cavsdec.c	2009-12-13 14:13:19.000000000 +0100
+++ ./cavsdec.c	2009-11-15 04:50:19.000000000 +0100
@@ -634,7 +634,6 @@
     const uint8_t *buf_end;
     const uint8_t *buf_ptr;
     AVFrame *picture = data;
-    uint32_t stc = -1;
 
     s->avctx = avctx;
 
@@ -649,6 +648,7 @@
     buf_ptr = buf;
     buf_end = buf + buf_size;
     for(;;) {
+        uint32_t stc = -1;
         buf_ptr = ff_find_start_code(buf_ptr,buf_end, &stc);
         if(stc & 0xFFFFFE00)
             return FFMAX(0, buf_ptr - buf - s->parse_context.last_index);
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/dv.c ./dv.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/dv.c	2009-12-13 14:15:18.000000000 +0100
+++ ./dv.c	2009-11-15 04:50:19.000000000 +0100
@@ -44,6 +44,7 @@
 #include "put_bits.h"
 #include "simple_idct.h"
 #include "dvdata.h"
+#include "timecode.h"
 
 //#undef NDEBUG
 //#include <assert.h>
@@ -1181,6 +1182,7 @@
      *   2. It is not at all clear what STYPE is used for 4:2:0 PAL
      *      compression scheme (if any).
      */
+    int time_code;
     int apt   = (c->sys->pix_fmt == PIX_FMT_YUV420P ? 0 : 1);
 
     uint8_t aspect = 0;
@@ -1226,6 +1228,30 @@
                    0xc;       /* reserved -- always b1100 */
           buf[4] = 0xff;      /* reserved -- always 1 */
           break;
+    case dv_timecode:
+          time_code = c->avctx->frame_number + c->avctx->timecode_frame_start;
+          /*
+           * LTC drop-frame frame counter drops two frames (0 and 1) every
+           * minute, unless it is exactly divisible by 10
+           */
+          if (c->avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE)
+              time_code = ff_framenum_to_drop_timecode(time_code);
+          buf[1] = (0 << 7) | /* Color fame: 0 - unsync; 1 - sync mode */
+                   /* Drop frame timecode: 0 - nondrop; 1 - drop */
+                   (!!(c->avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE) << 6) |
+                   (((time_code % c->sys->ltc_divisor) / 10) << 4) |                 /* Tens of frames */
+                    ((time_code % c->sys->ltc_divisor) % 10);                        /* Units of frames */
+          buf[2] = (1 << 7) | /* Biphase mark polarity correction: 0 - even; 1 - odd */
+                   ((((time_code / c->sys->ltc_divisor) % 60) / 10) << 4) |          /* Tens of seconds */
+                    (((time_code / c->sys->ltc_divisor) % 60) % 10);                 /* Units of seconds */
+          buf[3] = (1 << 7) | /* Binary group flag BGF0 */
+                   ((((time_code / (c->sys->ltc_divisor * 60)) % 60) / 10) << 4) |   /* Tens of minutes */
+                    (((time_code / (c->sys->ltc_divisor * 60)) % 60) % 10);          /* Units of minutes */
+          buf[4] = (1 << 7) | /* Binary group flag BGF2 */
+                   (1 << 6) | /* Binary group flag BGF1 */
+                   ((((time_code / (c->sys->ltc_divisor * 3600) % 24)) / 10) << 4) | /* Tens of hours */
+                    (((time_code / (c->sys->ltc_divisor * 3600) % 24)) % 10);        /* Units of hours */
+          break;
     default:
           buf[1] = buf[2] = buf[3] = buf[4] = 0xff;
     }
@@ -1249,8 +1275,10 @@
             /* DV subcode: 2DIFs */
             for (j = 0; j < 2; j++) {
                 buf += dv_write_dif_id(dv_sect_subcode, chan, i, j, buf);
-                for (k = 0; k < 6; k++)
-                     buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf) + 5;
+                for (k = 0; k < 6; k++) {
+                     buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size/2), buf);
+                     buf += dv_write_pack(dv_timecode, c, buf);
+                }
                 buf += 29; /* unused bytes */
             }
 
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/h264.c ./h264.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/h264.c	2009-12-13 14:15:18.000000000 +0100
+++ ./h264.c	2009-11-15 04:50:19.000000000 +0100
@@ -2180,6 +2180,8 @@
     h->sei_buffering_period_present =  0;
 }
 
+static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size);
+
 static av_cold int decode_init(AVCodecContext *avctx){
     H264Context *h= avctx->priv_data;
     MpegEncContext * const s = &h->s;
@@ -2195,8 +2197,6 @@
     // set defaults
 //    s->decode_mb= ff_h263_decode_mb;
     s->quarter_sample = 1;
-    if(!avctx->has_b_frames)
-    s->low_delay= 1;
 
     avctx->pix_fmt= avctx->get_format(avctx, avctx->codec->pix_fmts);
     avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt);
@@ -2204,21 +2204,27 @@
 
     decode_init_vlc();
 
-    if(avctx->extradata_size > 0 && avctx->extradata &&
-       *(char *)avctx->extradata == 1){
-        h->is_avc = 1;
-        h->got_avcC = 0;
-    } else {
-        h->is_avc = 0;
-    }
-
     h->thread_context[0] = h;
     h->outputed_poc = INT_MIN;
     h->prev_poc_msb= 1<<16;
     reset_sei(h);
+
+    if(s->flags & CODEC_FLAG_LOW_DELAY)
+        s->low_delay=1;
+    else
+        s->avctx->has_b_frames=1;
+
     if(avctx->codec_id == CODEC_ID_H264){
-        if(avctx->ticks_per_frame == 1){
-            s->avctx->time_base.den *=2;
+        if(avctx->extradata_size > 0 && avctx->extradata) {
+            if (*(char *)avctx->extradata == 1) {
+                if (ff_h264_decode_avcC(h, avctx) < 0)
+                    return -1;
+            } else {
+                if (decode_nal_units(h, avctx->extradata,
+                                     avctx->extradata_size) < 0)
+                    return -1;
+            }
+            h->got_avcC = 1;
         }
         avctx->ticks_per_frame = 2;
     }
@@ -3496,11 +3502,10 @@
     return 0;
 }
 
-static int init_poc(H264Context *h){
+int ff_h264_init_poc(H264Context *h, int field_poc[2])
+{
     MpegEncContext * const s = &h->s;
     const int max_frame_num= 1<<h->sps.log2_max_frame_num;
-    int field_poc[2];
-    Picture *cur = s->current_picture_ptr;
 
     h->frame_num_offset= h->prev_frame_num_offset;
     if(h->frame_num < h->prev_frame_num)
@@ -3564,12 +3569,6 @@
         field_poc[1]= poc;
     }
 
-    if(s->picture_structure != PICT_BOTTOM_FIELD)
-        s->current_picture_ptr->field_poc[0]= field_poc[0];
-    if(s->picture_structure != PICT_TOP_FIELD)
-        s->current_picture_ptr->field_poc[1]= field_poc[1];
-    cur->poc= FFMIN(cur->field_poc[0], cur->field_poc[1]);
-
     return 0;
 }
 
@@ -3715,6 +3714,7 @@
     unsigned int slice_type, tmp, i, j;
     int default_ref_list_done = 0;
     int last_pic_structure;
+    int field_poc[2];
 
     s->dropable= h->nal_ref_idc == 0;
 
@@ -3834,17 +3834,6 @@
 
         s->avctx->width = s->width;
         s->avctx->height = s->height;
-        s->avctx->sample_aspect_ratio= h->sps.sar;
-        if(!s->avctx->sample_aspect_ratio.den)
-            s->avctx->sample_aspect_ratio.den = 1;
-
-        if(h->sps.timing_info_present_flag){
-            s->avctx->time_base= (AVRational){h->sps.num_units_in_tick, h->sps.time_scale};
-            if(h->x264_build > 0 && h->x264_build < 44)
-                s->avctx->time_base.den *= 2;
-            av_reduce(&s->avctx->time_base.num, &s->avctx->time_base.den,
-                      s->avctx->time_base.num, s->avctx->time_base.den, 1<<30);
-        }
     }
 
     h->frame_num= get_bits(&s->gb, h->sps.log2_max_frame_num);
@@ -3865,9 +3854,9 @@
     h->mb_field_decoding_flag= s->picture_structure != PICT_FRAME;
 
     if(h0->current_slice == 0){
-        while(h->frame_num !=  h->prev_frame_num &&
+        while(h->sps.gaps_in_frame_num_allowed_flag == 1 && h->frame_num !=  h->prev_frame_num &&
               h->frame_num != (h->prev_frame_num+1)%(1<<h->sps.log2_max_frame_num)){
-            av_log(NULL, AV_LOG_DEBUG, "Frame num gap %d %d\n", h->frame_num, h->prev_frame_num);
+            av_log(s->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n", h->frame_num, h->prev_frame_num);
             if (frame_start(h) < 0)
                 return -1;
             h->prev_frame_num++;
@@ -3965,7 +3954,14 @@
             h->delta_poc[1]= get_se_golomb(&s->gb);
     }
 
-    init_poc(h);
+    ff_h264_init_poc(h, field_poc);
+
+    if(s->picture_structure != PICT_BOTTOM_FIELD)
+        s->current_picture_ptr->field_poc[0]= field_poc[0];
+    if(s->picture_structure != PICT_TOP_FIELD)
+        s->current_picture_ptr->field_poc[1]= field_poc[1];
+    s->current_picture_ptr->poc= FFMIN(s->current_picture_ptr->field_poc[0],
+                                       s->current_picture_ptr->field_poc[1]);
 
     if(h->pps.redundant_pic_cnt_present){
         h->redundant_pic_count= get_ue_golomb(&s->gb);
@@ -6918,8 +6914,11 @@
 
     user_data[i]= 0;
     e= sscanf(user_data+16, "x264 - core %d"/*%s - H.264/MPEG-4 AVC codec - Copyleft 2005 - http://www.videolan.org/x264.html*/, &build);
-    if(e==1 && build>=0)
+    if(e==1 && build>=0){
         h->x264_build= build;
+        if(h->x264_build > 0 && h->x264_build < 44)
+            s->avctx->time_base.den *= 2;
+    }
 
     if(s->avctx->debug & FF_DEBUG_BUGS)
         av_log(s->avctx, AV_LOG_DEBUG, "user data:\"%s\"\n", user_data+16);
@@ -7063,6 +7062,10 @@
     }
 //            s->avctx->aspect_ratio= sar_width*s->width / (float)(s->height*sar_height);
 
+    s->avctx->sample_aspect_ratio= sps->sar;
+    if(!s->avctx->sample_aspect_ratio.den)
+        s->avctx->sample_aspect_ratio.den = 1;
+
     if(get_bits1(&s->gb)){      /* overscan_info_present_flag */
         get_bits1(&s->gb);      /* overscan_appropriate_flag */
     }
@@ -7091,6 +7094,10 @@
             return -1;
         }
         sps->fixed_frame_rate_flag = get_bits1(&s->gb);
+
+        s->avctx->time_base= (AVRational){sps->num_units_in_tick, sps->time_scale};
+        av_reduce(&s->avctx->time_base.num, &s->avctx->time_base.den,
+                  s->avctx->time_base.num, s->avctx->time_base.den, 1<<30);
     }
 
     sps->nal_hrd_parameters_present_flag = get_bits1(&s->gb);
@@ -7119,6 +7126,9 @@
             av_log(h->s.avctx, AV_LOG_ERROR, "illegal num_reorder_frames %d\n", sps->num_reorder_frames);
             return -1;
         }
+
+        s->avctx->has_b_frames = sps->num_reorder_frames;
+        s->low_delay = 0;
     }
 
     return 0;
@@ -7301,6 +7311,12 @@
                );
     }
 
+    if(!sps->bitstream_restriction_flag &&
+       s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT){
+        s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
+        s->low_delay= 0;
+    }
+
     av_free(h->sps_buffers[sps_id]);
     h->sps_buffers[sps_id]= sps;
     h->sps = *sps;
@@ -7638,12 +7654,6 @@
         case NAL_SPS:
             init_get_bits(&s->gb, ptr, bit_length);
             ff_h264_decode_seq_parameter_set(h);
-
-            if(s->flags& CODEC_FLAG_LOW_DELAY)
-                s->low_delay=1;
-
-            if(avctx->has_b_frames < 2)
-                avctx->has_b_frames= !s->low_delay;
             break;
         case NAL_PPS:
             init_get_bits(&s->gb, ptr, bit_length);
@@ -7695,6 +7705,53 @@
         return pos;
 }
 
+int ff_h264_decode_avcC(H264Context *h, AVCodecContext *avctx)
+{
+    int i, cnt, nalsize;
+    unsigned char *p = avctx->extradata;
+
+    if(avctx->extradata_size < 7) {
+        av_log(avctx, AV_LOG_ERROR, "avcC too short\n");
+        return -1;
+    }
+    if(*p != 1) {
+        av_log(avctx, AV_LOG_ERROR, "Unknown avcC version %d\n", *p);
+        return -1;
+    }
+
+    h->is_avc = 1;
+    /* sps and pps in the avcC always have length coded with 2 bytes,
+       so put a fake nal_length_size = 2 while parsing them */
+    h->nal_length_size = 2;
+    // Decode sps from avcC
+    cnt = *(p+5) & 0x1f; // Number of sps
+    p += 6;
+    for (i = 0; i < cnt; i++) {
+        nalsize = AV_RB16(p) + 2;
+        if (decode_nal_units(h, p, nalsize) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Decoding sps %d from avcC failed\n", i);
+            return -1;
+        }
+        p += nalsize;
+    }
+    // Decode pps from avcC
+    cnt = *(p++); // Number of pps
+    for (i = 0; i < cnt; i++) {
+        nalsize = AV_RB16(p) + 2;
+        if (decode_nal_units(h, p, nalsize) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "Decoding pps %d from avcC failed\n", i);
+            return -1;
+        }
+        p += nalsize;
+    }
+    // Now store right nal length size, that will be use to parse all other nals
+    h->nal_length_size = ((*(((char*)(avctx->extradata))+4))&0x03)+1;
+    // Do not reparse avcC
+    h->got_avcC = 1;
+
+    return 0;
+}
+
 static int decode_frame(AVCodecContext *avctx,
                              void *data, int *data_size,
                              AVPacket *avpkt)
@@ -7734,53 +7791,6 @@
         return 0;
     }
 
-    if(h->is_avc && !h->got_avcC) {
-        int i, cnt, nalsize;
-        unsigned char *p = avctx->extradata;
-        if(avctx->extradata_size < 7) {
-            av_log(avctx, AV_LOG_ERROR, "avcC too short\n");
-            return -1;
-        }
-        if(*p != 1) {
-            av_log(avctx, AV_LOG_ERROR, "Unknown avcC version %d\n", *p);
-            return -1;
-        }
-        /* sps and pps in the avcC always have length coded with 2 bytes,
-           so put a fake nal_length_size = 2 while parsing them */
-        h->nal_length_size = 2;
-        // Decode sps from avcC
-        cnt = *(p+5) & 0x1f; // Number of sps
-        p += 6;
-        for (i = 0; i < cnt; i++) {
-            nalsize = AV_RB16(p) + 2;
-            if(decode_nal_units(h, p, nalsize) < 0) {
-                av_log(avctx, AV_LOG_ERROR, "Decoding sps %d from avcC failed\n", i);
-                return -1;
-            }
-            p += nalsize;
-        }
-        // Decode pps from avcC
-        cnt = *(p++); // Number of pps
-        for (i = 0; i < cnt; i++) {
-            nalsize = AV_RB16(p) + 2;
-            if(decode_nal_units(h, p, nalsize)  != nalsize) {
-                av_log(avctx, AV_LOG_ERROR, "Decoding pps %d from avcC failed\n", i);
-                return -1;
-            }
-            p += nalsize;
-        }
-        // Now store right nal length size, that will be use to parse all other nals
-        h->nal_length_size = ((*(((char*)(avctx->extradata))+4))&0x03)+1;
-        // Do not reparse avcC
-        h->got_avcC = 1;
-    }
-
-    if(!h->got_avcC && !h->is_avc && s->avctx->extradata_size){
-        if(decode_nal_units(h, s->avctx->extradata, s->avctx->extradata_size) < 0)
-            return -1;
-        h->got_avcC = 1;
-    }
-
     buf_index=decode_nal_units(h, buf, buf_size);
     if(buf_index < 0)
         return -1;
@@ -7869,19 +7879,6 @@
         //FIXME do something with unavailable reference frames
 
             /* Sort B-frames into display order */
-
-            if(h->sps.bitstream_restriction_flag
-               && s->avctx->has_b_frames < h->sps.num_reorder_frames){
-                s->avctx->has_b_frames = h->sps.num_reorder_frames;
-                s->low_delay = 0;
-            }
-
-            if(   s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT
-               && !h->sps.bitstream_restriction_flag){
-                s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
-                s->low_delay= 0;
-            }
-
             pics = 0;
             while(h->delayed_pic[pics]) pics++;
 
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/h264.h ./h264.h
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/h264.h	2009-12-13 14:13:19.000000000 +0100
+++ ./h264.h	2009-11-15 04:50:19.000000000 +0100
@@ -563,6 +563,16 @@
 int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length);
 
 /**
+ * Decode ISO Media 'avcC' extradata
+ */
+int ff_h264_decode_avcC(H264Context *h, AVCodecContext *avctx);
+
+/**
+ * Init Picture Order Count
+ */
+int ff_h264_init_poc(H264Context *h, int field_poc[2]);
+
+/**
  * Decodes a network abstraction layer unit.
  * @param consumed is the number of bytes used as input
  * @param length is the length of the array
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/h264_parser.c ./h264_parser.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/h264_parser.c	2009-12-13 14:13:19.000000000 +0100
+++ ./h264_parser.c	2009-11-15 04:50:19.000000000 +0100
@@ -32,6 +32,16 @@
 
 #include <assert.h>
 
+typedef struct {
+    H264Context h;
+    int field_poc[2];
+    uint8_t *buf;
+    unsigned buf_size;
+    unsigned frame_size;
+    int pict_type;
+    int key_frame;
+    int top_field_first;
+} H264ParseContext;
 
 int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_size)
 {
@@ -110,7 +120,8 @@
                                   AVCodecContext *avctx,
                                   const uint8_t *buf, int buf_size)
 {
-    H264Context *h = s->priv_data;
+    H264ParseContext *c = s->priv_data;
+    H264Context *h = &c->h;
     const uint8_t *buf_end = buf + buf_size;
     unsigned int pps_id;
     unsigned int slice_type;
@@ -118,21 +129,31 @@
     const uint8_t *ptr;
 
     /* set some sane default values */
-    s->pict_type = FF_I_TYPE;
+    s->pict_type = 0;
     s->key_frame = 0;
 
-    h->s.avctx= avctx;
-    h->sei_recovery_frame_cnt = -1;
+    if (!buf_size)
+        return 0;
+
+    h->sei_recovery_frame_cnt       = -1;
     h->sei_dpb_output_delay         =  0;
     h->sei_cpb_removal_delay        = -1;
     h->sei_buffering_period_present =  0;
 
     for(;;) {
-        int src_length, dst_length, consumed;
-        buf = ff_find_start_code(buf, buf_end, &state);
-        if(buf >= buf_end)
-            break;
-        --buf;
+        int src_length, dst_length, consumed, i, nalsize = 0;
+        int field_poc[2];
+
+        if (h->is_avc) {
+            for (i = 0; i < h->nal_length_size && buf < buf_end; i++)
+                nalsize = (nalsize << 8) | *buf++;
+            state = buf[0];
+        } else {
+            buf = ff_find_start_code(buf, buf_end, &state);
+            if(buf >= buf_end)
+                break;
+            --buf;
+        }
         src_length = buf_end - buf;
         switch (state & 0x1f) {
         case NAL_SLICE:
@@ -153,6 +174,14 @@
             break;
         case NAL_PPS:
             ff_h264_decode_picture_parameter_set(h, h->s.gb.size_in_bits);
+            if(h->sps.timing_info_present_flag){
+                avctx->time_base= (AVRational){h->sps.num_units_in_tick, h->sps.time_scale};
+                if(h->x264_build > 0 && h->x264_build < 44)
+                    avctx->time_base.den *= 2;
+                av_reduce(&avctx->time_base.num, &avctx->time_base.den,
+                          avctx->time_base.num, avctx->time_base.den, 1<<30);
+                avctx->ticks_per_frame = 2;
+            }
             break;
         case NAL_SEI:
             ff_h264_decode_sei(h);
@@ -195,12 +224,45 @@
                 }
             }
 
+            if(h->s.picture_structure==PICT_FRAME){
+                h->curr_pic_num=   h->frame_num;
+                h->max_pic_num= 1<< h->sps.log2_max_frame_num;
+            }else{
+                h->curr_pic_num= 2*h->frame_num + 1;
+                h->max_pic_num= 1<<(h->sps.log2_max_frame_num + 1);
+            }
+
+            if(h->nal_unit_type == NAL_IDR_SLICE){
+                get_ue_golomb(&h->s.gb); /* idr_pic_id */
+            }
+
+            if(h->sps.poc_type==0){
+                h->poc_lsb= get_bits(&h->s.gb, h->sps.log2_max_poc_lsb);
+
+                if(h->pps.pic_order_present==1 && h->s.picture_structure==PICT_FRAME){
+                    h->delta_poc_bottom= get_se_golomb(&h->s.gb);
+                }
+            }
+
+            if(h->sps.poc_type==1 && !h->sps.delta_pic_order_always_zero_flag){
+                h->delta_poc[0]= get_se_golomb(&h->s.gb);
+
+                if(h->pps.pic_order_present==1 && h->s.picture_structure==PICT_FRAME)
+                    h->delta_poc[1]= get_se_golomb(&h->s.gb);
+            }
+
+            ff_h264_init_poc(h, field_poc);
+
+            if(h->s.picture_structure != PICT_BOTTOM_FIELD)
+                c->field_poc[0] = field_poc[0];
+            if(h->s.picture_structure != PICT_TOP_FIELD)
+                c->field_poc[1] = field_poc[1];
+
             if(h->sps.pic_struct_present_flag) {
                 switch (h->sei_pic_struct) {
+                    /* fields are merged */
                     case SEI_PIC_STRUCT_TOP_FIELD:
                     case SEI_PIC_STRUCT_BOTTOM_FIELD:
-                        s->repeat_pict = 0;
-                        break;
                     case SEI_PIC_STRUCT_FRAME:
                     case SEI_PIC_STRUCT_TOP_BOTTOM:
                     case SEI_PIC_STRUCT_BOTTOM_TOP:
@@ -224,7 +286,22 @@
                 s->repeat_pict = h->s.picture_structure == PICT_FRAME ? 1 : 0;
             }
 
-            return 0; /* no need to evaluate the rest */
+            /* no need to evaluate the rest */
+            if (h->s.picture_structure == PICT_TOP_FIELD) {
+                if (c->field_poc[1] == INT_MAX)
+                    c->top_field_first = 1;
+                return 1 + !c->top_field_first;
+            } else if (h->s.picture_structure == PICT_BOTTOM_FIELD) {
+                if (c->field_poc[0] == INT_MAX)
+                    c->top_field_first = 0;
+                return 1 + c->top_field_first;
+            }
+
+            return 0;
+        }
+        if (h->is_avc && consumed != nalsize) {
+            av_log(avctx, AV_LOG_WARNING, "consumed %d nalsize %d\n", consumed, nalsize);
+            consumed = nalsize;
         }
         buf += consumed;
     }
@@ -238,9 +315,10 @@
                       const uint8_t **poutbuf, int *poutbuf_size,
                       const uint8_t *buf, int buf_size)
 {
-    H264Context *h = s->priv_data;
+    H264ParseContext *c = s->priv_data;
+    H264Context *h = &c->h;
     ParseContext *pc = &h->s.parse_context;
-    int next;
+    int next, ret;
 
     if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
         next= buf_size;
@@ -257,18 +335,75 @@
             assert(pc->last_index + next >= 0 );
             ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state
         }
+    }
 
-        parse_nal_units(s, avctx, buf, buf_size);
+    h->s.avctx= avctx;
 
-        if (h->sei_cpb_removal_delay >= 0) {
-            s->dts_sync_point    = h->sei_buffering_period_present;
-            s->dts_ref_dts_delta = h->sei_cpb_removal_delay;
-            s->pts_dts_delta     = h->sei_dpb_output_delay;
+    if (avctx->extradata_size > 0 && avctx->extradata && !h->got_avcC) {
+        if (*(char *)avctx->extradata == 1) {
+            if (ff_h264_decode_avcC(h, avctx) < 0)
+                return -1;
         } else {
-            s->dts_sync_point    = INT_MIN;
-            s->dts_ref_dts_delta = INT_MIN;
-            s->pts_dts_delta     = INT_MIN;
+            parse_nal_units(s, avctx, avctx->extradata, avctx->extradata_size);
+            h->got_avcC = 1;
+        }
+    }
+
+    ret = parse_nal_units(s, avctx, buf, buf_size);
+    if (ret < 0 || (!s->pict_type && buf_size)) {
+        /* update parser context anyway for timestamps and pos */
+        s->frame_offset = s->next_frame_offset;
+        s->next_frame_offset = s->cur_offset + next;
+        s->fetch_timestamp = 1;
+
+        *poutbuf = NULL;
+        *poutbuf_size = 0;
+        return next;
+    }
+
+    if (h->sei_cpb_removal_delay >= 0) {
+        s->dts_sync_point    = h->sei_buffering_period_present;
+        s->dts_ref_dts_delta = h->sei_cpb_removal_delay;
+        s->pts_dts_delta     = h->sei_dpb_output_delay;
+    } else {
+        s->dts_sync_point    = INT_MIN;
+        s->dts_ref_dts_delta = INT_MIN;
+        s->pts_dts_delta     = INT_MIN;
+    }
+
+    if (ret == 1) { // first field
+        uint8_t *nbuf;
+        nbuf = av_fast_realloc(c->buf, &c->buf_size, buf_size);
+        if (!nbuf)
+            return AVERROR(ENOMEM);
+        c->buf = nbuf;
+        memcpy(nbuf, buf, buf_size);
+
+        c->frame_size = buf_size;
+        /* keep pict information from the first field */
+        c->pict_type = s->pict_type;
+        c->key_frame = s->key_frame;
+
+        *poutbuf = NULL;
+        *poutbuf_size = 0;
+        return next;
+    } else if (ret == 2) { // second field
+        uint8_t *nbuf;
+        nbuf = av_fast_realloc(c->buf, &c->buf_size, c->frame_size +
+                               buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+        if (!nbuf) {
+            c->frame_size = 0;
+            return AVERROR(ENOMEM);
         }
+        c->buf = nbuf;
+        memcpy(nbuf+c->frame_size, buf, buf_size);
+        memset(nbuf+c->frame_size+buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+        buf = nbuf;
+        buf_size += c->frame_size;
+        c->frame_size = 0;
+
+        s->pict_type = c->pict_type;
+        s->key_frame = c->key_frame;
     }
 
     *poutbuf = buf;
@@ -300,20 +435,36 @@
     return 0;
 }
 
+static int init(AVCodecParserContext *s)
+{
+    H264ParseContext *c = s->priv_data;
+
+    c->h.thread_context[0] = &c->h;
+    c->h.outputed_poc = INT_MIN;
+    c->h.prev_poc_msb= 1<<16;
+
+    c->field_poc[0]=
+    c->field_poc[1]= INT_MAX;
+
+    return 0;
+}
+
 static void close(AVCodecParserContext *s)
 {
-    H264Context *h = s->priv_data;
-    ParseContext *pc = &h->s.parse_context;
+    H264ParseContext *c = s->priv_data;
+    ParseContext *pc = &c->h.s.parse_context;
 
+    av_freep(&c->buf);
+    c->frame_size = 0;
     av_free(pc->buffer);
-    ff_h264_free_context(h);
+    ff_h264_free_context(&c->h);
 }
 
 
 AVCodecParser h264_parser = {
     { CODEC_ID_H264 },
-    sizeof(H264Context),
-    NULL,
+    sizeof(H264ParseContext),
+    init,
     h264_parse,
     close,
     h264_split,
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/imx_remove_klv_bsf.c ./imx_remove_klv_bsf.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/imx_remove_klv_bsf.c	1970-01-01 01:00:00.000000000 +0100
+++ ./imx_remove_klv_bsf.c	2009-11-15 04:50:19.000000000 +0100
@@ -0,0 +1,95 @@
+/*
+ * IMX remove klv bitstream filter
+ * Copyright (c) 2009 Baptiste Coudurier <baptiste dot coudurier at gmail dot com>
+ *
+ * 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
+ */
+
+/**
+ * @file libavcodec/imx_remove_klv_bsf.c
+ * imx remove klv bitstream filter
+ * remove klv cruft from d-10/imx mpeg-2 bitstream stored in mov
+ */
+
+#include "avcodec.h"
+#include "bytestream.h"
+
+static int64_t klv_decode_ber_length(const uint8_t **buf)
+{
+    uint64_t size = bytestream_get_byte(buf);
+    if (size & 0x80) { /* long form */
+        int bytes_num = size & 0x7f;
+        /* SMPTE 379M 5.3.4 guarantee that bytes_num must not exceed 8 bytes */
+        if (bytes_num > 8)
+            return -1;
+        size = 0;
+        while (bytes_num--)
+            size = size << 8 | bytestream_get_byte(buf);
+    }
+    return size;
+}
+
+static int imx_remove_klv(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
+                          uint8_t **poutbuf, int *poutbuf_size,
+                          const uint8_t *buf, int buf_size, int keyframe)
+{
+    /* MXF essence element key */
+    static const uint8_t d10_klv_header[15] = { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x05,0x01,0x01 };
+    const uint8_t *bufp = buf;
+
+    if (avctx->codec_id != CODEC_ID_MPEG2VIDEO) {
+        av_log(avctx, AV_LOG_ERROR, "imx bitstream filter only applies to mpeg2video codec\n");
+        return 0;
+    }
+
+    if (buf_size < 17) {
+        av_log(avctx, AV_LOG_ERROR, "wrong packet size\n");
+        return -1;
+    }
+
+    if (!memcmp(buf, d10_klv_header, 15)) {
+        int64_t frame_size;
+        bufp += 16;
+        if ((frame_size = klv_decode_ber_length(&bufp)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "error decoding klv length\n");
+            return -1;
+        }
+        if (bufp - buf + frame_size > buf_size) {
+            av_log(avctx, AV_LOG_ERROR, "wrong frame size\n");
+            return -1;
+        }
+        if (frame_size > INT_MAX)
+            return -1;
+        *poutbuf = av_malloc(frame_size);
+        if (!*poutbuf)
+            return AVERROR(ENOMEM);
+        memcpy(*poutbuf, bufp, frame_size);
+        *poutbuf_size = frame_size;
+        return 1;
+    } else {
+        av_log(avctx, AV_LOG_ERROR, "bitstream does not contain klv packet header\n");
+        *poutbuf = NULL;
+        *poutbuf_size = 0;
+        return 0;
+    }
+}
+
+AVBitStreamFilter imx_remove_klv_bsf = {
+    "imxremoveklv",
+    0,
+    imx_remove_klv,
+};
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/Makefile ./Makefile
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/Makefile	2009-12-13 14:15:18.000000000 +0100
+++ ./Makefile	2009-11-15 04:50:19.000000000 +0100
@@ -88,7 +88,7 @@
 OBJS-$(CONFIG_DVDSUB_DECODER)          += dvdsubdec.o
 OBJS-$(CONFIG_DVDSUB_ENCODER)          += dvdsubenc.o
 OBJS-$(CONFIG_DVVIDEO_DECODER)         += dv.o dvdata.o
-OBJS-$(CONFIG_DVVIDEO_ENCODER)         += dv.o dvdata.o
+OBJS-$(CONFIG_DVVIDEO_ENCODER)         += dv.o dvdata.o timecode.o
 OBJS-$(CONFIG_DXA_DECODER)             += dxa.o
 OBJS-$(CONFIG_EAC3_DECODER)            += eac3dec.o eac3dec_data.o
 OBJS-$(CONFIG_EACMV_DECODER)           += eacmv.o
@@ -193,6 +193,7 @@
 OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12.o mpeg12data.o \
                                           mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_MPEG1VIDEO_ENCODER)      += mpeg12enc.o mpegvideo_enc.o \
+                                          timecode.o \
                                           motion_est.o ratecontrol.o  \
                                           mpeg12.o mpeg12data.o       \
                                           mpegvideo.o error_resilience.o
@@ -200,6 +201,7 @@
 OBJS-$(CONFIG_MPEG2VIDEO_DECODER)      += mpeg12.o mpeg12data.o \
                                           mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_MPEG2VIDEO_ENCODER)      += mpeg12enc.o mpegvideo_enc.o \
+                                          timecode.o \
                                           motion_est.o ratecontrol.o  \
                                           mpeg12.o mpeg12data.o       \
                                           mpegvideo.o error_resilience.o
@@ -266,6 +268,7 @@
                                           mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_RV40_DECODER)            += rv40.o rv34.o h264pred.o rv40dsp.o \
                                           mpegvideo.o error_resilience.o
+OBJS-$(CONFIG_S302M_DECODER)           += s302m.o
 OBJS-$(CONFIG_SGI_DECODER)             += sgidec.o
 OBJS-$(CONFIG_SGI_ENCODER)             += sgienc.o rle.o
 OBJS-$(CONFIG_SHORTEN_DECODER)         += shorten.o
@@ -534,6 +537,7 @@
 OBJS-$(CONFIG_DUMP_EXTRADATA_BSF)         += dump_extradata_bsf.o
 OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF)       += h264_mp4toannexb_bsf.o
 OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF)        += imx_dump_header_bsf.o
+OBJS-$(CONFIG_IMX_REMOVE_KLV_BSF)         += imx_remove_klv_bsf.o
 OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF)     += mjpega_dump_header_bsf.o
 OBJS-$(CONFIG_MOV2TEXTSUB_BSF)            += movsub_bsf.o
 OBJS-$(CONFIG_MP3_HEADER_COMPRESS_BSF)    += mp3_header_compress_bsf.o
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mips and ./mips
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mlib and ./mlib
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mpeg12enc.c ./mpeg12enc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mpeg12enc.c	2009-12-13 14:13:20.000000000 +0100
+++ ./mpeg12enc.c	2009-11-15 04:50:19.000000000 +0100
@@ -32,6 +32,7 @@
 #include "mpeg12.h"
 #include "mpeg12data.h"
 #include "bytestream.h"
+#include "timecode.h"
 
 
 static const uint8_t inv_non_linear_qscale[13] = {
@@ -291,18 +292,16 @@
 
             s->gop_picture_number = s->current_picture_ptr->coded_picture_number;
             if (s->avctx->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE) {
-                /* only works for NTSC 29.97 */
-                int d = time_code / 17982;
-                int m = time_code % 17982;
-                //if (m < 2) m += 2; /* not needed since -2,-1 / 1798 in C returns 0 */
-                time_code += 18 * d + 2 * ((m - 2) / 1798);
+                time_code = ff_framenum_to_drop_timecode(time_code);
             }
             put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24));
             put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60));
             put_bits(&s->pb, 1, 1);
             put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60));
             put_bits(&s->pb, 6, (uint32_t)((time_code % fps)));
-            put_bits(&s->pb, 1, !!(s->flags & CODEC_FLAG_CLOSED_GOP));
+            put_bits(&s->pb, 1, !!(s->flags & CODEC_FLAG_CLOSED_GOP) ||
+                     (s->avctx->max_b_frames > 0 &&
+                      !s->current_picture_ptr->coded_picture_number));
             put_bits(&s->pb, 1, 0); /* broken link */
         }
 }
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mpegvideo_enc.c ./mpegvideo_enc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mpegvideo_enc.c	2009-12-13 14:15:18.000000000 +0100
+++ ./mpegvideo_enc.c	2009-11-15 04:50:19.000000000 +0100
@@ -381,6 +381,14 @@
         return -1;
     }
 
+    if ((s->codec_id == CODEC_ID_MPEG4 || s->codec_id == CODEC_ID_H263 ||
+         s->codec_id == CODEC_ID_H263P) &&
+        (avctx->sample_aspect_ratio.num > 255 || avctx->sample_aspect_ratio.den > 255)) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid pixel aspect ratio %i/%i, limit is 255/255\n",
+               avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
+        return -1;
+    }
+
     if((s->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME|CODEC_FLAG_ALT_SCAN))
        && s->codec_id != CODEC_ID_MPEG4 && s->codec_id != CODEC_ID_MPEG2VIDEO){
         av_log(avctx, AV_LOG_ERROR, "interlacing not supported by codec\n");
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mpegvideo_parser.c ./mpegvideo_parser.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/mpegvideo_parser.c	2009-12-13 14:15:18.000000000 +0100
+++ ./mpegvideo_parser.c	2009-11-15 04:50:19.000000000 +0100
@@ -28,15 +28,17 @@
                                       const uint8_t *buf, int buf_size)
 {
     ParseContext1 *pc = s->priv_data;
-    const uint8_t *buf_end;
+    const uint8_t *buf_end = buf + buf_size;
     uint32_t start_code;
     int frame_rate_index, ext_type, bytes_left;
     int frame_rate_ext_n, frame_rate_ext_d;
     int picture_structure, top_field_first, repeat_first_field, progressive_frame;
     int horiz_size_ext, vert_size_ext, bit_rate_ext;
 //FIXME replace the crap with get_bits()
+
+    s->pict_type = 0;
     s->repeat_pict = 0;
-    buf_end = buf + buf_size;
+
     while (buf < buf_end) {
         start_code= -1;
         buf= ff_find_start_code(buf, buf_end, &start_code);
@@ -58,6 +60,7 @@
                 avctx->bit_rate = ((buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6))*400;
                 avctx->codec_id = CODEC_ID_MPEG1VIDEO;
                 avctx->sub_id = 1;
+                avctx->has_b_frames = 1; // consider mpeg-1 has delay
             }
             break;
         case EXT_START_CODE:
@@ -141,12 +144,22 @@
             *poutbuf_size = 0;
             return buf_size;
         }
-
     }
     /* we have a full frame : we just parse the first few MPEG headers
        to have the full timing information. The time take by this
        function should be negligible for uncorrupted streams */
     mpegvideo_extract_headers(s, avctx, buf, buf_size);
+    if (!s->pict_type && buf_size) {
+        av_log(avctx, AV_LOG_ERROR, "error fetching pict type, discarding\n");
+        /* update parser context anyway for timestamps and pos */
+        s->frame_offset = s->next_frame_offset;
+        s->next_frame_offset = s->cur_offset + next;
+        s->fetch_timestamp = 1;
+
+        *poutbuf = NULL;
+        *poutbuf_size = 0;
+        return next;
+    }
 #if 0
     printf("pict_type=%d frame_rate=%0.3f repeat_pict=%d\n",
            s->pict_type, (double)avctx->time_base.den / avctx->time_base.num, s->repeat_pict);
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/pcm.c ./pcm.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/pcm.c	2009-12-13 14:13:20.000000000 +0100
+++ ./pcm.c	2009-11-15 04:50:19.000000000 +0100
@@ -192,15 +192,6 @@
     case CODEC_ID_PCM_U24BE:
         ENCODE(uint32_t, be24, samples, dst, n, 8, 0x800000)
         break;
-    case CODEC_ID_PCM_S24DAUD:
-        for(;n>0;n--) {
-            uint32_t tmp = av_reverse[(*samples >> 8) & 0xff] +
-                           (av_reverse[*samples & 0xff] << 8);
-            tmp <<= 4; // sync flags would go here
-            bytestream_put_be24(&dst, tmp);
-            samples++;
-        }
-        break;
     case CODEC_ID_PCM_U16LE:
         ENCODE(uint16_t, le16, samples, dst, n, 0, 0x8000)
         break;
@@ -392,14 +383,6 @@
     case CODEC_ID_PCM_U24BE:
         DECODE(uint32_t, be24, src, samples, n, 8, 0x800000)
         break;
-    case CODEC_ID_PCM_S24DAUD:
-        for(;n>0;n--) {
-          uint32_t v = bytestream_get_be24(&src);
-          v >>= 4; // sync flags are here
-          *samples++ = av_reverse[(v >> 8) & 0xff] +
-                       (av_reverse[v & 0xff] << 8);
-        }
-        break;
     case CODEC_ID_PCM_S16LE_PLANAR:
         n /= avctx->channels;
         for(c=0;c<avctx->channels;c++)
@@ -564,7 +547,6 @@
 PCM_CODEC  (CODEC_ID_PCM_S16LE, SAMPLE_FMT_S16, pcm_s16le, "PCM signed 16-bit little-endian");
 PCM_DECODER(CODEC_ID_PCM_S16LE_PLANAR, SAMPLE_FMT_S16, pcm_s16le_planar, "PCM 16-bit little-endian planar");
 PCM_CODEC  (CODEC_ID_PCM_S24BE, SAMPLE_FMT_S32, pcm_s24be, "PCM signed 24-bit big-endian");
-PCM_CODEC  (CODEC_ID_PCM_S24DAUD, SAMPLE_FMT_S16,  pcm_s24daud, "PCM D-Cinema audio signed 24-bit");
 PCM_CODEC  (CODEC_ID_PCM_S24LE, SAMPLE_FMT_S32, pcm_s24le, "PCM signed 24-bit little-endian");
 PCM_CODEC  (CODEC_ID_PCM_S32BE, SAMPLE_FMT_S32, pcm_s32be, "PCM signed 32-bit big-endian");
 PCM_CODEC  (CODEC_ID_PCM_S32LE, SAMPLE_FMT_S32, pcm_s32le, "PCM signed 32-bit little-endian");
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/ppc and ./ppc
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/ps2 and ./ps2
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/s302m.c ./s302m.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/s302m.c	1970-01-01 01:00:00.000000000 +0100
+++ ./s302m.c	2009-11-15 04:50:19.000000000 +0100
@@ -0,0 +1,142 @@
+/*
+ * SMPTE 302M decoder
+ * Copyright (c) 2008 Laurent Aimar <fenrir at videolan.org>
+ * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier at gmail.com>
+ *
+ * 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 "libavutil/intreadwrite.h"
+
+#define AES3_HEADER_LEN 4
+
+static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, int buf_size)
+{
+    uint32_t h;
+    int frame_size, channels, id, bits;
+
+    if (buf_size <= AES3_HEADER_LEN) {
+        av_log(avctx, AV_LOG_ERROR, "frame is too short\n");
+        return -1;
+    }
+
+    /*
+     * AES3 header :
+     * size:            16
+     * number channels   2
+     * channel_id        8
+     * bits per samples  2
+     * alignments        4
+     */
+
+    h = AV_RB32(buf);
+    frame_size = (h >> 16) & 0xffff;
+    channels = 2 + 2*((h >> 14) & 0x03);
+    id = (h >> 6) & 0xff;
+    bits = 16 + 4*((h >> 4) & 0x03);
+
+    if (AES3_HEADER_LEN + frame_size != buf_size || bits > 24) {
+        av_log(avctx, AV_LOG_ERROR, "frame has invalid header\n");
+        return -1;
+    }
+
+    /* Set output properties */
+    avctx->bits_per_coded_sample = bits;
+    if (bits > 16)
+        avctx->sample_fmt = SAMPLE_FMT_S32;
+    else
+        avctx->sample_fmt = SAMPLE_FMT_S16;
+
+    avctx->channels = channels;
+    avctx->sample_rate = 48000;
+    avctx->bit_rate = 48000*avctx->channels*(avctx->bits_per_coded_sample+4) +
+        32*(48000/(buf_size*8/(avctx->channels*(avctx->bits_per_coded_sample+4))));
+
+    return frame_size;
+}
+
+static int s302m_decode_frame(AVCodecContext *avctx,
+                              void *data, int *data_size,
+                              AVPacket *avpkt)
+{
+    const uint8_t *buf = avpkt->data;
+    int frame_size, buf_size = avpkt->size;
+
+    frame_size = s302m_parse_frame_header(avctx, buf, buf_size);
+    if (frame_size < 0)
+        return -1;
+
+    buf_size -= AES3_HEADER_LEN;
+    buf      += AES3_HEADER_LEN;
+
+    if (*data_size < 4*buf_size*8/(avctx->bits_per_coded_sample+4))
+        return -1;
+
+    if (avctx->bits_per_coded_sample == 24) {
+        uint32_t *o = data;
+        for (; buf_size > 6; buf_size -= 7) {
+            *o++ = (av_reverse[buf[2]]      << 24) |
+                   (av_reverse[buf[1]]      << 16) |
+                   (av_reverse[buf[0]]      <<  8);
+            *o++ = (av_reverse[buf[6]&0xf0] << 28) |
+                   (av_reverse[buf[5]]      << 20) |
+                   (av_reverse[buf[4]]      << 12) |
+                   (av_reverse[buf[3]&0x0f] <<  8);
+            buf += 7;
+        }
+        *data_size = (uint8_t*)o - (uint8_t*)data;
+    } else if (avctx->bits_per_coded_sample == 20) {
+        uint32_t *o = data;
+        for (; buf_size > 5; buf_size -= 6) {
+            *o++ = (av_reverse[buf[2]&0xf0] << 28) |
+                   (av_reverse[buf[1]]      << 20) |
+                   (av_reverse[buf[0]]      << 12);
+            *o++ = (av_reverse[buf[5]&0xf0] << 28) |
+                   (av_reverse[buf[4]]      << 20) |
+                   (av_reverse[buf[3]]      << 12);
+            buf += 6;
+        }
+        *data_size = (uint8_t*)o - (uint8_t*)data;
+    } else {
+        uint16_t *o = data;
+        for (; buf_size > 4; buf_size -= 5) {
+            *o++ = (av_reverse[buf[1]]      <<  8) |
+                    av_reverse[buf[0]];
+            *o++ = (av_reverse[buf[4]&0xf0] << 12) |
+                   (av_reverse[buf[3]]      <<  4) |
+                    av_reverse[buf[2]&0x0f];
+            buf += 5;
+        }
+        *data_size = (uint8_t*)o - (uint8_t*)data;
+    }
+
+    return buf - avpkt->data;
+}
+
+
+AVCodec s302m_decoder = {
+    "s302m",
+    CODEC_TYPE_AUDIO,
+    CODEC_ID_S302M,
+    0,
+    NULL,
+    NULL,
+    NULL,
+    s302m_decode_frame,
+    .long_name= NULL_IF_CONFIG_SMALL("SMPTE 302M"),
+};
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/sh4 and ./sh4
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/sparc and ./sparc
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/timecode.c ./timecode.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/timecode.c	1970-01-01 01:00:00.000000000 +0100
+++ ./timecode.c	2009-11-15 04:50:19.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+ * Timecode helper functions
+ * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier at free.fr>
+ *
+ * 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 "timecode.h"
+
+int ff_framenum_to_drop_timecode(int frame_num)
+{
+    /* only works for NTSC 29.97 */
+    int d = frame_num / 17982;
+    int m = frame_num % 17982;
+    //if (m < 2) m += 2; /* not needed since -2,-1 / 1798 in C returns 0 */
+    return frame_num + 18 * d + 2 * ((m - 2) / 1798);
+}
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/timecode.h ./timecode.h
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/timecode.h	1970-01-01 01:00:00.000000000 +0100
+++ ./timecode.h	2009-11-15 04:50:19.000000000 +0100
@@ -0,0 +1,33 @@
+/*
+ * Timecode helper functions
+ * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier at free.fr>
+ *
+ * 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 AVCODEC_TIMECODE_H
+#define AVCODEC_TIMECODE_H
+
+/**
+ * Adjust frame number for NTSC drop frame time code
+ * Adjustment is only valid in NTSC 29.97
+ * @param frame_num Actual frame number to adjust
+ * @return Adjusted frame number
+ */
+int ff_framenum_to_drop_timecode(int frame_num);
+
+#endif /* AVCODEC_TIMECODE_H */
diff -uN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/utils.c ./utils.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/utils.c	2009-12-13 14:15:18.000000000 +0100
+++ ./utils.c	2009-11-15 04:50:19.000000000 +0100
@@ -365,8 +365,10 @@
     }
 
     /* If internal buffer type return the same buffer */
-    if(pic->type == FF_BUFFER_TYPE_INTERNAL)
+    if(pic->type == FF_BUFFER_TYPE_INTERNAL) {
+        pic->reordered_opaque= s->reordered_opaque;
         return 0;
+    }
 
     /*
      * Not internal type and reget_buffer not overridden, emulate cr buffer
@@ -789,6 +791,7 @@
                      avcodec_get_pix_fmt_name(enc->pix_fmt));
         }
         if (enc->width) {
+            int g;
             snprintf(buf + strlen(buf), buf_size - strlen(buf),
                      ", %dx%d",
                      enc->width, enc->height);
@@ -802,12 +805,13 @@
                          enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den,
                          display_aspect_ratio.num, display_aspect_ratio.den);
             }
-            if(av_log_get_level() >= AV_LOG_DEBUG){
-                int g= av_gcd(enc->time_base.num, enc->time_base.den);
-                snprintf(buf + strlen(buf), buf_size - strlen(buf),
-                     ", %d/%d",
-                     enc->time_base.num/g, enc->time_base.den/g);
-            }
+            g= av_gcd(enc->time_base.num, enc->time_base.den);
+            if (enc->time_base.num)
+                snprintf(buf+strlen(buf), buf_size-strlen(buf), ", tbc %d/%d",
+                         enc->ticks_per_frame*enc->time_base.num/g,
+                         enc->time_base.den/g);
+            else
+                snprintf(buf+strlen(buf), buf_size-strlen(buf), ", tbc N/A");
         }
         if (encode) {
             snprintf(buf + strlen(buf), buf_size - strlen(buf),
@@ -975,7 +941,6 @@
     case CODEC_ID_PCM_U16BE:
     case CODEC_ID_PCM_U16LE:
         return 16;
-    case CODEC_ID_PCM_S24DAUD:
     case CODEC_ID_PCM_S24BE:
     case CODEC_ID_PCM_S24LE:
     case CODEC_ID_PCM_U24BE:
Common subdirectories: /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavcodec/x86 and ./x86
-------------- next part --------------
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/allformats.c ./allformats.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/allformats.c	2009-12-13 14:15:18.000000000 +0100
+++ ./allformats.c	2009-11-15 04:50:20.000000000 +0100
@@ -69,7 +69,7 @@
     REGISTER_DEMUXER  (CAF, caf);
     REGISTER_DEMUXER  (CAVSVIDEO, cavsvideo);
     REGISTER_MUXER    (CRC, crc);
-    REGISTER_MUXDEMUX (DAUD, daud);
+    REGISTER_DEMUXER  (S302M, s302m);
     REGISTER_MUXDEMUX (DIRAC, dirac);
     REGISTER_MUXDEMUX (DNXHD, dnxhd);
     REGISTER_DEMUXER  (DSICIN, dsicin);
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/avformat.h ./avformat.h
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/avformat.h	2009-12-13 14:15:18.000000000 +0100
+++ ./avformat.h	2009-11-15 04:50:20.000000000 +0100
@@ -69,25 +69,65 @@
  *    A demuxer should set a default if it sets any translated tag.
  */
 
-#define AV_METADATA_MATCH_CASE      1
-#define AV_METADATA_IGNORE_SUFFIX   2
+#define AV_METADATA_MATCH_CASE      0x0001
+#define AV_METADATA_NONCONST_KEY    0x0002  ///< used with av_metadata_set
+#define AV_METADATA_NONCONST_VALUE  0x0004  ///< used with av_metadata_set
+#define AV_METADATA_REPLACE         0x0008  ///< replace current metadata
+
+/**
+ * Used attributes: "language", "mime"
+ */
+typedef struct {
+    char *key;
+    char *value;
+} AVMetadataAttribute;
+
+typedef struct {
+    unsigned count;
+    AVMetadataAttribute *elems;
+} AVMetadataAttributes;
+
+enum AVMetadataType {
+    METADATA_STRING, ///< UTF-8
+    METADATA_INT,
+    METADATA_DOUBLE,
+    METADATA_BYTEARRAY,
+};
 
 typedef struct {
     char *key;
     char *value;
+    enum AVMetadataType type;
+    unsigned len;
+    AVMetadataAttributes *attributes;
 }AVMetadataTag;
 
 typedef struct AVMetadata AVMetadata;
 typedef struct AVMetadataConv AVMetadataConv;
 
 /**
  * Gets a metadata element with matching key.
- * @param prev Set to the previous matching element to find the next.
  * @param flags Allows case as well as suffix-insensitive comparisons.
  * @return Found tag or NULL, changing key or value leads to undefined behavior.
  */
 AVMetadataTag *
-av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags);
+av_metadata_get(AVMetadata *m, const char *key, int flags);
+
+/**
+ * Sets the given tag in m
+ * @param type tag type
+ * @param key tag key to add to m (will be av_strduped unless NONCONST flag is set)
+ * @param value tag value to add to m (will be av_strduped unless NONCONST flag is set)
+ * @param value tag value len
+ * @param flags flags regarding key and value parameters
+ * @return >= 0 on success otherwise an error code <0
+ */
+int av_metadata_set_custom(AVMetadata **m, enum AVMetadataType type, const char *key,
+                           const char *value, unsigned len, int flags);
 
 /**
  * Sets the given tag in m, overwriting an existing tag.
@@ -98,19 +138,46 @@
 int av_metadata_set(AVMetadata **pm, const char *key, const char *value);
 
 /**
- * Converts all the metadata sets from ctx according to the source and
- * destination conversion tables.
- * @param d_conv destination tags format conversion table
- * @param s_conv source tags format conversion table
+ * Sets the given string tag in m
+ * @param key tag key to add to m (will be av_strduped unless NONCONST flag is set)
+ * @param value tag value to add to m (will be av_strduped unless NONCONST flag is set)
+ * @param flags flags regarding key and value parameters
+ * @return >= 0 on success otherwise an error code <0
+ */
+int av_metadata_set_string(AVMetadata **m, const char *key, const char *value, int flags);
+int av_metadata_set_int(AVMetadata **pm, const char *key, int value);
+int av_metadata_set_double(AVMetadata **pm, const char *key, double value);
+
+/**
+ * Gets attribute of the given metadata with matching key.
+ * @return Found tag or NULL, changing key or value leads to undefined behavior.
  */
-void av_metadata_conv(struct AVFormatContext *ctx,const AVMetadataConv *d_conv,
-                                                  const AVMetadataConv *s_conv);
+const char *av_metadata_get_attribute(AVMetadataTag *tag, const char *key);
+
+/**
+ * Sets attribute to the given tag
+ * @param key attribute key to add to tag (will be av_strduped)
+ * @param value attribute value to add to tag (will be av_strduped)
+ * @return >= 0 on success otherwise an error code <0
+ */
+int av_metadata_set_attribute(AVMetadataTag *tag, const char *key, const char *value);
 
 /**
  * Frees all the memory allocated for an AVMetadata struct.
  */
 void av_metadata_free(AVMetadata **m);
 
+/**
+ * Convert metadata according to conversions given, during the process,
+ * attributes are kept.
+ * @param in metadata to convert
+ * @param out metadata output
+ * @param d_conv conversion to apply before setting metadata in out
+ * @param s_conv conversion to apply after reading metadata from in
+ */
+void av_metadata_conv_generic(AVMetadata **out, AVMetadata *in,
+                              const AVMetadataConv *d_conv,
+                              const AVMetadataConv *s_conv);
 
 /* packet functions */
 
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/dvenc.c ./dvenc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/dvenc.c	2009-12-13 14:13:21.000000000 +0100
+++ ./dvenc.c	2009-11-15 04:50:20.000000000 +0100
@@ -71,35 +71,10 @@
 {
     struct tm tc;
     time_t ct;
-    int ltc_frame;
     va_list ap;
 
     buf[0] = (uint8_t)pack_id;
     switch (pack_id) {
-    case dv_timecode:
-        ct = (time_t)av_rescale_rnd(c->frames, c->sys->time_base.num,
-                                    c->sys->time_base.den, AV_ROUND_DOWN);
-        brktimegm(ct, &tc);
-        /*
-         * LTC drop-frame frame counter drops two frames (0 and 1) every
-         * minute, unless it is exactly divisible by 10
-         */
-        ltc_frame = (c->frames + 2 * ct / 60 - 2 * ct / 600) % c->sys->ltc_divisor;
-        buf[1] = (0                 << 7) | /* color frame: 0 - unsync; 1 - sync mode */
-                 (1                 << 6) | /* drop frame timecode: 0 - nondrop; 1 - drop */
-                 ((ltc_frame / 10)  << 4) | /* tens of frames */
-                 (ltc_frame % 10);          /* units of frames */
-        buf[2] = (1                 << 7) | /* biphase mark polarity correction: 0 - even; 1 - odd */
-                 ((tc.tm_sec / 10)  << 4) | /* tens of seconds */
-                 (tc.tm_sec % 10);          /* units of seconds */
-        buf[3] = (1                 << 7) | /* binary group flag BGF0 */
-                 ((tc.tm_min / 10)  << 4) | /* tens of minutes */
-                 (tc.tm_min % 10);          /* units of minutes */
-        buf[4] = (1                 << 7) | /* binary group flag BGF2 */
-                 (1                 << 6) | /* binary group flag BGF1 */
-                 ((tc.tm_hour / 10) << 4) | /* tens of hours */
-                 (tc.tm_hour % 10);         /* units of hours */
-        break;
     case dv_audio_source:  /* AAUX source pack */
         va_start(ap, buf);
         buf[1] = (1 << 7) | /* locked mode -- SMPTE only supports locked mode */
@@ -199,15 +174,12 @@
 
 static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame)
 {
-    int j, k;
+    int j;
     uint8_t* buf;
 
     for (buf = frame; buf < frame + c->sys->frame_size; buf += 150 * 80) {
         /* DV subcode: 2nd and 3d DIFs */
         for (j = 80; j < 80 * 3; j += 80) {
-            for (k = 6; k < 6 * 8; k += 8)
-                dv_write_pack(dv_timecode, c, &buf[j+k]);
-
             if (((long)(buf-frame)/(c->sys->frame_size/(c->sys->difseg_size*c->sys->n_difchan))%c->sys->difseg_size) > 5) { /* FIXME: is this really needed ? */
                 dv_write_pack(dv_video_recdate, c, &buf[j+14]);
                 dv_write_pack(dv_video_rectime, c, &buf[j+22]);
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/flvenc.c ./flvenc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/flvenc.c	2009-12-13 14:15:18.000000000 +0100
+++ ./flvenc.c	2009-11-15 04:50:20.000000000 +0100
@@ -166,11 +166,7 @@
     for(i=0; i<s->nb_streams; i++){
         AVCodecContext *enc = s->streams[i]->codec;
         if (enc->codec_type == CODEC_TYPE_VIDEO) {
-            if (s->streams[i]->r_frame_rate.den && s->streams[i]->r_frame_rate.num) {
-                framerate = av_q2d(s->streams[i]->r_frame_rate);
-            } else {
-                framerate = 1/av_q2d(s->streams[i]->codec->time_base);
-            }
+            framerate = 1/av_q2d(s->streams[i]->codec->time_base);
             video_enc = enc;
             if(enc->codec_tag == 0) {
                 av_log(enc, AV_LOG_ERROR, "video codec not compatible with flv\n");
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/gxf.c ./gxf.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/gxf.c	2009-12-13 14:13:21.000000000 +0100
+++ ./gxf.c	2009-11-15 04:50:20.000000000 +0100
@@ -464,7 +464,7 @@
         if (skip)
             url_fskip(pb, skip);
         pkt->stream_index = stream_index;
-        pkt->dts = field_nr;
+        pkt->dts = field_nr*st->time_base.num;
         return ret;
     }
     return AVERROR(EIO);
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/img2.c ./img2.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/img2.c	2009-12-13 14:15:18.000000000 +0100
+++ ./img2.c	2009-11-15 04:50:20.000000000 +0100
@@ -216,6 +216,9 @@
         av_set_pts_info(st, 60, ap->time_base.num, ap->time_base.den);
     }
 
+    st->r_frame_rate.num = st->time_base.den;
+    st->r_frame_rate.den = st->time_base.num;
+
     if(ap->width && ap->height){
         st->codec->width = ap->width;
         st->codec->height= ap->height;
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/isom.h ./isom.h
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/isom.h	2009-12-13 14:13:21.000000000 +0100
+++ ./isom.h	2009-11-15 04:50:20.000000000 +0100
@@ -139,6 +139,9 @@
     MOVTrackExt *trex_data;
     unsigned trex_count;
     int itunes_metadata;  ///< metadata are itunes style
+    AVMetadata **metadata;///< current metadata context (track or global)
+    char **keys_data;     ///< metadata keys
+    unsigned keys_count;  ///< metadata keys
 } MOVContext;
 
 int ff_mp4_read_descr_len(ByteIOContext *pb);
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/Makefile ./Makefile
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/Makefile	2009-12-13 14:15:18.000000000 +0100
+++ ./Makefile	2009-11-15 04:50:20.000000000 +0100
@@ -45,8 +44,7 @@
 OBJS-$(CONFIG_CAF_DEMUXER)               += cafdec.o caf.o mov.o riff.o isom.o
 OBJS-$(CONFIG_CAVSVIDEO_DEMUXER)         += raw.o
 OBJS-$(CONFIG_CRC_MUXER)                 += crcenc.o
-OBJS-$(CONFIG_DAUD_DEMUXER)              += daud.o
-OBJS-$(CONFIG_DAUD_MUXER)                += daud.o
+OBJS-$(CONFIG_S302M_DEMUXER)             += s302m.o
 OBJS-$(CONFIG_DIRAC_DEMUXER)             += raw.o
 OBJS-$(CONFIG_DIRAC_MUXER)               += raw.o
 OBJS-$(CONFIG_DNXHD_DEMUXER)             += raw.o
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/matroska.c ./matroska.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/matroska.c	2009-12-13 14:13:21.000000000 +0100
+++ ./matroska.c	2009-11-15 04:50:20.000000000 +0100
@@ -79,18 +79,6 @@
     {""                 , CODEC_ID_NONE}
 };
 
-const CodecMime ff_mkv_mime_tags[] = {
-    {"text/plain"                 , CODEC_ID_TEXT},
-    {"image/gif"                  , CODEC_ID_GIF},
-    {"image/jpeg"                 , CODEC_ID_MJPEG},
-    {"image/png"                  , CODEC_ID_PNG},
-    {"image/tiff"                 , CODEC_ID_TIFF},
-    {"application/x-truetype-font", CODEC_ID_TTF},
-    {"application/x-font"         , CODEC_ID_TTF},
-
-    {""                           , CODEC_ID_NONE}
-};
-
 const AVMetadataConv ff_mkv_metadata_conv[] = {
     { "ARTIST"        , "artist" },
     { "LEAD_PERFORMER", "artist" },
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/matroskadec.c ./matroskadec.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/matroskadec.c	2009-12-13 14:13:21.000000000 +0100
+++ ./matroskadec.c	2009-11-15 04:50:20.000000000 +0100
@@ -151,7 +151,7 @@
     char *mime;
     EbmlBin bin;
 
-    AVStream *stream;
+    AVMetadataTag *tag;
 } MatroskaAttachement;
 
 typedef struct {
@@ -987,28 +987,24 @@
 }
 
 static void matroska_convert_tag(AVFormatContext *s, EbmlList *list,
-                                 AVMetadata **metadata, char *prefix)
+                                 AVMetadata **metadata)
 {
     MatroskaTag *tags = list->elem;
-    char key[1024];
     int i;
 
     for (i=0; i < list->nb_elem; i++) {
-        const char *lang = strcmp(tags[i].lang, "und") ? tags[i].lang : NULL;
-        if (prefix)  snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name);
-        else         av_strlcpy(key, tags[i].name, sizeof(key));
-        if (tags[i].def || !lang) {
-        av_metadata_set(metadata, key, tags[i].string);
+        AVMetadataTag *tag;
+        if (av_metadata_set_string(metadata, tags[i].name, tags[i].string,
+                                   AV_METADATA_NONCONST_VALUE |
+                                   AV_METADATA_NONCONST_KEY) < 0)
+            return;
+        tags[i].name = NULL;
+        tags[i].string = NULL;
+        tag = &(*metadata)->elems[(*metadata)->count-1];
+        if (strcmp(tags[i].lang, "und"))
+            av_metadata_set_attribute(tag, "language", tags[i].lang);
         if (tags[i].sub.nb_elem)
-            matroska_convert_tag(s, &tags[i].sub, metadata, key);
-        }
-        if (lang) {
-            av_strlcat(key, "-", sizeof(key));
-            av_strlcat(key, lang, sizeof(key));
-            av_metadata_set(metadata, key, tags[i].string);
-            if (tags[i].sub.nb_elem)
-                matroska_convert_tag(s, &tags[i].sub, metadata, key);
-        }
+            av_log(s, AV_LOG_WARNING, "sub elements in tag\n");
     }
 }
 
@@ -1020,26 +1016,22 @@
 
     for (i=0; i < matroska->tags.nb_elem; i++) {
         if (tags[i].target.attachuid) {
-            MatroskaAttachement *attachment = matroska->attachments.elem;
-            for (j=0; j<matroska->attachments.nb_elem; j++)
-                if (attachment[j].uid == tags[i].target.attachuid)
-                    matroska_convert_tag(s, &tags[i].tag,
-                                         &attachment[j].stream->metadata, NULL);
+            if (matroska->attachments.nb_elem > 0)
+                av_log(s, AV_LOG_WARNING, "attachment has tags\n");
         } else if (tags[i].target.chapteruid) {
             MatroskaChapter *chapter = matroska->chapters.elem;
             for (j=0; j<matroska->chapters.nb_elem; j++)
                 if (chapter[j].uid == tags[i].target.chapteruid)
                     matroska_convert_tag(s, &tags[i].tag,
-                                         &chapter[j].chapter->metadata, NULL);
+                                         &chapter[j].chapter->metadata);
         } else if (tags[i].target.trackuid) {
             MatroskaTrack *track = matroska->tracks.elem;
             for (j=0; j<matroska->tracks.nb_elem; j++)
                 if (track[j].uid == tags[i].target.trackuid)
                     matroska_convert_tag(s, &tags[i].tag,
-                                         &track[j].stream->metadata, NULL);
+                                         &track[j].stream->metadata);
         } else {
-            matroska_convert_tag(s, &tags[i].tag, &s->metadata,
-                                 tags[i].target.type);
+            matroska_convert_tag(s, &tags[i].tag, &s->metadata);
         }
     }
 }
@@ -1341,16 +1333,12 @@
 
         if (track->flag_default)
             st->disposition |= AV_DISPOSITION_DEFAULT;
 
-        if (track->default_duration)
-            av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
-                      track->default_duration, 1000000000, 30000);
-
         if (!st->codec->extradata) {
             if(extradata){
                 st->codec->extradata = extradata;
@@ -1379,6 +1367,8 @@
                       255);
             if (st->codec->codec_id != CODEC_ID_H264)
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
+            if (track->default_duration > 0)
+                st->r_frame_rate = av_d2q(1000000000/(double)track->default_duration, INT_MAX);
         } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) {
             st->codec->codec_type = CODEC_TYPE_AUDIO;
             st->codec->sample_rate = track->audio.out_samplerate;
@@ -1394,26 +1384,14 @@
               attachements[j].bin.data && attachements[j].bin.size > 0)) {
             av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n");
         } else {
-            AVStream *st = av_new_stream(s, 0);
-            if (st == NULL)
+            if (av_metadata_set_custom(&s->metadata, METADATA_BYTEARRAY,
+                                       attachements[j].filename,
+                                       attachements[j].bin.data, attachements[j].bin.size,
+                                       AV_METADATA_NONCONST_VALUE) < 0)
                 break;
-            av_metadata_set(&st->metadata, "filename",attachements[j].filename);
-            st->codec->codec_id = CODEC_ID_NONE;
-            st->codec->codec_type = CODEC_TYPE_ATTACHMENT;
-            st->codec->extradata  = av_malloc(attachements[j].bin.size);
-            if(st->codec->extradata == NULL)
-                break;
-            st->codec->extradata_size = attachements[j].bin.size;
-            memcpy(st->codec->extradata, attachements[j].bin.data, attachements[j].bin.size);
-
-            for (i=0; ff_mkv_mime_tags[i].id != CODEC_ID_NONE; i++) {
-                if (!strncmp(ff_mkv_mime_tags[i].str, attachements[j].mime,
-                             strlen(ff_mkv_mime_tags[i].str))) {
-                    st->codec->codec_id = ff_mkv_mime_tags[i].id;
-                    break;
-                }
-            }
-            attachements[j].stream = st;
+            attachements[j].tag = &s->metadata->elems[s->metadata->count-1];
+            attachements[j].bin.data = NULL;
+            av_metadata_set_attribute(attachements[j].tag, "mime", attachements[j].mime);
         }
     }
 
@@ -1425,8 +1403,7 @@
             ff_new_chapter(s, chapters[i].uid, (AVRational){1, 1000000000},
                            chapters[i].start, chapters[i].end,
                            chapters[i].title);
-            av_metadata_set(&chapters[i].chapter->metadata,
-                            "title", chapters[i].title);
+            av_metadata_set(&chapters[i].chapter->metadata, "title", chapters[i].title);
             max_start = chapters[i].start;
         }
 
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/metadata.c ./metadata.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/metadata.c	2009-12-13 14:13:21.000000000 +0100
+++ ./metadata.c	2009-11-15 04:50:20.000000000 +0100
@@ -18,121 +18,236 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <strings.h>
 #include "avformat.h"
 #include "metadata.h"
 
 AVMetadataTag *
-av_metadata_get(AVMetadata *m, const char *key, const AVMetadataTag *prev, int flags)
+av_metadata_get(AVMetadata *m, const char *key, int flags)
 {
     unsigned int i, j;
 
     if(!m)
         return NULL;
 
-    if(prev) i= prev - m->elems + 1;
-    else     i= 0;
-
-    for(; i<m->count; i++){
-        const char *s= m->elems[i].key;
+    for(i=0; i<m->count; i++){
+        char *s= m->elems[i].key;
         if(flags & AV_METADATA_MATCH_CASE) for(j=0;         s[j]  ==         key[j]  && key[j]; j++);
         else                               for(j=0; toupper(s[j]) == toupper(key[j]) && key[j]; j++);
         if(key[j])
             continue;
-        if(s[j] && !(flags & AV_METADATA_IGNORE_SUFFIX))
-            continue;
         return &m->elems[i];
     }
     return NULL;
 }
 
-int av_metadata_set(AVMetadata **pm, const char *key, const char *value)
+static void av_metadata_free_tag(AVMetadataTag *tag)
+{
+    av_freep(&tag->key);
+    av_freep(&tag->value);
+    while (tag->attributes && tag->attributes->count--) {
+        av_freep(&tag->attributes->elems
+                 [tag->attributes->count].key);
+        av_freep(&tag->attributes->elems
+                 [tag->attributes->count].value);
+    }
+    av_freep(&tag->attributes);
+}
+
+int av_metadata_set_custom(AVMetadata **pm, enum AVMetadataType type,
+                           const char *key, const char *value, unsigned len,
+                           int flags)
 {
     AVMetadata *m= *pm;
-    AVMetadataTag *tag= av_metadata_get(m, key, NULL, AV_METADATA_MATCH_CASE);
+    AVMetadataTag *tag;
+
+    if(!key || !pm || !len || !value)
+        return -1;
 
     if(!m)
         m=*pm= av_mallocz(sizeof(*m));
+    if(!m)
+        return AVERROR_NOMEM;
 
-    if(tag){
-        av_free(tag->value);
-        av_free(tag->key);
-        *tag= m->elems[--m->count];
-    }else{
-        AVMetadataTag *tmp= av_realloc(m->elems, (m->count+1) * sizeof(*m->elems));
-        if(tmp){
-            m->elems= tmp;
-        }else
-            return AVERROR(ENOMEM);
-    }
-    if(value){
-        m->elems[m->count].key  = av_strdup(key  );
-        m->elems[m->count].value= av_strdup(value);
-        m->count++;
-    }
-    if(!m->count) {
-        av_free(m->elems);
-        av_freep(pm);
-    }
+    if (flags & AV_METADATA_REPLACE) {
+        tag = av_metadata_get(m, key, flags);
+        if (!tag)
+            goto alloc;
+        av_metadata_free_tag(tag);
+    } else {
+    alloc:
+        if(m->count >= UINT_MAX / sizeof(*m->elems))
+            return -1;
+        tag = av_realloc(m->elems, (m->count+1)*sizeof(*m->elems));
+        if(!tag)
+            return AVERROR_NOMEM;
+        m->elems = tag;
+        tag = &m->elems[m->count++];
+    }
+
+    if (flags & AV_METADATA_NONCONST_KEY)
+        tag->key  = key;
+    else
+        tag->key  = av_strdup(key);
+
+    if (flags & AV_METADATA_NONCONST_VALUE) {
+        tag->value = value;
+    } else if (type == METADATA_BYTEARRAY) {
+        tag->value = av_malloc(len);
+        if (!tag->value)
+            return AVERROR_NOMEM;
+        memcpy(tag->value, value, len);
+    } else {
+        tag->value = av_malloc(len+1);
+        if (!tag->value)
+            return AVERROR_NOMEM;
+        memcpy(tag->value, value, len);
+        tag->value[len] = 0;
+    }
+
+    tag->len = len;
+    tag->type = type;
+    tag->attributes = NULL;
 
     return 0;
 }
 
-void av_metadata_free(AVMetadata **pm)
+int av_metadata_set_string(AVMetadata **pm, const char *key,
+                           const char *value, int flags)
 {
-    AVMetadata *m= *pm;
+    if (!value)
+        return -1;
+    return av_metadata_set_custom(pm, METADATA_STRING, key,
+                                  value, strlen(value), flags);
+}
 
-    if(m){
-        while(m->count--){
-            av_free(m->elems[m->count].key);
-            av_free(m->elems[m->count].value);
-        }
-        av_free(m->elems);
+int av_metadata_set_int(AVMetadata **pm, const char *key, int value)
+{
+    char buf[16];
+    int len = snprintf(buf, sizeof(buf), "%d", value);
+    return av_metadata_set_custom(pm, METADATA_INT, key, buf, len, 0);
+}
+
+int av_metadata_set_double(AVMetadata **pm, const char *key, double value)
+{
+    char buf[16];
+    int len = snprintf(buf, sizeof(buf), "%f", value);
+    return av_metadata_set_custom(pm, METADATA_DOUBLE, key, buf, len, 0);
+}
+
+int av_metadata_set(AVMetadata **pm, const char *key, const char *value)
+{
+    return av_metadata_set_string(pm, key, value, 0);
+}
+
+const char *av_metadata_get_attribute(AVMetadataTag *tag, const char *key)
+{
+    int i, j;
+
+    if (!tag->attributes)
+        return NULL;
+
+    for (i = 0; i < tag->attributes->count; i++) {
+        char *s = tag->attributes->elems[i].key;
+        for (j = 0; toupper(s[j]) == toupper(key[j]) && key[j]; j++)
+            ;
+        if (key[j])
+            continue;
+        return tag->attributes->elems[i].value;
     }
-    av_freep(pm);
+    return NULL;
+}
+
+int av_metadata_set_attribute(AVMetadataTag *tag, const char *key, const char *value)
+{
+    AVMetadataAttribute *attribute;
+
+    if (!tag->attributes)
+        tag->attributes = av_mallocz(sizeof(*tag->attributes));
+    if (!tag->attributes)
+        return AVERROR_NOMEM;
+
+    if (tag->attributes->count == UINT_MAX / sizeof(*attribute))
+        return -1;
+
+    attribute = av_realloc(tag->attributes->elems,
+                           (tag->attributes->count+1)*sizeof(*attribute));
+    if (!attribute)
+        return AVERROR_NOMEM;
+
+    tag->attributes->elems = attribute;
+    attribute = &tag->attributes->elems[tag->attributes->count];
+    attribute->key = av_strdup(key);
+    attribute->value = av_strdup(value);
+
+    tag->attributes->count++;
+
+    return 0;
 }
 
-static void metadata_conv(AVMetadata **pm, const AVMetadataConv *d_conv,
-                                           const AVMetadataConv *s_conv)
+int av_metadata_copy_attributes(AVMetadataTag *otag, AVMetadataTag *itag)
+{
+    if (!itag->attributes)
+        return 0;
+
+    otag->attributes = av_mallocz(sizeof(*itag->attributes));
+    if (!otag->attributes)
+        return AVERROR_NOMEM;
+    otag->attributes->elems = av_malloc(itag->attributes->count *
+                                        sizeof(*itag->attributes->elems));
+    if (!otag->attributes->elems)
+        return AVERROR_NOMEM;
+
+    memcpy(otag->attributes->elems, itag->attributes->elems,
+           itag->attributes->count*sizeof(*itag->attributes->elems));
+    otag->attributes->count = itag->attributes->count;
+
+    return 0;
+}
+
+void av_metadata_conv_generic(AVMetadata **out, AVMetadata *in,
+                              const AVMetadataConv *d_conv,
+                              const AVMetadataConv *s_conv)
 {
     /* TODO: use binary search to look up the two conversion tables
        if the tables are getting big enough that it would matter speed wise */
     const AVMetadataConv *sc, *dc;
     AVMetadataTag *mtag = NULL;
-    AVMetadata *dst = NULL;
     const char *key;
+    int i;
 
-    while((mtag=av_metadata_get(*pm, "", mtag, AV_METADATA_IGNORE_SUFFIX))) {
+    if (!out || !in)
+        return;
+
+    for (i = 0; i < in->count; i++) {
+        mtag = &in->elems[i];
         key = mtag->key;
-        if (s_conv != d_conv) {
             if (s_conv)
                 for (sc=s_conv; sc->native; sc++)
                     if (!strcasecmp(key, sc->native)) {
                         key = sc->generic;
                         break;
                     }
             if (d_conv)
                 for (dc=d_conv; dc->native; dc++)
                     if (!strcasecmp(key, dc->generic)) {
                         key = dc->native;
                         break;
                     }
-        }
-        av_metadata_set(&dst, key, mtag->value);
+        av_metadata_set_custom(out, mtag->type, key, mtag->value, mtag->len, 0);
+        av_metadata_copy_attributes(&(*out)->elems[(*out)->count-1], mtag);
     }
-    av_metadata_free(pm);
-    *pm = dst;
 }
 
-void av_metadata_conv(AVFormatContext *ctx, const AVMetadataConv *d_conv,
-                                            const AVMetadataConv *s_conv)
+void av_metadata_free(AVMetadata **pm)
 {
-    int i;
-    metadata_conv(&ctx->metadata, d_conv, s_conv);
-    for (i=0; i<ctx->nb_streams ; i++)
-        metadata_conv(&ctx->streams [i]->metadata, d_conv, s_conv);
-    for (i=0; i<ctx->nb_chapters; i++)
-        metadata_conv(&ctx->chapters[i]->metadata, d_conv, s_conv);
-    for (i=0; i<ctx->nb_programs; i++)
-        metadata_conv(&ctx->programs[i]->metadata, d_conv, s_conv);
+    AVMetadata *m= *pm;
+
+    if(m){
+        while(m->count--)
+            av_metadata_free_tag(&m->elems[m->count]);
+        av_freep(&m->elems);
+    }
+    av_freep(pm);
 }
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mov.c ./mov.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mov.c	2009-12-13 14:15:18.000000000 +0100
+++ ./mov.c	2009-11-15 04:50:20.000000000 +0100
@@ -31,6 +30,7 @@
 #include "avformat.h"
 #include "riff.h"
 #include "isom.h"
+#include "id3v1.h"
 #include "libavcodec/mpeg4audio.h"
 #include "libavcodec/mpegaudiodata.h"
 #include "libavcodec/get_bits.h"
@@ -80,92 +80,194 @@
 
 static const MOVParseTableEntry mov_default_parse_table[];
 
+static int mov_metadata_gnre(MOVContext *c, ByteIOContext *pb, unsigned len)
+{
+    uint16_t genre = get_be16(pb);
+    if (genre-1 < ID3v1_GENRE_MAX)
+        av_metadata_set(c->metadata, "genre", ff_id3v1_genre_str[genre-1]);
+
+    return 0;
+}
+
 static int mov_metadata_trkn(MOVContext *c, ByteIOContext *pb, unsigned len)
 {
     char buf[16];
-
+    int track, track_count;
     get_be16(pb); // unknown
-    snprintf(buf, sizeof(buf), "%d", get_be16(pb));
-    av_metadata_set(&c->fc->metadata, "track", buf);
+    track = get_be16(pb);
+    track_count = get_be16(pb);
+    snprintf(buf, sizeof(buf), "%d/%d", track, track_count);
+    av_metadata_set(c->metadata, "track", buf);
+
+    return 0;
+}
+
+static int mov_read_keys(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+{
+    unsigned int i, entries;
+
+    get_be32(pb); // version+flags
+
+    entries = get_be32(pb);
+    if (entries >= UINT_MAX/sizeof(*c->keys_data))
+        return -1;
 
-    get_be16(pb); // total tracks
+    for (i = 0; i < c->keys_count; i++)
+        av_freep(&c->keys_data[i]);
+    av_freep(&c->keys_data);
+
+    c->keys_data = av_malloc(entries*sizeof(*c->keys_data));
+    if (!c->keys_data)
+        return AVERROR_NOMEM;
+    c->keys_count = entries;
+
+    for (i = 0; i < entries; i++) {
+        uint32_t size = get_be32(pb);
+        url_fskip(pb, 4); // 'mdta'
+        if (size > atom.size || size < 8)
+            return -1;
+        size -= 8;
+        c->keys_data[i] = av_malloc(size+1);
+        if (!c->keys_data[i])
+            return AVERROR_NOMEM;
+        get_buffer(pb, c->keys_data[i], size);
+        c->keys_data[i][size] = 0;
+    }
 
     return 0;
 }
 
-static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+static const struct {
+    uint32_t tag;
+    const char *key;
+    int (*parse)(MOVContext*, ByteIOContext*, unsigned);
+} udta_parse_table[] = {
+    { MKTAG( 'a','A','R','T'), "album artist" },
+    { MKTAG( 'c','p','r','t'), "copyright" },
+    { MKTAG( 'g','n','r','e'), "genre", mov_metadata_gnre },
+    { MKTAG( 't','r','k','n'), "track", mov_metadata_trkn },
+    { MKTAG(0xa9,'A','R','T'), "artist" },
+    { MKTAG(0xa9,'a','l','b'), "album" },
+    { MKTAG(0xa9,'a','u','t'), "author" },
+    { MKTAG(0xa9,'c','m','t'), "comment" },
+    { MKTAG(0xa9,'c','p','y'), "copyright" },
+    { MKTAG(0xa9,'d','a','y'), "year" },
+    { MKTAG(0xa9,'e','n','c'), "encoder" },
+    { MKTAG(0xa9,'g','e','n'), "genre" },
+    { MKTAG(0xa9,'i','n','f'), "comment" },
+    { MKTAG(0xa9,'n','a','m'), "title" },
+    { MKTAG(0xa9,'t','o','o'), "encoder" },
+    { MKTAG(0xa9,'w','r','t'), "composer" },
+    { 0 },
+};
+
+static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
 {
-#ifdef MOV_EXPORT_ALL_METADATA
-    char tmp_key[5];
-#endif
-    char str[1024], key2[16], language[4] = {0};
+    enum AVMetadataType type;
+    char language[4] = {0};
     const char *key = NULL;
-    uint16_t str_size;
+    unsigned i, size;
     int (*parse)(MOVContext*, ByteIOContext*, unsigned) = NULL;
 
-    switch (atom.type) {
-    case MKTAG(0xa9,'n','a','m'): key = "title";     break;
-    case MKTAG(0xa9,'a','u','t'):
-    case MKTAG(0xa9,'A','R','T'): key = "author";    break;
-    case MKTAG(0xa9,'w','r','t'): key = "composer";  break;
-    case MKTAG(0xa9,'c','p','y'): key = "copyright"; break;
-    case MKTAG(0xa9,'c','m','t'):
-    case MKTAG(0xa9,'i','n','f'): key = "comment";   break;
-    case MKTAG(0xa9,'a','l','b'): key = "album";     break;
-    case MKTAG(0xa9,'d','a','y'): key = "year";      break;
-    case MKTAG(0xa9,'g','e','n'): key = "genre";     break;
-    case MKTAG(0xa9,'t','o','o'):
-    case MKTAG(0xa9,'e','n','c'): key = "encoder";   break;
-    case MKTAG( 't','r','k','n'): key = "track";
-        parse = mov_metadata_trkn; break;
+    for (i = 0; i < FF_ARRAY_ELEMS(udta_parse_table); i++) {
+        if (udta_parse_table[i].tag == atom.type) {
+            key = udta_parse_table[i].key;
+            parse = udta_parse_table[i].parse;
+            break;
+        }
     }
 
     if (c->itunes_metadata && atom.size > 8) {
         int data_size = get_be32(pb);
         int tag = get_le32(pb);
         if (tag == MKTAG('d','a','t','a')) {
-            get_be32(pb); // type
+            int datatype = get_be32(pb); // type
+            dprintf(c->fc, "data type: %d\n", datatype);
+            switch (datatype) {
+            case  1:  type = METADATA_STRING; break;
+            case 21:  type = METADATA_INT; break;
+            case 23:  type = METADATA_INT; break;
+            default:
+                dprintf(c->fc, "unsupported data type\n");
+                type = METADATA_BYTEARRAY;
+                break;
+            }
             get_be32(pb); // unknown
-            str_size = data_size - 16;
+            size = data_size - 16;
             atom.size -= 16;
         } else return 0;
-    } else if (atom.size > 4 && key && !c->itunes_metadata) {
-        str_size = get_be16(pb); // string length
-        ff_mov_lang_to_iso639(get_be16(pb), language);
+    } else if (!c->itunes_metadata && atom.size > 4) {
+        size = get_be16(pb); // string length
+        if (!ff_mov_lang_to_iso639(get_be16(pb), language) ||
+            size > atom.size) {
+            language[0] = 0;
+            url_fseek(pb, -4, SEEK_CUR);
+            goto unrecognized;
+        }
         atom.size -= 4;
-    } else
-        str_size = atom.size;
+        type = METADATA_STRING;
+    } else {
+    unrecognized:
+        size = atom.size;
+        type = METADATA_BYTEARRAY;
+    }
 
-#ifdef MOV_EXPORT_ALL_METADATA
     if (!key) {
-        snprintf(tmp_key, 5, "%.4s", (char*)&atom.type);
-        key = tmp_key;
-    }
+        unsigned tagbe = AV_RB32(&atom.type)-1;
+        if (tagbe < c->keys_count) {
+            key = c->keys_data[tagbe];
+        } else {
+#ifdef MOV_EXPORT_ALL_METADATA
+            char keybuf[5];
+            AV_WL32(keybuf, atom.type);
+            keybuf[4] = 0;
+            key = keybuf;
 #endif
+        }
+    }
 
     if (!key)
         return 0;
     if (atom.size < 0)
         return -1;
 
-    str_size = FFMIN3(sizeof(str)-1, str_size, atom.size);
+    size = FFMIN(size, atom.size);
 
-    if (parse)
-        parse(c, pb, str_size);
-    else {
-        get_buffer(pb, str, str_size);
-        str[str_size] = 0;
-        av_metadata_set(&c->fc->metadata, key, str);
-        if (*language && strcmp(language, "und")) {
-            snprintf(key2, sizeof(key2), "%s-%s", key, language);
-            av_metadata_set(&c->fc->metadata, key2, str);
-        }
-    }
-#ifdef DEBUG_METADATA
-    av_log(c->fc, AV_LOG_DEBUG, "lang \"%3s\" ", language);
-    av_log(c->fc, AV_LOG_DEBUG, "tag \"%s\" value \"%s\" atom \"%.4s\" %d %lld\n",
-           key, str, (char*)&atom.type, str_size, atom.size);
-#endif
+    if (parse) {
+        parse(c, pb, size);
+    } else if (type == METADATA_INT) {
+        int value;
+        switch (size) {
+        case 4: value = get_be32(pb); break;
+        case 2: value = get_be16(pb); break;
+        case 1: value = get_byte(pb); break;
+        default:
+            dprintf(c->fc, "unsupported int size: %d\n", size);
+            url_fskip(pb, size);
+            value = 0;
+            break;
+        }
+        av_metadata_set_int(c->metadata, key, value);
+    } else {
+        AVMetadataTag *tag = NULL;
+        uint8_t *buf;
+        if (type == METADATA_STRING)
+            buf = av_malloc(size+1);
+        else
+            buf = av_malloc(size);
+        if (!buf)
+            return AVERROR_NOMEM;
+        get_buffer(pb, buf, size);
+        if (type == METADATA_STRING)
+            buf[size] = 0;
+        if (av_metadata_set_custom(c->metadata, type, key, buf, size,
+                                   AV_METADATA_NONCONST_VALUE) < 0)
+            return 0;
+        tag = &(*c->metadata)->elems[(*c->metadata)->count-1];
+
+        if (*language && strcmp(language, "und"))
+            av_metadata_set_attribute(tag, "language", language);
+    }
 
     return 0;
 }
@@ -217,7 +319,7 @@
         // container is user data
         if (!parse && (atom.type == MKTAG('u','d','t','a') ||
                        atom.type == MKTAG('i','l','s','t')))
-            parse = mov_read_udta_string;
+            parse = mov_read_udta;
 
         if (!parse) { /* skip leaf atoms data */
             url_fskip(pb, a.size);
@@ -1488,9 +1590,9 @@
                    sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
                     av_add_index_entry(st, current_offset, current_dts, sample_size, distance,
                                     keyframe ? AVINDEX_KEYFRAME : 0);
-                    dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
-                            "size %d, distance %d, keyframe %d\n", st->index, current_sample,
-                            current_offset, current_dts, sample_size, distance, keyframe);
+                    //dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
+                    //        "size %d, distance %d, keyframe %d\n", st->index, current_sample,
+                    //        current_offset, current_dts, sample_size, distance, keyframe);
                 }
 
                 current_offset += sample_size;
@@ -1530,19 +1632,19 @@
                     size = sc->bytes_per_frame;
                 } else {
                     if (sc->samples_per_frame > 1) {
-                        samples = FFMIN((1024 / sc->samples_per_frame)*
+                        samples = FFMIN((1920 / sc->samples_per_frame)*
                                         sc->samples_per_frame, chunk_samples);
                         size = (samples / sc->samples_per_frame) * sc->bytes_per_frame;
                     } else {
-                        samples = FFMIN(1024, chunk_samples);
+                        samples = FFMIN(1920, chunk_samples);
                         size = samples * sc->sample_size;
                     }
                 }
 
                 av_add_index_entry(st, current_offset, current_dts, size, 0, AVINDEX_KEYFRAME);
-                dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", "
-                        "size %d, duration %d\n", st->index, i, current_offset, current_dts,
-                        size, samples);
+                //dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", "
+                //        "size %d, duration %d\n", st->index, i, current_offset, current_dts,
+                //        size, samples);
 
                 current_offset += size;
                 current_dts += samples;
@@ -1613,8 +1715,10 @@
     st->codec->codec_type = CODEC_TYPE_DATA;
     sc->ffindex = st->index;
 
+    c->metadata = &st->metadata;
     if ((ret = mov_read_default(c, pb, atom)) < 0)
         return ret;
+    c->metadata = &c->fc->metadata;
 
     /* sanity checks */
     if (sc->chunk_count && (!sc->stts_count || !sc->stsc_count ||
@@ -1638,6 +1742,9 @@
         st->codec->frame_size = av_rescale(sc->stts_data[0].duration,
                                            st->codec->sample_rate, sc->time_scale);
         dprintf(c->fc, "frame size %d\n", st->codec->frame_size);
+    } else if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den,
+                  sc->time_scale*st->nb_frames, st->duration, INT_MAX);
     }
 
     mov_build_index(c, st);
@@ -1653,24 +1760,6 @@
     } else
         sc->pb = c->fc->pb;
 
-    switch (st->codec->codec_id) {
-#if CONFIG_H261_DECODER
-    case CODEC_ID_H261:
-#endif
-#if CONFIG_H263_DECODER
-    case CODEC_ID_H263:
-#endif
-#if CONFIG_H264_DECODER
-    case CODEC_ID_H264:
-#endif
-#if CONFIG_MPEG4_DECODER
-    case CODEC_ID_MPEG4:
-#endif
-        st->codec->width = 0; /* let decoder init width/height */
-        st->codec->height= 0;
-        break;
-    }
-
     /* Do not need those anymore. */
     av_freep(&sc->chunk_offsets);
     av_freep(&sc->stsc_data);
@@ -2045,6 +2134,7 @@
 { MKTAG('h','d','l','r'), mov_read_hdlr },
 { MKTAG('i','l','s','t'), mov_read_ilst },
 { MKTAG('j','p','2','h'), mov_read_extradata },
+{ MKTAG('k','e','y','s'), mov_read_keys },
 { MKTAG('m','d','a','t'), mov_read_mdat },
 { MKTAG('m','d','h','d'), mov_read_mdhd },
 { MKTAG('m','d','i','a'), mov_read_default },
@@ -2130,7 +2220,7 @@
 {
     MOVContext *mov = s->priv_data;
     ByteIOContext *pb = s->pb;
-    int err;
+    int i, err;
     MOVAtom atom = { 0, 0, 0 };
 
     mov->fc = s;
@@ -2140,6 +2230,7 @@
     else
         atom.size = INT64_MAX;
 
+    mov->metadata = &s->metadata;
     /* check MOV header */
     if ((err = mov_read_default(mov, pb, atom)) < 0) {
         av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err);
@@ -2151,6 +2242,11 @@
     }
     dprintf(mov->fc, "on_parse_exit_offset=%lld\n", url_ftell(pb));
 
+    for (i = 0; i < mov->keys_count; i++)
+        av_freep(&mov->keys_data[i]);
+    av_freep(&mov->keys_data);
+    mov->keys_count = 0;
+
     return 0;
 }
 
@@ -2165,7 +2261,7 @@
         if (msc->pb && msc->current_sample < avst->nb_index_entries) {
             AVIndexEntry *current_sample = &avst->index_entries[msc->current_sample];
             int64_t dts = av_rescale(current_sample->timestamp, AV_TIME_BASE, msc->time_scale);
-            dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
+            //dprintf(s, "stream %d, sample %d, dts %"PRId64"\n", i, msc->current_sample, dts);
             if (!sample || (url_is_streamed(s->pb) && current_sample->pos < sample->pos) ||
                 (!url_is_streamed(s->pb) &&
                  ((msc->pb != s->pb && dts < best_dts) || (msc->pb == s->pb &&
@@ -2246,8 +2342,8 @@
         goto retry;
     pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
     pkt->pos = sample->pos;
-    dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n",
-            pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
+    //dprintf(s, "stream %d, pts %"PRId64", dts %"PRId64", pos 0x%"PRIx64", duration %d\n",
+    //        pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
     return 0;
 }
 
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/movenc.c ./movenc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/movenc.c	2009-12-13 14:15:18.000000000 +0100
+++ ./movenc.c	2009-11-15 04:50:20.000000000 +0100
@@ -71,12 +71,17 @@
     int         trackID;
     int         tag; ///< stsd fourcc
     AVCodecContext *enc;
-
+    int64_t     first_pts;
+    int         min_cts;
+    int         max_cts;
+    int64_t     pts_duration;
     int         vosLen;
     uint8_t     *vosData;
     MOVIentry   *cluster;
     int         audio_vbr;
     int         height; ///< active picture (w/o VBI) height for D-10/IMX
+    AVRational  dar;    ///< display aspect ratio
+    int         tref;   ///< track referenced by timecode track
 } MOVTrack;
 
 typedef struct MOVMuxContext {
@@ -739,6 +744,60 @@
     return updateSize(pb, pos);
 }
 
+static int mov_write_tapt_tag(ByteIOContext *pb, MOVTrack *track)
+{
+    int display_width;
+
+    display_width = (uint64_t)track->height*track->dar.num/track->dar.den;
+
+    put_be32(pb, 68);
+    put_tag (pb, "tapt");
+    put_be32(pb, 20);
+    put_tag (pb, "clef");
+    put_be32(pb, 0); // version + flags
+    put_be32(pb, display_width<<16);
+    put_be32(pb, track->height<<16);
+    put_be32(pb, 20);
+    put_tag (pb, "prof");
+    put_be32(pb, 0); // version + flags
+    put_be32(pb, display_width<<16);
+    put_be32(pb, track->height<<16);
+    put_be32(pb, 20);
+    put_tag (pb, "enof");
+    put_be32(pb, 0); // version + flags
+    put_be32(pb, track->enc->width<<16);
+    put_be32(pb, track->height    <<16);
+    return 68;
+}
+
+static int mov_write_pasp_tag(ByteIOContext *pb, MOVTrack *track)
+{
+    AVRational sar;
+    av_reduce(&sar.num, &sar.den, track->height*track->dar.num,
+              track->enc->width*track->dar.den, INT_MAX);
+
+    put_be32(pb, 16);
+    put_tag(pb, "pasp");
+    put_be32(pb, sar.num);
+    put_be32(pb, sar.den);
+    return 16;
+}
+
+static int mov_write_clap_tag(ByteIOContext *pb, MOVTrack *track)
+{
+    put_be32(pb, 40);
+    put_tag(pb, "clap");
+    put_be32(pb, track->enc->width);
+    put_be32(pb, 1);
+    put_be32(pb, track->height);
+    put_be32(pb, 1);
+    put_be32(pb, 0);
+    put_be32(pb, 1);
+    put_be32(pb, 0);
+    put_be32(pb, 1);
+    return 40;
+}
+
 static int mov_write_video_tag(ByteIOContext *pb, MOVTrack *track)
 {
     int64_t pos = url_ftell(pb);
@@ -800,9 +859,30 @@
     } else if(track->vosLen > 0)
         mov_write_glbl_tag(pb, track);
 
+    if (track->enc->sample_aspect_ratio.num) {
+        mov_write_pasp_tag(pb, track);
+        mov_write_clap_tag(pb, track);
+    }
+
     return updateSize(pb, pos);
 }
 
+static int mov_write_tmcd_tag(ByteIOContext *pb, MOVTrack* track)
+{
+    put_be32(pb, 36); /* size */
+    put_tag(pb, "tmcd");
+    put_be32(pb, 0); /* reserved */
+    put_be16(pb, 0); /* reserved */
+    put_be16(pb, 1); /* data reference index */
+    put_be32(pb, 0); /* reserved */
+    put_be32(pb, !!(track->enc->flags2 & CODEC_FLAG2_DROP_FRAME_TIMECODE)); /* flags */
+    put_be32(pb, track->timescale); /* timescale */
+    put_be32(pb, track->enc->time_base.num); /* frame duration */
+    put_byte(pb, av_rescale_rnd(track->timescale, 1, track->enc->time_base.num, AV_ROUND_UP)); /* number of frames */
+    put_be24(pb, 0); /* reserved */
+    return 36;
+}
+
 static int mov_write_stsd_tag(ByteIOContext *pb, MOVTrack *track)
 {
     int64_t pos = url_ftell(pb);
@@ -814,11 +894,27 @@
         mov_write_video_tag(pb, track);
     else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
         mov_write_audio_tag(pb, track);
+    else if (track->enc->codec_type == CODEC_TYPE_DATA &&
+             track->enc->codec_tag == MKTAG('t','m','c','d'))
+        mov_write_tmcd_tag(pb, track);
     else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE)
         mov_write_subtitle_tag(pb, track);
     return updateSize(pb, pos);
 }
 
+static int mov_write_cslg_tag(ByteIOContext *pb, MOVTrack *track)
+{
+    put_be32(pb, 32);
+    put_tag (pb, "cslg");
+    put_be32(pb, 0); // version + flags
+    put_be32(pb, -track->cluster[0].dts); // dts shift
+    put_be32(pb, track->min_cts); // least dts to pts delta
+    put_be32(pb, track->max_cts); // greatest dts to pts delta
+    put_be32(pb, 0); // pts start
+    put_be32(pb, track->pts_duration); // pts end
+    return 0;
+}
+
 static int mov_write_ctts_tag(ByteIOContext *pb, MOVTrack *track)
 {
     MOVStts *ctts_entries;
@@ -921,8 +1017,11 @@
     if (track->mode == MODE_MOV && track->flags & MOV_TRACK_STPS)
         mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE);
     if (track->enc->codec_type == CODEC_TYPE_VIDEO &&
-        track->flags & MOV_TRACK_CTTS)
+        track->flags & MOV_TRACK_CTTS) {
         mov_write_ctts_tag(pb, track);
+        if (track->mode == MODE_MOV)
+            mov_write_cslg_tag(pb, track);
+    }
     mov_write_stsc_tag(pb, track);
     mov_write_stsz_tag(pb, track);
     mov_write_stco_tag(pb, track);
@@ -946,9 +1045,10 @@
     return 12;
 }
 
-static int mov_write_gmhd_tag(ByteIOContext *pb)
+static int mov_write_gmhd_tag(ByteIOContext *pb, MOVTrack *track)
 {
-    put_be32(pb, 0x20);   /* size */
+    int64_t pos = url_ftell(pb);
+    put_be32(pb, 0);      /* size */
     put_tag(pb, "gmhd");
     put_be32(pb, 0x18);   /* gmin size */
     put_tag(pb, "gmin");  /* generic media info */
@@ -959,7 +1059,31 @@
     put_be16(pb, 0x8000); /* opColor (b?) */
     put_be16(pb, 0);      /* balance */
     put_be16(pb, 0);      /* reserved */
-    return 0x20;
+
+    if (track->enc->codec_tag == MKTAG('t','m','c','d')) {
+        /* tmcd atom */
+        put_be32(pb, 47); /* size */
+        put_tag(pb, "tmcd");
+
+        /* tcmi atom */
+        put_be32(pb, 39); /* size */
+        put_tag(pb, "tcmi");
+        put_be32(pb, 0); /* version & flags */
+        put_be16(pb, 0); /* font */
+        put_be16(pb, 0); /* face */
+        put_be16(pb, 12); /* size */
+        put_be16(pb, 0); /* reserved */
+        put_be16(pb, 65535); /* fg color */
+        put_be16(pb, 65535); /* fg color */
+        put_be16(pb, 65535); /* fg color */
+        put_be16(pb, 0); /* bg color */
+        put_be16(pb, 0); /* bg color */
+        put_be16(pb, 0); /* bg color */
+        put_byte(pb, 6); /* font name length */
+        put_buffer(pb, "System", 6);
+    }
+
+    return updateSize(pb, pos);
 }
 
 static int mov_write_smhd_tag(ByteIOContext *pb)
@@ -998,6 +1122,10 @@
         } else if (track->enc->codec_type == CODEC_TYPE_AUDIO) {
             hdlr_type = "soun";
             descr = "SoundHandler";
+        } else if (track->enc->codec_type == CODEC_TYPE_DATA &&
+                   track->enc->codec_tag == MKTAG('t','m','c','d')) {
+            hdlr_type = "tmcd";
+            descr = "TimeCodeHandler";
         } else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
             if (track->tag == MKTAG('t','x','3','g')) hdlr_type = "sbtl";
             else                                      hdlr_type = "text";
@@ -1030,8 +1158,10 @@
         mov_write_vmhd_tag(pb);
     else if (track->enc->codec_type == CODEC_TYPE_AUDIO)
         mov_write_smhd_tag(pb);
+    else if (track->enc->codec_type == CODEC_TYPE_DATA)
+        mov_write_gmhd_tag(pb, track);
     else if (track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
-        if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb);
+        if (track->tag == MKTAG('t','e','x','t')) mov_write_gmhd_tag(pb, track);
         else                                      mov_write_nmhd_tag(pb);
     }
     if (track->mode == MODE_MOV) /* FIXME: Why do it for MODE_MOV only ? */
@@ -1126,10 +1256,7 @@
     /* Track width and height, for visual only */
     if(track->enc->codec_type == CODEC_TYPE_VIDEO ||
        track->enc->codec_type == CODEC_TYPE_SUBTITLE) {
-        double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio);
-        if(!sample_aspect_ratio || track->height != track->enc->height)
-            sample_aspect_ratio = 1;
-        put_be32(pb, sample_aspect_ratio * track->enc->width*0x10000);
+        put_be32(pb, track->enc->width*0x10000);
         put_be32(pb, track->height*0x10000);
     }
     else {
@@ -1151,7 +1278,7 @@
 
     put_be32(pb, av_rescale_rnd(track->trackDuration, globalTimescale, track->timescale, AV_ROUND_UP)); /* duration   ... doesn't seem to effect psp */
 
-    put_be32(pb, track->cluster[0].cts); /* first pts is cts since dts is 0 */
+    put_be32(pb, track->first_pts - track->cluster[0].dts);
     put_be32(pb, 0x00010000);
     return 0x24;
 }
@@ -1175,14 +1302,28 @@
     return 0x34;
 }
 
+static int mov_write_tref_tag(ByteIOContext *pb, MOVTrack* track)
+{
+    put_be32(pb, 20); /* size */
+    put_tag(pb, "tref");
+    put_be32(pb, 12); /* size */
+    put_tag(pb, "tmcd");
+    put_be32(pb, track->tref);
+    return 20;
+}
+
 static int mov_write_trak_tag(ByteIOContext *pb, MOVTrack *track, AVStream *st)
 {
     int64_t pos = url_ftell(pb);
     put_be32(pb, 0); /* size */
     put_tag(pb, "trak");
     mov_write_tkhd_tag(pb, track, st);
+    if (track->mode == MODE_MOV && track->enc->sample_aspect_ratio.num)
+        mov_write_tapt_tag(pb, track);
     if (track->mode == MODE_PSP || track->flags & MOV_TRACK_CTTS)
         mov_write_edts_tag(pb, track);  // PSP Movies require edts box
+    if (track->tref)
+        mov_write_tref_tag(pb, track);
     mov_write_mdia_tag(pb, track);
     if (track->mode == MODE_PSP)
         mov_write_uuid_tag_psp(pb,track);  // PSP Movies require this uuid box
@@ -1314,51 +1455,48 @@
                                      const char *name, const char *tag,
                                      int long_style)
 {
-    int l, lang = 0, len, len2;
-    AVMetadataTag *t, *t2 = NULL;
-    char tag2[16];
+    AVMetadataTag *t;
+    const char *lang;
+    int langcode;
 
-    if (!(t = av_metadata_get(s->metadata, tag, NULL, 0)))
+    if (!(t = av_metadata_get(s->metadata, tag, 0)))
         return 0;
 
-    len = strlen(t->key);
-    snprintf(tag2, sizeof(tag2), "%s-", tag);
-    while ((t2 = av_metadata_get(s->metadata, tag2, t2, AV_METADATA_IGNORE_SUFFIX))) {
-        len2 = strlen(t2->key);
-        if (len2 == len+4 && !strcmp(t->value, t2->value)
-            && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 0)) >= 0) {
-            lang = l;
-            break;
-        }
-    }
-    return mov_write_string_tag(pb, name, t->value, lang, long_style);
+    lang = av_metadata_get_attribute(t, "language");
+    langcode = lang ? ff_mov_iso639_to_lang(lang, 0) : 0;
+
+    return mov_write_string_tag(pb, name, t->value, langcode, long_style);
 }
 
 /* iTunes track number */
 static int mov_write_trkn_tag(ByteIOContext *pb, MOVMuxContext *mov,
                               AVFormatContext *s)
 {
-    AVMetadataTag *t = av_metadata_get(s->metadata, "track", NULL, 0);
-    int size = 0, track = t ? atoi(t->value) : 0;
-    if (track) {
+    AVMetadataTag *t = av_metadata_get(s->metadata, "track", 0);
+    int tracks = 0, track = t ? atoi(t->value) : 0;
+    int64_t pos = url_ftell(pb);
+
+    if (!track)
+        return 0;
+
+    put_be32(pb, 0); /* size */
+    put_tag(pb, "trkn");
+    {
+        char *slash;
         int64_t pos = url_ftell(pb);
+        if ((slash = strrchr(t->value, '/')))
+            tracks = atoi(slash+1);
         put_be32(pb, 0); /* size */
-        put_tag(pb, "trkn");
-        {
-            int64_t pos = url_ftell(pb);
-            put_be32(pb, 0); /* size */
-            put_tag(pb, "data");
-            put_be32(pb, 0);        // 8 bytes empty
-            put_be32(pb, 0);
-            put_be16(pb, 0);        // empty
-            put_be16(pb, track);    // track number
-            put_be16(pb, 0);        // total track number
-            put_be16(pb, 0);        // empty
-            updateSize(pb, pos);
-        }
-        size = updateSize(pb, pos);
+        put_tag(pb, "data");
+        put_be32(pb, 0);        // 8 bytes empty
+        put_be32(pb, 0);
+        put_be16(pb, 0);        // empty
+        put_be16(pb, track);    // track number
+        put_be16(pb, tracks);   // total track number
+        put_be16(pb, 0);        // empty
+        updateSize(pb, pos);
     }
-    return size;
+    return updateSize(pb, pos);
 }
 
 /* iTunes meta data list */
@@ -1369,8 +1507,8 @@
     put_be32(pb, 0); /* size */
     put_tag(pb, "ilst");
     mov_write_string_metadata(s, pb, "\251nam", "title"    , 1);
-    mov_write_string_metadata(s, pb, "\251ART", "author"   , 1);
-    mov_write_string_metadata(s, pb, "\251wrt", "author"   , 1);
+    mov_write_string_metadata(s, pb, "\251ART", "artist"   , 1);
+    mov_write_string_metadata(s, pb, "\251wrt", "composer" , 1);
     mov_write_string_metadata(s, pb, "\251alb", "album"    , 1);
     mov_write_string_metadata(s, pb, "\251day", "year"     , 1);
     mov_write_string_tag(pb, "\251too", LIBAVFORMAT_IDENT, 0, 1);
@@ -1427,7 +1565,7 @@
                                   const char *tag, const char *str)
 {
     int64_t pos = url_ftell(pb);
-    AVMetadataTag *t = av_metadata_get(s->metadata, str, NULL, 0);
+    AVMetadataTag *t = av_metadata_get(s->metadata, str, 0);
     if (!t || !utf8len(t->value))
         return 0;
     put_be32(pb, 0);   /* size */
@@ -1439,7 +1577,7 @@
         put_be16(pb, language_code("eng")); /* language */
         put_buffer(pb, t->value, strlen(t->value)+1); /* UTF8 string value */
         if (!strcmp(tag, "albm") &&
-            (t = av_metadata_get(s->metadata, "year", NULL, 0)))
+            (t = av_metadata_get(s->metadata, "year", 0)))
             put_byte(pb, atoi(t->value));
     }
     return updateSize(pb, pos);
@@ -1508,7 +1646,7 @@
 
 static int mov_write_uuidusmt_tag(ByteIOContext *pb, AVFormatContext *s)
 {
-    AVMetadataTag *title = av_metadata_get(s->metadata, "title", NULL, 0);
+    AVMetadataTag *title = av_metadata_get(s->metadata, "title", 0);
     int64_t pos, pos2;
 
     if (title) {
@@ -1743,7 +1881,7 @@
     for(i=0; i<s->nb_streams; i++){
         AVStream *st= s->streams[i];
         MOVTrack *track= &mov->tracks[i];
-        AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL,0);
+        AVMetadataTag *lang = av_metadata_get(st->metadata, "language", 0);
 
         track->enc = st->codec;
         track->language = ff_mov_iso639_to_lang(lang?lang->value:"und", mov->mode!=MODE_MOV);
@@ -1765,7 +1903,13 @@
                     goto error;
                 }
                 track->height = track->tag>>24 == 'n' ? 486 : 576;
+            } else {
+                track->height = st->codec->height;
             }
+
+            track->dar.num = track->enc->width *track->enc->sample_aspect_ratio.num;
+            track->dar.den = track->enc->height*track->enc->sample_aspect_ratio.den;
+
             track->timescale = st->codec->time_base.den;
             if (track->mode == MODE_MOV && track->timescale > 100000)
                 av_log(s, AV_LOG_WARNING,
@@ -1791,9 +1935,8 @@
             }
         }else if(st->codec->codec_type == CODEC_TYPE_SUBTITLE){
             track->timescale = st->codec->time_base.den;
-        }
-        if (!track->height)
             track->height = st->codec->height;
+        }
 
         av_set_pts_info(st, 64, 1, track->timescale);
     }
@@ -1906,7 +2049,20 @@
     }
     if (pkt->dts != pkt->pts)
         trk->flags |= MOV_TRACK_CTTS;
-    trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
+
+    if (trk->flags & MOV_TRACK_CTTS) {
+        if (trk->mode == MODE_MOV) {
+            trk->cluster[trk->entry].cts = pkt->pts - pkt->dts + trk->cluster[0].dts;
+            trk->min_cts = FFMIN(trk->cluster[trk->entry].cts, trk->min_cts);
+            trk->max_cts = FFMAX(trk->cluster[trk->entry].cts, trk->max_cts);
+            trk->pts_duration = FFMAX(pkt->pts+pkt->duration, trk->pts_duration);
+            trk->first_pts = FFMIN(pkt->dts + trk->cluster[trk->entry].cts, trk->first_pts);
+        } else {
+            trk->cluster[trk->entry].cts = pkt->pts - pkt->dts;
+            trk->first_pts = FFMIN(pkt->pts, trk->first_pts);
+        }
+    }
+
     trk->cluster[trk->entry].flags = 0;
     if (pkt->flags & PKT_FLAG_KEY) {
         if (mov->mode == MODE_MOV && enc->codec_id == CODEC_ID_MPEG2VIDEO) {
@@ -1933,8 +2089,56 @@
     ByteIOContext *pb = s->pb;
     int res = 0;
     int i;
+    int64_t moov_pos;
+
+    /* VERY VERY UGLY */
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *st = s->streams[i];
+        if (st->codec->codec_type == CODEC_TYPE_VIDEO &&
+            mov->mode == MODE_MOV && st->codec->timecode_frame_start > 0) {
+            MOVTrack *track;
+            AVPacket pkt;
+
+            track = av_realloc(mov->tracks, (mov->nb_streams+1)*sizeof(*track));
+            if (!track)
+                break;
+            mov->tracks = track;
+            track = &mov->tracks[mov->nb_streams];
+            memset(track, 0, sizeof(*track));
+            track->enc = avcodec_alloc_context();
+            if (!track->enc)
+                break;
+            mov->nb_streams++;
+
+            track->tag = track->enc->codec_tag = MKTAG('t','m','c','d');
+            track->enc->codec_type = CODEC_TYPE_DATA;
+            track->enc->time_base = st->codec->time_base;
+            track->enc->flags2 = st->codec->flags2;
+            track->enc->timecode_frame_start = st->codec->timecode_frame_start;
+
+            track->mode = MODE_MOV;
+            track->timescale = track->enc->time_base.den;
+            track->vosData = (uint8_t*)track->enc; // hack to free enc later
+            track->vosLen = sizeof(*track->enc);
+
+            mov->tracks[i].tref = mov->nb_streams;
+
+            av_new_packet(&pkt, 4);
+            pkt.dts = 0;
+            pkt.pts = 0;
+            pkt.size = 4;
+            AV_WB32(pkt.data, st->codec->timecode_frame_start);
+            pkt.stream_index = mov->nb_streams - 1;
+            pkt.duration = mov->tracks[i].trackDuration;
+
+            mov_write_packet(s, &pkt);
+
+            av_free_packet(&pkt);
+            break;
+        }
+    }
 
-    int64_t moov_pos = url_ftell(pb);
+    moov_pos = url_ftell(pb);
 
     /* Write size of mdat tag */
     if (mov->mdat_size+8 <= UINT32_MAX) {
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mpegts.c ./mpegts.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mpegts.c	2009-12-13 14:13:21.000000000 +0100
+++ ./mpegts.c	2009-11-15 04:50:20.000000000 +0100
@@ -38,7 +38,7 @@
    synchronisation is lost */
 #define MAX_RESYNC_SIZE 65536
 
-#define MAX_PES_PAYLOAD 200*1024
+#define MAX_PES_PAYLOAD 250*1024
 
 typedef struct PESContext PESContext;
 
@@ -526,6 +526,7 @@
 static const StreamType REGD_types[] = {
     { MKTAG('d','r','a','c'), CODEC_TYPE_VIDEO, CODEC_ID_DIRAC },
     { MKTAG('A','C','-','3'), CODEC_TYPE_AUDIO,   CODEC_ID_AC3 },
+    { MKTAG('B','S','S','D'), CODEC_TYPE_AUDIO, CODEC_ID_S302M },
     { 0 },
 };
 
@@ -1108,12 +1111,16 @@
                 if (name) {
                     AVProgram *program = av_new_program(ts->stream, sid);
                     if(program) {
-                        av_metadata_set(&program->metadata, "name", name);
-                        av_metadata_set(&program->metadata, "provider_name", provider_name);
+                        av_metadata_set_string(&program->metadata,
+                                               "name", name,
+                                               AV_METADATA_NONCONST_VALUE |
+                                               AV_METADATA_REPLACE);
+                        av_metadata_set_string(&program->metadata,
+                                               "provider name", provider_name,
+                                               AV_METADATA_NONCONST_VALUE |
+                                               AV_METADATA_REPLACE);
                     }
                 }
-                av_free(name);
-                av_free(provider_name);
                 break;
             default:
                 break;
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mxfdec.c ./mxfdec.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mxfdec.c	2009-12-13 14:15:18.000000000 +0100
+++ ./mxfdec.c	2009-11-15 04:50:20.000000000 +0100
@@ -804,6 +804,8 @@
             st->codec->height = descriptor->height;
             st->codec->bits_per_coded_sample = descriptor->bits_per_sample; /* Uncompressed */
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
+            st->r_frame_rate.num = material_track->edit_rate.den;
+            st->r_frame_rate.den = material_track->edit_rate.num;
         } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
             container_ul = mxf_get_codec_ul(mxf_essence_container_uls, essence_container_ul);
             if (st->codec->codec_id == CODEC_ID_NONE)
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mxfenc.c ./mxfenc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/mxfenc.c	2009-12-13 14:13:21.000000000 +0100
+++ ./mxfenc.c	2009-11-15 04:50:20.000000000 +0100
@@ -42,7 +42,9 @@
 #include "mxf.h"
 
 static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 };
+static const int P60_samples_per_frame[]  = {  801,  801,  800,  801,  801, 0 };
 static const int PAL_samples_per_frame[]  = { 1920, 0 };
+static const int P50_samples_per_frame[]  = {  960, 0 };
 
 AVOutputFormat mxf_d10_muxer;
 
@@ -183,7 +185,7 @@
     int last_key_index;  ///< index of last key frame
     uint64_t duration;
     AVStream *timecode_track;
-    int timecode_base;       ///< rounded time code base (25 or 30)
+    int timecode_base;       ///< rounded time code base (25,30,50,60)
     int timecode_start;      ///< frame number computed from mpeg-2 gop header timecode
     int timecode_drop_frame; ///< time code use drop frame method frop mpeg-2 essence gop header
     int edit_unit_byte_count; ///< fixed edit unit byte count
@@ -828,7 +830,7 @@
     default:   f1 =  0; f2 =   0; break;
     }
 
-    if (!sc->interlaced) {
+    if (!sc->interlaced && f2) {
         f2  = 0;
         f1 *= 2;
     }
@@ -1428,6 +1430,14 @@
                 samples_per_frame = NTSC_samples_per_frame;
                 mxf->time_base = (AVRational){ 1001, 30000 };
                 mxf->timecode_base = 30;
+            } else if (fabs(av_q2d(st->codec->time_base) - 1/50.0) < 0.0001) {
+                samples_per_frame = P50_samples_per_frame;
+                mxf->time_base = (AVRational){ 1, 50 };
+                mxf->timecode_base = 50;
+            } else if (fabs(av_q2d(st->codec->time_base) - 1001/60000.0) < 0.0001) {
+                samples_per_frame = P60_samples_per_frame;
+                mxf->time_base = (AVRational){ 1001, 60000 };
+                mxf->timecode_base = 60;
             } else {
                 av_log(s, AV_LOG_ERROR, "unsupported video frame rate\n");
                 return -1;
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/rmdec.c ./rmdec.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/rmdec.c	2009-12-13 14:15:18.000000000 +0100
+++ ./rmdec.c	2009-11-15 04:50:20.000000000 +0100
@@ -63,33 +63,25 @@
 
 static const unsigned char sipr_subpk_size[4] = { 29, 19, 37, 20 };
 
-static inline void get_strl(ByteIOContext *pb, char *buf, int buf_size, int len)
-{
-    int i;
-    char *q, r;
-
-    q = buf;
-    for(i=0;i<len;i++) {
-        r = get_byte(pb);
-        if (i < buf_size - 1)
-            *q++ = r;
-    }
-    if (buf_size > 0) *q = '\0';
-}
-
 static void get_str8(ByteIOContext *pb, char *buf, int buf_size)
 {
-    get_strl(pb, buf, buf_size, get_byte(pb));
+    uint8_t size = get_byte(pb);
+    get_buffer(pb, buf, size);
+    buf[size] = 0;
 }
 
 static void rm_read_metadata(AVFormatContext *s, int wide)
 {
-    char buf[1024];
     int i;
     for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) {
         int len = wide ? get_be16(s->pb) : get_byte(s->pb);
-        get_strl(s->pb, buf, sizeof(buf), len);
-        av_metadata_set(&s->metadata, ff_rm_metadata[i], buf);
+        char *buf = av_malloc(len+1);
+        if (!buf)
+            return;
+        get_buffer(s->pb, buf, len);
+        buf[len] = 0;
+        av_metadata_set_string(&s->metadata, ff_rm_metadata[i],
+                               buf, AV_METADATA_NONCONST_VALUE);
     }
 }
 
@@ -278,7 +270,6 @@
             goto fail1;
         st->codec->width = get_be16(pb);
         st->codec->height = get_be16(pb);
-        st->codec->time_base.num= 1;
         fps= get_be16(pb);
         st->codec->codec_type = CODEC_TYPE_VIDEO;
         get_be32(pb);
@@ -298,7 +289,9 @@
         get_buffer(pb, st->codec->extradata, st->codec->extradata_size);
 
 //        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
-        st->codec->time_base.den = fps * st->codec->time_base.num;
+        st->r_frame_rate.num = fps2;
+        st->r_frame_rate.den = 1;
+
         switch(((uint8_t*)st->codec->extradata)[4]>>4){
         case 1: st->codec->codec_id = CODEC_ID_RV10; break;
         case 2: st->codec->codec_id = CODEC_ID_RV20; break;
@@ -635,7 +628,7 @@
             memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices,
                 vst->videobufpos - 1 - 8*vst->slices);
         pkt->size = vst->videobufpos + 8*(vst->cur_slice - vst->slices);
-        pkt->pts = AV_NOPTS_VALUE;
+        pkt->dts = AV_NOPTS_VALUE;
         pkt->pos = vst->pktpos;
         vst->slices = 0;
         return 0;
@@ -771,7 +764,7 @@
     }
 #endif
 
-    pkt->pts= timestamp;
+    pkt->dts= timestamp;
     if (flags & 2)
         pkt->flags |= PKT_FLAG_KEY;
 
@@ -795,7 +788,7 @@
                st->codec->block_align);
     }
     rm->audio_pkt_cnt--;
-    if ((pkt->pts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
+    if ((pkt->dts = ast->audiotimestamp) != AV_NOPTS_VALUE) {
         ast->audiotimestamp = AV_NOPTS_VALUE;
         pkt->flags = PKT_FLAG_KEY;
     } else
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/utils.c ./utils.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/utils.c	2009-12-13 14:15:18.000000000 +0100
+++ ./utils.c	2009-11-15 04:50:20.000000000 +0100
@@ -708,207 +705,17 @@
 static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
                                AVCodecParserContext *pc, AVPacket *pkt)
 {
-    int num, den, presentation_delayed, delay, i;
-    int64_t offset;
-
-    if (st->codec->codec_id != CODEC_ID_H264 && pc && pc->pict_type == FF_B_TYPE)
-        //FIXME Set low_delay = 0 when has_b_frames = 1
-        st->codec->has_b_frames = 1;
-
-    /* do we have a video B-frame ? */
-    delay= st->codec->has_b_frames;
-    presentation_delayed = 0;
-    /* XXX: need has_b_frame, but cannot get it if the codec is
-        not initialized */
-    if (delay &&
-        pc && pc->pict_type != FF_B_TYPE)
-        presentation_delayed = 1;
-
-    if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && pkt->dts > pkt->pts && st->pts_wrap_bits<63
-       /*&& pkt->dts-(1LL<<st->pts_wrap_bits) < pkt->pts*/){
-        pkt->dts -= 1LL<<st->pts_wrap_bits;
-    }
-
-    // some mpeg2 in mpeg-ps lack dts (issue171 / input_file.mpg)
-    // we take the conservative approach and discard both
-    // Note, if this is misbehaving for a H.264 file then possibly presentation_delayed is not set correctly.
-    if(delay==1 && pkt->dts == pkt->pts && pkt->dts != AV_NOPTS_VALUE && presentation_delayed){
-        av_log(s, AV_LOG_WARNING, "invalid dts/pts combination\n");
-        pkt->dts= pkt->pts= AV_NOPTS_VALUE;
-    }
-
     if (pkt->duration == 0) {
+        int num, den;
         compute_frame_duration(&num, &den, st, pc, pkt);
         if (den && num) {
             pkt->duration = av_rescale(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num);
-
-            if(pkt->duration != 0 && s->packet_buffer)
-                update_initial_durations(s, st, pkt);
-        }
-    }
-
-    /* correct timestamps with byte offset if demuxers only have timestamps
-       on packet boundaries */
-    if(pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size){
-        /* this will estimate bitrate based on this frame's duration and size */
-        offset = av_rescale(pc->offset, pkt->duration, pkt->size);
-        if(pkt->pts != AV_NOPTS_VALUE)
-            pkt->pts += offset;
-        if(pkt->dts != AV_NOPTS_VALUE)
-            pkt->dts += offset;
-    }
-
-    if (pc && pc->dts_sync_point >= 0) {
-        // we have synchronization info from the parser
-        int64_t den = st->codec->time_base.den * (int64_t) st->time_base.num;
-        if (den > 0) {
-            int64_t num = st->codec->time_base.num * (int64_t) st->time_base.den;
-            if (pkt->dts != AV_NOPTS_VALUE) {
-                // got DTS from the stream, update reference timestamp
-                st->reference_dts = pkt->dts - pc->dts_ref_dts_delta * num / den;
-                pkt->pts = pkt->dts + pc->pts_dts_delta * num / den;
-            } else if (st->reference_dts != AV_NOPTS_VALUE) {
-                // compute DTS based on reference timestamp
-                pkt->dts = st->reference_dts + pc->dts_ref_dts_delta * num / den;
-                pkt->pts = pkt->dts + pc->pts_dts_delta * num / den;
-            }
-            if (pc->dts_sync_point > 0)
-                st->reference_dts = pkt->dts; // new reference
-        }
-    }
-
-    /* This may be redundant, but it should not hurt. */
-    if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts > pkt->dts)
-        presentation_delayed = 1;
-
-//    av_log(NULL, AV_LOG_DEBUG, "IN delayed:%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64" st:%d pc:%p\n", presentation_delayed, pkt->pts, pkt->dts, st->cur_dts, pkt->stream_index, pc);
-    /* interpolate PTS and DTS if they are not present */
-    //We skip H264 currently because delay and has_b_frames are not reliably set
-    if((delay==0 || (delay==1 && pc)) && st->codec->codec_id != CODEC_ID_H264){
-        if (presentation_delayed) {
-            /* DTS = decompression timestamp */
-            /* PTS = presentation timestamp */
-            if (pkt->dts == AV_NOPTS_VALUE)
-                pkt->dts = st->last_IP_pts;
-            update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts);
-            if (pkt->dts == AV_NOPTS_VALUE)
-                pkt->dts = st->cur_dts;
-
-            /* this is tricky: the dts must be incremented by the duration
-            of the frame we are displaying, i.e. the last I- or P-frame */
-            if (st->last_IP_duration == 0)
-                st->last_IP_duration = pkt->duration;
-            if(pkt->dts != AV_NOPTS_VALUE)
-                st->cur_dts = pkt->dts + st->last_IP_duration;
-            st->last_IP_duration  = pkt->duration;
-            st->last_IP_pts= pkt->pts;
-            /* cannot compute PTS if not present (we can compute it only
-            by knowing the future */
-        } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){
-            if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){
-                int64_t old_diff= FFABS(st->cur_dts - pkt->duration - pkt->pts);
-                int64_t new_diff= FFABS(st->cur_dts - pkt->pts);
-                if(old_diff < new_diff && old_diff < (pkt->duration>>3)){
-                    pkt->pts += pkt->duration;
-    //                av_log(NULL, AV_LOG_DEBUG, "id:%d old:%"PRId64" new:%"PRId64" dur:%d cur:%"PRId64" size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size);
-                }
-            }
-
-            /* presentation is not delayed : PTS and DTS are the same */
-            if(pkt->pts == AV_NOPTS_VALUE)
-                pkt->pts = pkt->dts;
-            update_initial_timestamps(s, pkt->stream_index, pkt->pts, pkt->pts);
-            if(pkt->pts == AV_NOPTS_VALUE)
-                pkt->pts = st->cur_dts;
-            pkt->dts = pkt->pts;
-            if(pkt->pts != AV_NOPTS_VALUE)
-                st->cur_dts = pkt->pts + pkt->duration;
-        }
-    }
-
-    if(pkt->pts != AV_NOPTS_VALUE && delay <= MAX_REORDER_DELAY){
-        st->pts_buffer[0]= pkt->pts;
-        for(i=0; i<delay && st->pts_buffer[i] > st->pts_buffer[i+1]; i++)
-            FFSWAP(int64_t, st->pts_buffer[i], st->pts_buffer[i+1]);
-        if(pkt->dts == AV_NOPTS_VALUE)
-            pkt->dts= st->pts_buffer[0];
-        if(st->codec->codec_id == CODEC_ID_H264){ //we skiped it above so we try here
-            update_initial_timestamps(s, pkt->stream_index, pkt->dts, pkt->pts); // this should happen on the first packet
         }
-        if(pkt->dts > st->cur_dts)
-            st->cur_dts = pkt->dts;
     }
 
-//    av_log(NULL, AV_LOG_ERROR, "OUTdelayed:%d/%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts);
-
     /* update flags */
     if(is_intra_only(st->codec))
         pkt->flags |= PKT_FLAG_KEY;
@@ -920,8 +727,35 @@
         else if (pc->key_frame == -1 && pc->pict_type == FF_I_TYPE)
             pkt->flags |= PKT_FLAG_KEY;
     }
-    if (pc)
-        pkt->convergence_duration = pc->convergence_duration;
+
+    if (pkt->dts == AV_NOPTS_VALUE &&
+        (s->iformat->flags & AVFMT_NOTIMESTAMPS || s->flags & AVFMT_FLAG_GENPTS)) {
+        if (st->cur_dts != AV_NOPTS_VALUE/2 && !pkt->duration) {
+            av_log(s, AV_LOG_ERROR,
+                   "timestamps generation failed, frame duration not set\n");
+            st->cur_dts = AV_NOPTS_VALUE/2; // disable generation
+        }
+
+        if (st->cur_dts == AV_NOPTS_VALUE/2)
+            return;
+
+        if (st->cur_dts == AV_NOPTS_VALUE) {
+            if (st->start_time == AV_NOPTS_VALUE)
+                st->start_time = 0;
+            st->cur_dts = st->start_time - st->codec->has_b_frames*pkt->duration;
+        }
+
+        pkt->dts = st->cur_dts;
+
+        if (!st->codec->has_b_frames || (pc && pc->pict_type == FF_B_TYPE))
+            pkt->pts = pkt->dts;
+    }
+
+    if (pkt->dts != AV_NOPTS_VALUE)
+        st->cur_dts = pkt->dts;
+
+    if (st->cur_dts != AV_NOPTS_VALUE)
+        st->cur_dts += pkt->duration;
 }
 
 
@@ -968,6 +802,9 @@
                     pkt->dts = st->parser->dts;
                     pkt->pos = st->parser->pos;
                     pkt->destruct = NULL;
+                    if (st->parser->flags & PARSER_FLAG_COMPLETE_FRAMES &&
+                        st->cur_pkt.duration)
+                        pkt->duration = st->cur_pkt.duration;
                     compute_pkt_fields(s, st, st->parser, pkt);
 
                     if((s->iformat->flags & AVFMT_GENERIC_INDEX) && pkt->flags & PKT_FLAG_KEY){
@@ -1064,12 +901,20 @@
 {
     AVPacketList *pktl;
     int eof=0;
-    const int genpts= s->flags & AVFMT_FLAG_GENPTS;
+    const int genpts= s->flags & AVFMT_FLAG_GENPTS ||
+        s->iformat->flags & AVFMT_NOTIMESTAMPS;
 
     for(;;){
         pktl = s->packet_buffer;
         if (pktl) {
             AVPacket *next_pkt= &pktl->pkt;
+            AVStream *st = s->streams[next_pkt->stream_index];
+
+            if (st->discard == AVDISCARD_ALL) {
+                s->packet_buffer = pktl->next;
+                av_free(pktl);
+                continue;
+            }
 
             if(genpts && next_pkt->dts != AV_NOPTS_VALUE){
                 while(pktl && next_pkt->pts == AV_NOPTS_VALUE){
@@ -1089,6 +934,9 @@
                || !genpts || eof){
                 /* read packet from packet buffer, if there is data */
                 *pkt = *next_pkt;
+                if (pkt->pts == AV_NOPTS_VALUE && eof &&
+                    st->cur_dts != AV_NOPTS_VALUE)
+                    pkt->pts = st->cur_dts;
                 s->packet_buffer = pktl->next;
                 av_free(pktl);
                 return 0;
@@ -1673,8 +1503,9 @@
                 duration = end_time - start_time;
         }
     }
-    if (duration != INT64_MIN) {
+    if (duration != INT64_MIN)
         ic->duration = duration;
+    if (ic->duration != AV_NOPTS_VALUE) {
         if (ic->file_size > 0) {
             /* compute the bitrate */
             ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE /
@@ -1830,7 +1612,7 @@
     }
 }
 
-static void av_estimate_timings(AVFormatContext *ic, int64_t old_offset)
+static void av_estimate_timings(AVFormatContext *ic)
 {
     int64_t file_size;
 
@@ -1848,33 +1630,12 @@
          !strcmp(ic->iformat->name, "mpegts")) &&
         file_size && !url_is_streamed(ic->pb)) {
         /* get accurate estimate from the PTSes */
-        av_estimate_timings_from_pts(ic, old_offset);
-    } else if (av_has_duration(ic)) {
-        /* at least one component has timings - we use them for all
-           the components */
-        fill_all_stream_timings(ic);
-    } else {
+        av_estimate_timings_from_pts(ic);
+    } else if (!strcmp(ic->iformat->name, "mp3") ||
+               !strcmp(ic->iformat->name, "mp2")) {
         /* less precise: use bitrate info */
         av_estimate_timings_from_bit_rate(ic);
     }
-    av_update_stream_timings(ic);
-
-#if 0
-    {
-        int i;
-        AVStream *st;
-        for(i = 0;i < ic->nb_streams; i++) {
-            st = ic->streams[i];
-        printf("%d: start_time: %0.3f duration: %0.3f\n",
-               i, (double)st->start_time / AV_TIME_BASE,
-               (double)st->duration / AV_TIME_BASE);
-        }
-        printf("stream: start_time: %0.3f duration: %0.3f bitrate=%d kb/s\n",
-               (double)ic->start_time / AV_TIME_BASE,
-               (double)ic->duration / AV_TIME_BASE,
-               ic->bit_rate / 1000);
-    }
-#endif
 }
 
 static int has_codec_parameters(AVCodecContext *enc)
@@ -1894,10 +1655,10 @@
         val = enc->width && enc->pix_fmt != PIX_FMT_NONE;
         break;
     default:
-        val = 1;
-        break;
+        return 1;
     }
-    return enc->codec_id != CODEC_ID_NONE && val != 0;
+    return enc->codec_id != CODEC_ID_NONE &&
+        enc->codec_id != CODEC_ID_PROBE && val;
 }
 
 static int try_decode_frame(AVStream *st, AVPacket *avpkt)
@@ -2007,72 +1768,74 @@
     }
 }
 
-#define MAX_STD_TIMEBASES (60*12+5)
-static int get_std_framerate(int i){
-    if(i<60*12) return i*1001;
-    else        return ((const int[]){24,30,60,12,15})[i-60*12]*1000*12;
-}
-
-/*
- * Is the time base unreliable.
- * This is a heuristic to balance between quick acceptance of the values in
- * the headers vs. some extra checks.
- * Old DivX and Xvid often have nonsense timebases like 1fps or 2fps.
- * MPEG-2 commonly misuses field repeat flags to store different framerates.
- * And there are "variable" fps files this needs to detect as well.
- */
-static int tb_unreliable(AVCodecContext *c){
-    if(   c->time_base.den >= 101L*c->time_base.num
-       || c->time_base.den <    5L*c->time_base.num
-/*       || c->codec_tag == AV_RL32("DIVX")
-       || c->codec_tag == AV_RL32("XVID")*/
-       || c->codec_id == CODEC_ID_MPEG2VIDEO
-       || c->codec_id == CODEC_ID_H264
-       )
-        return 1;
-    return 0;
-}
-
-int av_find_stream_info(AVFormatContext *ic)
+static int fill_stream_infos(AVFormatContext *s)
 {
-    int i, count, ret, read_size, j;
-    AVStream *st;
-    AVPacket pkt1, *pkt;
-    int64_t last_dts[MAX_STREAMS];
-    int64_t duration_gcd[MAX_STREAMS]={0};
-    int duration_count[MAX_STREAMS]={0};
-    double (*duration_error)[MAX_STD_TIMEBASES];
-    int64_t old_offset = url_ftell(ic->pb);
-    int64_t codec_info_duration[MAX_STREAMS]={0};
-    int codec_info_nb_frames[MAX_STREAMS]={0};
+    AVPacketList *pktl = s->packet_buffer;
+    int i;
 
-    duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error));
-    if (!duration_error) return AVERROR(ENOMEM);
+    typedef struct {
+        unsigned nb_frames;
+        int64_t last_dts;
+        unsigned last_dts_frame;
+    } StreamInfo;
+    StreamInfo *stream_info;
+
+    stream_info = av_mallocz(s->nb_streams*sizeof(*stream_info));
+    if (!stream_info)
+        return AVERROR_NOMEM;
+
+    for (i = 0; pktl; i++) {
+        AVPacket *pkt = &pktl->pkt;
+        AVStream *st = s->streams[pkt->stream_index];
 
-    for(i=0;i<ic->nb_streams;i++) {
-        st = ic->streams[i];
-        if(st->codec->codec_type == CODEC_TYPE_VIDEO){
-/*            if(!st->time_base.num)
-                st->time_base= */
-            if(!st->codec->time_base.num)
-                st->codec->time_base= st->time_base;
-        }
-        //only for the split stuff
-        if (!st->parser) {
-            st->parser = av_parser_init(st->codec->codec_id);
-            if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){
-                st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
+        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+            StreamInfo *stream = &stream_info[pkt->stream_index];
+            if (pkt->dts != AV_NOPTS_VALUE) {
+                //av_log(s, AV_LOG_DEBUG, "dts diff %lld\n", pkt->dts - stream->last_dts);
+                stream->last_dts = pkt->dts;
+                stream->last_dts_frame = stream->nb_frames;
             }
+            stream->nb_frames++;
         }
+        pktl = pktl->next;
     }
 
-    for(i=0;i<MAX_STREAMS;i++){
-        last_dts[i]= AV_NOPTS_VALUE;
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *st = s->streams[i];
+        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
+            StreamInfo *stream = &stream_info[st->index];
+            if (!st->r_frame_rate.num && stream->last_dts > 0) {
+                float avg_frame_duration;
+                int64_t dts_duration = stream->last_dts - st->first_dts;
+                avg_frame_duration = dts_duration /
+                    (float)stream->last_dts_frame;
+
+                av_log(s, AV_LOG_DEBUG, "nb frames %d\n", stream->nb_frames);
+                st->r_frame_rate.num = stream->last_dts_frame*st->time_base.den;
+                st->r_frame_rate.den = dts_duration*st->time_base.num;
+                av_log(s, AV_LOG_DEBUG, "last dts frame %d dts duration %lld\n",
+                       stream->last_dts_frame, dts_duration);
+                av_log(s, AV_LOG_DEBUG, "avg frame dur %f\n", avg_frame_duration);
+            }
+        } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
+            if (!st->codec->bits_per_coded_sample)
+                st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id);
+        }
     }
 
-    count = 0;
+    av_free(stream_info);
+
+    return 0;
+}
+
+int av_find_stream_info(AVFormatContext *ic)
+{
+    int i, count, ret, read_size;
+    AVStream *st;
+    AVPacket pkt1, *pkt;
+
     read_size = 0;
-    for(;;) {
+    for(count = 0; count < 1000; count++) {
         if(url_interrupt_cb()){
             ret= AVERROR(EINTR);
             av_log(ic, AV_LOG_DEBUG, "interrupted\n");
@@ -2084,13 +1847,8 @@
             st = ic->streams[i];
             if (!has_codec_parameters(st->codec))
                 break;
-            /* variable fps and no guess at the real fps */
-            if(   tb_unreliable(st->codec)
-               && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)
-                break;
-            if(st->parser && st->parser->parser->split && !st->codec->extradata)
-                break;
-            if(st->first_dts == AV_NOPTS_VALUE)
+            if (st->codec->codec_type == CODEC_TYPE_VIDEO &&
+                !st->r_frame_rate.num)
                 break;
         }
         if (i == ic->nb_streams) {
@@ -2104,10 +1862,11 @@
                 break;
             }
         }
+
         /* we did not get all the codec info, but we read too much data */
         if (read_size >= ic->probesize) {
             ret = count;
-            av_log(ic, AV_LOG_WARNING, "MAX_READ_SIZE:%d reached\n", ic->probesize);
+            av_log(ic, AV_LOG_DEBUG, "MAX_READ_SIZE:%d reached\n", ic->probesize);
             break;
         }
 
@@ -2118,66 +1877,53 @@
             continue;
         if (ret < 0) {
             /* EOF or error */
-            ret = -1; /* we could not have all the codec parameters before EOF */
             for(i=0;i<ic->nb_streams;i++) {
                 st = ic->streams[i];
                 if (!has_codec_parameters(st->codec)){
                     char buf[256];
                     avcodec_string(buf, sizeof(buf), st->codec, 0);
                     av_log(ic, AV_LOG_WARNING, "Could not find codec parameters (%s)\n", buf);
-                } else {
-                    ret = 0;
                 }
+                ret = 0;
             }
             break;
         }
 
         pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end);
         if(av_dup_packet(pkt) < 0) {
-            av_free(duration_error);
             return AVERROR(ENOMEM);
         }
 
         read_size += pkt->size;
 
         st = ic->streams[pkt->stream_index];
-        if(codec_info_nb_frames[st->index]>1) {
-            if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration){
-                av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n");
-                break;
-            }
-            codec_info_duration[st->index] += pkt->duration;
+
+        if (st->first_dts == AV_NOPTS_VALUE)
+            st->first_dts = pkt->dts;
+        if (pkt->pts != AV_NOPTS_VALUE) {
+            if (st->start_time == AV_NOPTS_VALUE)
+                st->start_time = pkt->pts;
+            st->start_time = FFMIN(pkt->pts, st->start_time);
         }
-        if (pkt->duration != 0)
-            codec_info_nb_frames[st->index]++;
 
-        {
-            int index= pkt->stream_index;
-            int64_t last= last_dts[index];
-            int64_t duration= pkt->dts - last;
-
-            if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){
-                double dur= duration * av_q2d(st->time_base);
-
-//                if(st->codec->codec_type == CODEC_TYPE_VIDEO)
-//                    av_log(NULL, AV_LOG_ERROR, "%f\n", dur);
-                if(duration_count[index] < 2)
-                    memset(duration_error[index], 0, sizeof(*duration_error));
-                for(i=1; i<MAX_STD_TIMEBASES; i++){
-                    int framerate= get_std_framerate(i);
-                    int ticks= lrintf(dur*framerate/(1001*12));
-                    double error= dur - ticks*1001*12/(double)framerate;
-                    duration_error[index][i] += error*error;
-                }
-                duration_count[index]++;
-                // ignore the first 4 values, they might have some random jitter
-                if (duration_count[index] > 3)
-                    duration_gcd[index] = av_gcd(duration_gcd[index], duration);
+        if ((st->codec->codec_type == CODEC_TYPE_VIDEO ||
+             st->codec->codec_type == CODEC_TYPE_AUDIO) &&
+            st->time_base.den > 0) {
+            int64_t duration = 0;
+            if (pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE)
+                duration = av_rescale_q(pkt->pts - st->start_time,
+                                        st->time_base, AV_TIME_BASE_Q);
+            if (pkt->dts != AV_NOPTS_VALUE && st->first_dts != AV_NOPTS_VALUE)
+                duration = FFMAX(duration, av_rescale_q(pkt->dts - st->first_dts,
+                                                        st->time_base, AV_TIME_BASE_Q));
+            if (duration >= ic->max_analyze_duration) {
+                av_log(ic, AV_LOG_DEBUG, "max_analyze_duration reached\n");
+                break;
             }
-            if(last == AV_NOPTS_VALUE || duration_count[index]<=1)
-                last_dts[pkt->stream_index]= pkt->dts;
         }
-        if(st->parser && st->parser->parser->split && !st->codec->extradata){
+
+        /* FIXME change the decoder */
+        if (st->codec->codec_id == CODEC_ID_VC1 && !st->codec->extradata) {
             int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
             if(i){
                 st->codec->extradata_size= i;
@@ -2217,86 +1944,13 @@
         if(st->codec->codec)
             avcodec_close(st->codec);
     }
-    for(i=0;i<ic->nb_streams;i++) {
-        st = ic->streams[i];
-        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
-            if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample)
-                st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
-
-            // the check for tb_unreliable() is not completely correct, since this is not about handling
-            // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
-            // ipmovie.c produces.
-            if (tb_unreliable(st->codec) && duration_count[i] > 15 && duration_gcd[i] > 1)
-                av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * duration_gcd[i], INT_MAX);
-            if(duration_count[i]
-               && tb_unreliable(st->codec) /*&&
-               //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ...
-               st->time_base.num*duration_sum[i]/duration_count[i]*101LL > st->time_base.den*/){
-                int num = 0;
-                double best_error= 2*av_q2d(st->time_base);
-                best_error= best_error*best_error*duration_count[i]*1000*12*30;
-
-                for(j=1; j<MAX_STD_TIMEBASES; j++){
-                    double error= duration_error[i][j] * get_std_framerate(j);
-//                    if(st->codec->codec_type == CODEC_TYPE_VIDEO)
-//                        av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error);
-                    if(error < best_error){
-                        best_error= error;
-                        num = get_std_framerate(j);
-                    }
-                }
-                // do not increase frame rate by more than 1 % in order to match a standard rate.
-                if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
-                    av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
-            }
-
-            if (!st->r_frame_rate.num){
-                if(    st->codec->time_base.den * (int64_t)st->time_base.num
-                    <= st->codec->time_base.num * st->codec->ticks_per_frame * (int64_t)st->time_base.den){
-                    st->r_frame_rate.num = st->codec->time_base.den;
-                    st->r_frame_rate.den = st->codec->time_base.num * st->codec->ticks_per_frame;
-                }else{
-                    st->r_frame_rate.num = st->time_base.den;
-                    st->r_frame_rate.den = st->time_base.num;
-                }
-            }
-        }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {
-            if(!st->codec->bits_per_coded_sample)
-                st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id);
-        }
-    }
 
-    av_estimate_timings(ic, old_offset);
+    fill_stream_infos(ic);
 
+    av_estimate_timings(ic);
+    av_update_stream_timings(ic);
     compute_chapters_end(ic);
 
 #if 0
@@ -2397,11 +2041,7 @@
     st->id = id;
     st->start_time = AV_NOPTS_VALUE;
     st->duration = AV_NOPTS_VALUE;
-        /* we set the current DTS to 0 so that formats without any timestamps
-           but durations get some timestamps, formats with some unknown
-           timestamps have their first few packets buffered and the
-           timestamps corrected before they are returned to the user */
-    st->cur_dts = 0;
+    st->cur_dts = AV_NOPTS_VALUE;
     st->first_dts = AV_NOPTS_VALUE;
     st->probe_packets = MAX_PROBE_PACKETS;
 
@@ -2414,6 +2054,8 @@
 
     st->sample_aspect_ratio = (AVRational){0,1};
 
+    st->r_frame_rate = (AVRational){0,1};
+
     s->streams[s->nb_streams++] = st;
     return st;
 }
@@ -2870,18 +2553,17 @@
     /* XXX: add a generic system */
     if (flags & AVFMT_SHOW_IDS)
-        av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id);
+        av_log(NULL, AV_LOG_INFO, "[%#05x]", st->id);
     if (lang)
-        av_log(NULL, AV_LOG_INFO, "(%s)", lang->value);
-    av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g);
-    av_log(NULL, AV_LOG_INFO, ": %s", buf);
+        av_log(NULL, AV_LOG_INFO, "(%.3s): %s", lang->value, buf);
+    else
+        av_log(NULL, AV_LOG_INFO, "(und): %s", buf);
     if (st->sample_aspect_ratio.num && // default
         av_cmp_q(st->sample_aspect_ratio, st->codec->sample_aspect_ratio)) {
         AVRational display_aspect_ratio;
diff -urN /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/vc1testenc.c ./vc1testenc.c
--- /home/michael/ffmpeg-revs/ffmpeg-r20539/trunk/libavformat/vc1testenc.c	2009-12-13 14:13:21.000000000 +0100
+++ ./vc1testenc.c	2009-11-15 04:50:20.000000000 +0100
@@ -43,10 +43,9 @@
     put_le24(pb, 0); // hrd_buffer
     put_byte(pb, 0x80); // level|cbr|res1
     put_le32(pb, 0); // hrd_rate
-    if (s->streams[0]->r_frame_rate.den && s->streams[0]->r_frame_rate.num == 1)
-        put_le32(pb, s->streams[0]->r_frame_rate.den);
-    else
-        put_le32(pb, 0xFFFFFFFF); //variable framerate
+    put_le32(pb, s->streams[0]->codec->time_base.den);
+
+    av_set_pts_info(s->streams[0], 32, 1, s->streams[0]->codec->time_base.den);
 
     return 0;
 }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-cvslog/attachments/20091214/0713fb16/attachment-0001.pgp>



More information about the ffmpeg-cvslog mailing list