OSDN Git Service

Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 18 Aug 2011 08:20:25 +0000 (10:20 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 18 Aug 2011 08:56:08 +0000 (10:56 +0200)
* qatar/master: (23 commits)
  h264: hide reference frame errors unless requested
  swscale: split hScale() function pointer into h[cy]Scale().
  Move clipd macros to x86util.asm.
  avconv: reindent.
  avconv: rescue poor abused start_time global.
  avconv: rescue poor abused recording_time global.
  avconv: merge two loops in output_packet().
  avconv: fix broken indentation.
  avconv: get rid of the arbitrary MAX_FILES limit.
  avconv: get rid of the output_streams_for_file vs. ost_table schizophrenia
  avconv: add a wrapper for output AVFormatContexts and merge output_opts into it
  avconv: make itsscale syntax consistent with other options.
  avconv: factor out adding input streams.
  avconv: Factorize combining auto vsync with format.
  avconv: Factorize video resampling.
  avconv: Don't unnecessarily convert ipts to a double.
  ffmpeg: remove unsed variable nopts
  RV3/4 parser: remove unused variable 'off'
  add XMV demuxer
  rmdec: parse FPS in RealMedia properly
  ...

Conflicts:
avconv.c
libavformat/version.h
libswscale/swscale.c
tests/ref/fate/lmlm4-demux

Merged-by: Michael Niedermayer <michaelni@gmx.at>
23 files changed:
Changelog
avconv.c
doc/general.texi
ffmpeg.c
libavcodec/Makefile
libavcodec/allcodecs.c
libavcodec/h264_refs.c
libavcodec/rv34_parser.c [new file with mode: 0644]
libavcodec/x86/dsputil_yasm.asm
libavformat/Makefile
libavformat/allformats.c
libavformat/rmdec.c
libavformat/version.h
libavformat/xmv.c [new file with mode: 0644]
libavutil/x86/x86util.asm
libswscale/ppc/swscale_altivec.c
libswscale/swscale.c
libswscale/swscale_internal.h
libswscale/x86/swscale_template.c
tests/ref/fate/feeble-dxa
tests/ref/fate/lmlm4-demux
tests/ref/fate/real-rv40
tests/ref/fate/rv30

index caf9a53..fd5863d 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -41,6 +41,7 @@ easier to use. The changes are:
     * Presets in avconv are disabled, because only libx264 used them and
       presets for libx264 can now be specified using a private option
       '-preset <presetname>'.
+- XMV demuxer
 
 
 version 0.8:
index c86e16b..85937fc 100644 (file)
--- a/avconv.c
+++ b/avconv.c
@@ -109,15 +109,9 @@ typedef struct MetadataMap {
 
 static const OptionDef options[];
 
-#define MAX_FILES 100
 #define MAX_STREAMS 1024    /* arbitrary sanity check value */
 static const char *last_asked_format = NULL;
-static double *ts_scale;
-static int  nb_ts_scale;
-
-static AVFormatContext *output_files[MAX_FILES];
-static AVDictionary *output_opts[MAX_FILES];
-static int nb_output_files = 0;
+static AVDictionary *ts_scale;
 
 static StreamMap *stream_maps = NULL;
 static int nb_stream_maps;
@@ -294,11 +288,9 @@ typedef struct OutputStream {
 
    int sws_flags;
    AVDictionary *opts;
+   int is_past_recording_time;
 } OutputStream;
 
-static OutputStream **output_streams_for_file[MAX_FILES] = { NULL };
-static int nb_output_streams_for_file[MAX_FILES] = { 0 };
-
 typedef struct InputStream {
     int file_index;
     AVStream *st;
@@ -313,7 +305,6 @@ typedef struct InputStream {
     double ts_scale;
     int is_start;            /* is 1 at the start and after a discontinuity */
     int showed_multi_packet_warning;
-    int is_past_recording_time;
     AVDictionary *opts;
 } InputStream;
 
@@ -332,11 +323,24 @@ typedef struct InputFile {
 static struct termios oldtty;
 #endif
 
+typedef struct OutputFile {
+    AVFormatContext *ctx;
+    AVDictionary *opts;
+    int ost_index;       /* index of the first stream in output_streams */
+    int64_t recording_time; /* desired length of the resulting file in microseconds */
+    int64_t start_time;     /* start time in microseconds */
+} OutputFile;
+
 static InputStream *input_streams = NULL;
 static int         nb_input_streams = 0;
 static InputFile   *input_files   = NULL;
 static int         nb_input_files   = 0;
 
+static OutputStream *output_streams = NULL;
+static int        nb_output_streams = 0;
+static OutputFile   *output_files   = NULL;
+static int        nb_output_files   = 0;
+
 #if CONFIG_AVFILTER
 
 static int configure_video_filters(InputStream *ist, OutputStream *ost)
@@ -516,12 +520,11 @@ static int exit_program(int ret)
 
     /* close files */
     for(i=0;i<nb_output_files;i++) {
-        AVFormatContext *s = output_files[i];
+        AVFormatContext *s = output_files[i].ctx;
         if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
             avio_close(s->pb);
         avformat_free_context(s);
-        av_free(output_streams_for_file[i]);
-        av_dict_free(&output_opts[i]);
+        av_dict_free(&output_files[i].opts);
     }
     for(i=0;i<nb_input_files;i++) {
         av_close_input_file(input_files[i].ctx);
@@ -541,6 +544,8 @@ static int exit_program(int ret)
 
     av_freep(&input_streams);
     av_freep(&input_files);
+    av_freep(&output_streams);
+    av_freep(&output_files);
 
     uninit_opts();
     av_free(audio_buf);
@@ -682,7 +687,8 @@ static double
 get_sync_ipts(const OutputStream *ost)
 {
     const InputStream *ist = ost->sync_ist;
-    return (double)(ist->pts - start_time)/AV_TIME_BASE;
+    OutputFile *of = &output_files[ost->file_index];
+    return (double)(ist->pts - of->start_time)/AV_TIME_BASE;
 }
 
 static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
@@ -1071,58 +1077,14 @@ static void do_subtitle_out(AVFormatContext *s,
 static int bit_buffer_size= 1024*256;
 static uint8_t *bit_buffer= NULL;
 
-static void do_video_out(AVFormatContext *s,
-                         OutputStream *ost,
-                         InputStream *ist,
-                         AVFrame *in_picture,
-                         int *frame_size, float quality)
+static void do_video_resample(OutputStream *ost,
+                              InputStream *ist,
+                              AVFrame *in_picture,
+                              AVFrame **out_picture)
 {
-    int nb_frames, i, ret, av_unused resample_changed;
-    AVFrame *final_picture, *formatted_picture;
-    AVCodecContext *enc, *dec;
-    double sync_ipts;
-
-    enc = ost->st->codec;
-    dec = ist->st->codec;
-
-    sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base);
-
-    /* by default, we output a single frame */
-    nb_frames = 1;
-
-    *frame_size = 0;
-
-    if(video_sync_method){
-        double vdelta = sync_ipts - ost->sync_opts;
-        //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
-        if (vdelta < -1.1)
-            nb_frames = 0;
-        else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){
-            if(vdelta<=-0.6){
-                nb_frames=0;
-            }else if(vdelta>0.6)
-                ost->sync_opts= lrintf(sync_ipts);
-        }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);
-        if (nb_frames == 0){
-            ++nb_frames_drop;
-            if (verbose>2)
-                fprintf(stderr, "*** drop!\n");
-        }else if (nb_frames > 1) {
-            nb_frames_dup += nb_frames - 1;
-            if (verbose>2)
-                fprintf(stderr, "*** %d dup!\n", nb_frames-1);
-        }
-    }else
-        ost->sync_opts= lrintf(sync_ipts);
-
-    nb_frames= FFMIN(nb_frames, max_frames[AVMEDIA_TYPE_VIDEO] - ost->frame_number);
-    if (nb_frames <= 0)
-        return;
-
-    formatted_picture = in_picture;
-    final_picture = formatted_picture;
+    int resample_changed = 0;
+    AVCodecContext *dec = ist->st->codec;
+    *out_picture = in_picture;
 
     resample_changed = ost->resample_width   != dec->width  ||
                        ost->resample_height  != dec->height ||
@@ -1145,7 +1107,7 @@ static void do_video_out(AVFormatContext *s,
                           dec->pix_fmt != enc->pix_fmt;
 
     if (ost->video_resample) {
-        final_picture = &ost->resample_frame;
+        *out_picture = &ost->resample_frame;
         if (!ost->img_resample_ctx || resample_changed) {
             /* initialize the destination picture */
             if (!ost->resample_frame.data[0]) {
@@ -1166,8 +1128,8 @@ static void do_video_out(AVFormatContext *s,
                 exit_program(1);
             }
         }
-        sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize,
-              0, ost->resample_height, final_picture->data, final_picture->linesize);
+        sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize,
+              0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize);
     }
 #else
     if (resample_changed) {
@@ -1183,6 +1145,64 @@ static void do_video_out(AVFormatContext *s,
         ost->resample_height  = dec->height;
         ost->resample_pix_fmt = dec->pix_fmt;
     }
+}
+
+
+static void do_video_out(AVFormatContext *s,
+                         OutputStream *ost,
+                         InputStream *ist,
+                         AVFrame *in_picture,
+                         int *frame_size, float quality)
+{
+    int nb_frames, i, ret, format_video_sync;
+    AVFrame *final_picture;
+    AVCodecContext *enc, *dec;
+    double sync_ipts;
+
+    enc = ost->st->codec;
+    dec = ist->st->codec;
+
+    sync_ipts = get_sync_ipts(ost) / av_q2d(enc->time_base);
+
+    /* by default, we output a single frame */
+    nb_frames = 1;
+
+    *frame_size = 0;
+
+    format_video_sync = video_sync_method;
+    if (format_video_sync < 0)
+        format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1;
+
+    if (format_video_sync) {
+        double vdelta = sync_ipts - ost->sync_opts;
+        //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
+        if (vdelta < -1.1)
+            nb_frames = 0;
+        else if (format_video_sync == 2) {
+            if(vdelta<=-0.6){
+                nb_frames=0;
+            }else if(vdelta>0.6)
+                ost->sync_opts= lrintf(sync_ipts);
+        }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);
+        if (nb_frames == 0){
+            ++nb_frames_drop;
+            if (verbose>2)
+                fprintf(stderr, "*** drop!\n");
+        }else if (nb_frames > 1) {
+            nb_frames_dup += nb_frames - 1;
+            if (verbose>2)
+                fprintf(stderr, "*** %d dup!\n", nb_frames-1);
+        }
+    }else
+        ost->sync_opts= lrintf(sync_ipts);
+
+    nb_frames= FFMIN(nb_frames, max_frames[AVMEDIA_TYPE_VIDEO] - ost->frame_number);
+    if (nb_frames <= 0)
+        return;
+
+    do_video_resample(ost, ist, in_picture, &final_picture);
 
     /* duplicates frame if needed */
     for(i=0;i<nb_frames;i++) {
@@ -1307,8 +1327,8 @@ static void do_video_stats(AVFormatContext *os, OutputStream *ost,
     }
 }
 
-static void print_report(AVFormatContext **output_files,
-                         OutputStream **ost_table, int nb_ostreams,
+static void print_report(OutputFile *output_files,
+                         OutputStream *ost_table, int nb_ostreams,
                          int is_last_report)
 {
     char buf[1024];
@@ -1336,7 +1356,7 @@ static void print_report(AVFormatContext **output_files,
     }
 
 
-    oc = output_files[0];
+    oc = output_files[0].ctx;
 
     total_size = avio_size(oc->pb);
     if(total_size<0) // FIXME improve avio_size() so it works with non seekable output too
@@ -1346,7 +1366,7 @@ static void print_report(AVFormatContext **output_files,
     vid = 0;
     for(i=0;i<nb_ostreams;i++) {
         float q = -1;
-        ost = ost_table[i];
+        ost = &ost_table[i];
         enc = ost->st->codec;
         if (!ost->st->stream_copy && enc->coded_frame)
             q = enc->coded_frame->quality/(float)FF_QP2LAMBDA;
@@ -1448,7 +1468,7 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_
 
 /* pkt = NULL means EOF (needed to flush decoder buffers) */
 static int output_packet(InputStream *ist, int ist_index,
-                         OutputStream **ost_table, int nb_ostreams,
+                         OutputStream *ost_table, int nb_ostreams,
                          const AVPacket *pkt)
 {
     AVFormatContext *os;
@@ -1595,22 +1615,6 @@ static int output_packet(InputStream *ist, int ist_index,
             avpkt.size = 0;
         }
 
-#if CONFIG_AVFILTER
-        if(ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
-        if (start_time == 0 || ist->pts >= start_time) {
-            for(i=0;i<nb_ostreams;i++) {
-                ost = ost_table[i];
-                if (ost->input_video_filter && ost->source_index == ist_index) {
-                    if (!picture.sample_aspect_ratio.num)
-                        picture.sample_aspect_ratio = ist->st->sample_aspect_ratio;
-                    picture.pts = ist->pts;
-
-                    av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE);
-                }
-            }
-        }
-#endif
-
         // preprocess audio (volume)
         if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
             if (audio_volume != 256) {
@@ -1634,130 +1638,149 @@ static int output_packet(InputStream *ist, int ist_index,
         }
         /* if output time reached then transcode raw format,
            encode packets and output them */
-        if (start_time == 0 || ist->pts >= start_time)
-            for(i=0;i<nb_ostreams;i++) {
-                int frame_size;
+        for (i = 0; i < nb_ostreams; i++) {
+            OutputFile *of = &output_files[ost_table[i].file_index];
+            int frame_size;
+
+            ost = &ost_table[i];
+            if (ost->source_index != ist_index)
+                continue;
+
+            if (of->start_time && ist->pts < of->start_time)
+                continue;
+
+            if (of->recording_time != INT64_MAX &&
+                av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
+                              (AVRational){1, 1000000}) >= 0) {
+                ost->is_past_recording_time = 1;
+                continue;
+            }
 
-                ost = ost_table[i];
-                if (ost->source_index == ist_index) {
 #if CONFIG_AVFILTER
-                frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
-                    !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]);
-                while (frame_available) {
-                    if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) {
-                        AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
-                        if (av_vsink_buffer_get_video_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
-                            goto cont;
-                        if (ost->picref) {
-                            avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref);
-                            ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
-                        }
+            if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
+                ost->input_video_filter) {
+                if (!picture.sample_aspect_ratio.num)
+                    picture.sample_aspect_ratio = ist->st->sample_aspect_ratio;
+                picture.pts = ist->pts;
+
+                av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, AV_VSRC_BUF_FLAG_OVERWRITE);
+            }
+            frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
+                !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]);
+            while (frame_available) {
+                if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) {
+                    AVRational ist_pts_tb = ost->output_video_filter->inputs[0]->time_base;
+                    if (av_vsink_buffer_get_video_buffer_ref(ost->output_video_filter, &ost->picref, 0) < 0)
+                        goto cont;
+                    if (ost->picref) {
+                        avfilter_fill_frame_from_video_buffer_ref(&picture, ost->picref);
+                        ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q);
                     }
+                }
 #endif
-                    os = output_files[ost->file_index];
+                os = output_files[ost->file_index].ctx;
 
-                    /* set the input output pts pairs */
-                    //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE;
+                /* set the input output pts pairs */
+                //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE;
 
-                    if (ost->encoding_needed) {
-                        av_assert0(ist->decoding_needed);
-                        switch(ost->st->codec->codec_type) {
-                        case AVMEDIA_TYPE_AUDIO:
-                            do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size);
-                            break;
-                        case AVMEDIA_TYPE_VIDEO:
+                if (ost->encoding_needed) {
+                    av_assert0(ist->decoding_needed);
+                    switch(ost->st->codec->codec_type) {
+                    case AVMEDIA_TYPE_AUDIO:
+                        do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size);
+                        break;
+                    case AVMEDIA_TYPE_VIDEO:
 #if CONFIG_AVFILTER
-                            if (ost->picref->video && !ost->frame_aspect_ratio)
-                                ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
+                        if (ost->picref->video && !ost->frame_aspect_ratio)
+                            ost->st->codec->sample_aspect_ratio = ost->picref->video->sample_aspect_ratio;
 #endif
-                            do_video_out(os, ost, ist, &picture, &frame_size,
-                                         same_quant ? quality : ost->st->codec->global_quality);
-                            if (vstats_filename && frame_size)
-                                do_video_stats(os, ost, frame_size);
-                            break;
-                        case AVMEDIA_TYPE_SUBTITLE:
-                            do_subtitle_out(os, ost, ist, &subtitle,
-                                            pkt->pts);
-                            break;
-                        default:
-                            abort();
-                        }
-                    } else {
-                        AVFrame avframe; //FIXME/XXX remove this
-                        AVPicture pict;
-                        AVPacket opkt;
-                        int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base);
-
-                        av_init_packet(&opkt);
+                        do_video_out(os, ost, ist, &picture, &frame_size,
+                                        same_quant ? quality : ost->st->codec->global_quality);
+                        if (vstats_filename && frame_size)
+                            do_video_stats(os, ost, frame_size);
+                        break;
+                    case AVMEDIA_TYPE_SUBTITLE:
+                        do_subtitle_out(os, ost, ist, &subtitle,
+                                        pkt->pts);
+                        break;
+                    default:
+                        abort();
+                    }
+                } else {
+                    AVFrame avframe; //FIXME/XXX remove this
+                    AVPicture pict;
+                    AVPacket opkt;
+                    int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
+                    av_init_packet(&opkt);
 
-                        if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes)
+                    if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes)
 #if !CONFIG_AVFILTER
-                            continue;
+                        continue;
 #else
-                            goto cont;
+                        goto cont;
 #endif
 
-                        /* no reencoding needed : output the packet directly */
-                        /* force the input stream PTS */
+                    /* no reencoding needed : output the packet directly */
+                    /* force the input stream PTS */
 
-                        avcodec_get_frame_defaults(&avframe);
-                        ost->st->codec->coded_frame= &avframe;
-                        avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY;
+                    avcodec_get_frame_defaults(&avframe);
+                    ost->st->codec->coded_frame= &avframe;
+                    avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY;
 
-                        if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
-                            audio_size += data_size;
-                        else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
-                            video_size += data_size;
-                            ost->sync_opts++;
-                        }
+                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+                        audio_size += data_size;
+                    else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
+                        video_size += data_size;
+                        ost->sync_opts++;
+                    }
 
-                        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
-                            opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
-                        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;
-
-                        //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
-                        if(   ost->st->codec->codec_id != CODEC_ID_H264
-                           && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
-                           && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
-                           ) {
-                            if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY))
-                                opkt.destruct= av_destruct_packet;
-                        } else {
-                            opkt.data = data_buf;
-                            opkt.size = data_size;
-                        }
+                    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
+                        opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
+                    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;
+
+                    //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
+                    if(   ost->st->codec->codec_id != CODEC_ID_H264
+                       && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
+                       && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
+                       ) {
+                        if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY))
+                            opkt.destruct= av_destruct_packet;
+                    } else {
+                        opkt.data = data_buf;
+                        opkt.size = data_size;
+                    }
 
-                        if (os->oformat->flags & AVFMT_RAWPICTURE) {
-                            /* store AVPicture in AVPacket, as expected by the output format */
-                            avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
-                            opkt.data = (uint8_t *)&pict;
-                            opkt.size = sizeof(AVPicture);
-                            opkt.flags |= AV_PKT_FLAG_KEY;
-                        }
-                        write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
-                        ost->st->codec->frame_number++;
-                        ost->frame_number++;
-                        av_free_packet(&opkt);
+                    if (os->oformat->flags & AVFMT_RAWPICTURE) {
+                        /* store AVPicture in AVPacket, as expected by the output format */
+                        avpicture_fill(&pict, opkt.data, ost->st->codec->pix_fmt, ost->st->codec->width, ost->st->codec->height);
+                        opkt.data = (uint8_t *)&pict;
+                        opkt.size = sizeof(AVPicture);
+                        opkt.flags |= AV_PKT_FLAG_KEY;
                     }
+                    write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
+                    ost->st->codec->frame_number++;
+                    ost->frame_number++;
+                    av_free_packet(&opkt);
+                }
 #if CONFIG_AVFILTER
-                    cont:
-                    frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
-                                       ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
+                cont:
+                frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
+                                   ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
+                if (ost->picref)
                     avfilter_unref_buffer(ost->picref);
-                }
+            }
 #endif
-                }
             }
 
         av_free(buffer_to_free);
@@ -1772,10 +1795,10 @@ static int output_packet(InputStream *ist, int ist_index,
         /* EOF handling */
 
         for(i=0;i<nb_ostreams;i++) {
-            ost = ost_table[i];
+            ost = &ost_table[i];
             if (ost->source_index == ist_index) {
                 AVCodecContext *enc= ost->st->codec;
-                os = output_files[ost->file_index];
+                os = output_files[ost->file_index].ctx;
 
                 if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1)
                     continue;
@@ -1856,105 +1879,66 @@ static int output_packet(InputStream *ist, int ist_index,
     return 0;
 }
 
-static void print_sdp(AVFormatContext **avc, int n)
+static void print_sdp(OutputFile *output_files, int n)
 {
     char sdp[2048];
+    int i;
+    AVFormatContext **avc = av_malloc(sizeof(*avc)*n);
+
+    if (!avc)
+        exit_program(1);
+    for (i = 0; i < n; i++)
+        avc[i] = output_files[i].ctx;
 
     av_sdp_create(avc, n, sdp, sizeof(sdp));
     printf("SDP:\n%s\n", sdp);
     fflush(stdout);
+    av_freep(&avc);
 }
 
 /*
  * The following code is the main loop of the file converter
  */
-static int transcode(AVFormatContext **output_files,
+static int transcode(OutputFile *output_files,
                      int nb_output_files,
                      InputFile *input_files,
                      int nb_input_files)
 {
-    int ret = 0, i, j, k, n, nb_ostreams = 0, step;
-
+    int ret = 0, i, j, step;
     AVFormatContext *is, *os;
     AVCodecContext *codec, *icodec;
-    OutputStream *ost, **ost_table = NULL;
+    OutputStream *ost;
     InputStream *ist;
     char error[1024];
     int key;
     int want_sdp = 1;
-    uint8_t no_packet[MAX_FILES]={0};
+    uint8_t *no_packet;
     int no_packet_count=0;
     int nb_frame_threshold[AVMEDIA_TYPE_NB]={0};
     int nb_streams[AVMEDIA_TYPE_NB]={0};
 
+    if (!(no_packet = av_mallocz(nb_input_files)))
+        exit_program(1);
+
     if (rate_emu)
         for (i = 0; i < nb_input_streams; i++)
             input_streams[i].start = av_gettime();
 
     /* output stream init */
-    nb_ostreams = 0;
     for(i=0;i<nb_output_files;i++) {
-        os = output_files[i];
+        os = output_files[i].ctx;
         if (!os->nb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) {
-            av_dump_format(output_files[i], i, output_files[i]->filename, 1);
+            av_dump_format(os, i, os->filename, 1);
             fprintf(stderr, "Output file #%d does not contain any stream\n", i);
             ret = AVERROR(EINVAL);
             goto fail;
         }
-        nb_ostreams += os->nb_streams;
-    }
-
-    ost_table = av_mallocz(sizeof(OutputStream *) * nb_ostreams);
-    if (!ost_table)
-        goto fail;
-
-    for(k=0;k<nb_output_files;k++) {
-        os = output_files[k];
-        for(i=0;i<os->nb_streams;i++,n++) {
-            nb_streams[os->streams[i]->codec->codec_type]++;
-        }
-    }
-    for(step=1<<30; step; step>>=1){
-        int found_streams[AVMEDIA_TYPE_NB]={0};
-        for(j=0; j<AVMEDIA_TYPE_NB; j++)
-            nb_frame_threshold[j] += step;
-
-        for(j=0; j<nb_input_streams; j++) {
-            int skip=0;
-            ist = &input_streams[j];
-            if(opt_programid){
-                int pi,si;
-                AVFormatContext *f= input_files[ ist->file_index ].ctx;
-                skip=1;
-                for(pi=0; pi<f->nb_programs; pi++){
-                    AVProgram *p= f->programs[pi];
-                    if(p->id == opt_programid)
-                        for(si=0; si<p->nb_stream_indexes; si++){
-                            if(f->streams[ p->stream_index[si] ] == ist->st)
-                                skip=0;
-                        }
-                }
-            }
-            if (ist->discard && ist->st->discard != AVDISCARD_ALL && !skip
-                && nb_frame_threshold[ist->st->codec->codec_type] <= ist->st->codec_info_nb_frames){
-                found_streams[ist->st->codec->codec_type]++;
-            }
-        }
-        for(j=0; j<AVMEDIA_TYPE_NB; j++)
-            if(found_streams[j] < nb_streams[j])
-                nb_frame_threshold[j] -= step;
-    }
-    n = 0;
-    for(k=0;k<nb_output_files;k++) {
-        os = output_files[k];
-        for (i = 0; i < os->nb_streams; i++, n++)
-            ost_table[n] = output_streams_for_file[k][i];
     }
 
     /* for each output stream, we compute the right encoding parameters */
-    for(i=0;i<nb_ostreams;i++) {
-        ost = ost_table[i];
-        os = output_files[ost->file_index];
+    for (i = 0; i < nb_output_streams; i++) {
+        ost = &output_streams[i];
+        os = output_files[ost->file_index].ctx;
         ist = &input_streams[ost->source_index];
 
         codec = ost->st->codec;
@@ -2176,8 +2160,8 @@ static int transcode(AVFormatContext **output_files,
     }
 
     /* open each encoder */
-    for(i=0;i<nb_ostreams;i++) {
-        ost = ost_table[i];
+    for (i = 0; i < nb_output_streams; i++) {
+        ost = &output_streams[i];
         if (ost->encoding_needed) {
             AVCodec *codec = ost->enc;
             AVCodecContext *dec = input_streams[ost->source_index].st->codec;
@@ -2224,6 +2208,7 @@ static int transcode(AVFormatContext **output_files,
                 ret = AVERROR(EINVAL);
                 goto dump_format;
             }
+
             if (avcodec_open2(ist->st->codec, codec, &ist->opts) < 0) {
                 snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d",
                         ist->file_index, ist->st->index);
@@ -2246,15 +2231,15 @@ static int transcode(AVFormatContext **output_files,
     }
 
     /* open files and write file headers */
-    for(i=0;i<nb_output_files;i++) {
-        os = output_files[i];
-        if (avformat_write_header(os, &output_opts[i]) < 0) {
+    for (i = 0; i < nb_output_files; i++) {
+        os = output_files[i].ctx;
+        if (avformat_write_header(os, &output_files[i].opts) < 0) {
             snprintf(error, sizeof(error), "Could not write header for output file #%d (incorrect codec parameters ?)", i);
             ret = AVERROR(EINVAL);
             goto dump_format;
         }
-//        assert_avoptions(output_opts[i]);
-        if (strcmp(output_files[i]->oformat->name, "rtp")) {
+//        assert_avoptions(output_files[i].opts);
+        if (strcmp(os->oformat->name, "rtp")) {
             want_sdp = 0;
         }
     }
@@ -2263,14 +2248,14 @@ static int transcode(AVFormatContext **output_files,
     /* dump the file output parameters - cannot be done before in case
        of stream copy */
     for(i=0;i<nb_output_files;i++) {
-        av_dump_format(output_files[i], i, output_files[i]->filename, 1);
+        av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1);
     }
 
     /* dump the stream mapping */
     if (verbose >= 0) {
         fprintf(stderr, "Stream mapping:\n");
-        for(i=0;i<nb_ostreams;i++) {
-            ost = ost_table[i];
+        for (i = 0; i < nb_output_streams;i ++) {
+            ost = &output_streams[i];
             fprintf(stderr, "  Stream #%d.%d -> #%d.%d",
                     input_streams[ost->source_index].file_index,
                     input_streams[ost->source_index].st->index,
@@ -2307,11 +2292,11 @@ static int transcode(AVFormatContext **output_files,
     for(; received_sigterm == 0;) {
         int file_index, ist_index;
         AVPacket pkt;
-        double ipts_min;
+        int64_t ipts_min;
         double opts_min;
 
     redo:
-        ipts_min= 1e100;
+        ipts_min = INT64_MAX;
         opts_min= 1e100;
         /* if 'q' pressed, exits */
         if (!using_stdin) {
@@ -2345,8 +2330,8 @@ static int transcode(AVFormatContext **output_files,
                 for(i=0;i<nb_input_streams;i++) {
                     input_streams[i].st->codec->debug = debug;
                 }
-                for(i=0;i<nb_ostreams;i++) {
-                    ost = ost_table[i];
+                for(i=0;i<nb_output_streams;i++) {
+                    ost = &output_streams[i];
                     ost->st->codec->debug = debug;
                 }
                 if(debug) av_log_set_level(AV_LOG_DEBUG);
@@ -2368,15 +2353,16 @@ static int transcode(AVFormatContext **output_files,
         /* select the stream that we must read now by looking at the
            smallest output pts */
         file_index = -1;
-        for(i=0;i<nb_ostreams;i++) {
-            double ipts, opts;
-            ost = ost_table[i];
-            os = output_files[ost->file_index];
+        for (i = 0; i < nb_output_streams; i++) {
+            int64_t ipts;
+            double  opts;
+            ost = &output_streams[i];
+            os = output_files[ost->file_index].ctx;
             ist = &input_streams[ost->source_index];
-            if(ist->is_past_recording_time || no_packet[ist->file_index])
+            if(ost->is_past_recording_time || no_packet[ist->file_index])
                 continue;
                 opts = ost->st->pts.val * av_q2d(ost->st->time_base);
-            ipts = (double)ist->pts;
+            ipts = ist->pts;
             if (!input_files[ist->file_index].eof_reached){
                 if(ipts < ipts_min) {
                     ipts_min = ipts;
@@ -2396,7 +2382,7 @@ static int transcode(AVFormatContext **output_files,
         if (file_index < 0) {
             if(no_packet_count){
                 no_packet_count=0;
-                memset(no_packet, 0, sizeof(no_packet));
+                memset(no_packet, 0, nb_input_files);
                 usleep(10000);
                 continue;
             }
@@ -2404,7 +2390,7 @@ static int transcode(AVFormatContext **output_files,
         }
 
         /* finish if limit size exhausted */
-        if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0]->pb))
+        if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0].ctx->pb))
             break;
 
         /* read a frame from it and output it in the fifo */
@@ -2424,7 +2410,7 @@ static int transcode(AVFormatContext **output_files,
         }
 
         no_packet_count=0;
-        memset(no_packet, 0, sizeof(no_packet));
+        memset(no_packet, 0, nb_input_files);
 
         if (do_pkt_dump) {
             av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump,
@@ -2467,19 +2453,8 @@ static int transcode(AVFormatContext **output_files,
             }
         }
 
-        /* finish if recording time exhausted */
-        if (recording_time != INT64_MAX &&
-            (pkt.pts != AV_NOPTS_VALUE ?
-                av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000})
-                    :
-                av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000})
-            )>= 0) {
-            ist->is_past_recording_time = 1;
-            goto discard_packet;
-        }
-
         //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
-        if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
+        if (output_packet(ist, ist_index, output_streams, nb_output_streams, &pkt) < 0) {
 
             if (verbose >= 0)
                 fprintf(stderr, "Error while decoding stream #%d.%d\n",
@@ -2494,14 +2469,14 @@ static int transcode(AVFormatContext **output_files,
         av_free_packet(&pkt);
 
         /* dump report by using the output first video and audio streams */
-        print_report(output_files, ost_table, nb_ostreams, 0);
+        print_report(output_files, output_streams, nb_output_streams, 0);
     }
 
     /* at the end of stream, we must flush the decoder buffers */
     for (i = 0; i < nb_input_streams; i++) {
         ist = &input_streams[i];
         if (ist->decoding_needed) {
-            output_packet(ist, i, ost_table, nb_ostreams, NULL);
+            output_packet(ist, i, output_streams, nb_output_streams, NULL);
         }
     }
 
@@ -2509,16 +2484,16 @@ static int transcode(AVFormatContext **output_files,
 
     /* write the trailer if needed and close file */
     for(i=0;i<nb_output_files;i++) {
-        os = output_files[i];
+        os = output_files[i].ctx;
         av_write_trailer(os);
     }
 
     /* dump report by using the first video and audio streams */
-    print_report(output_files, ost_table, nb_ostreams, 1);
+    print_report(output_files, output_streams, nb_output_streams, 1);
 
     /* close each encoder */
-    for(i=0;i<nb_ostreams;i++) {
-        ost = ost_table[i];
+    for (i = 0; i < nb_output_streams; i++) {
+        ost = &output_streams[i];
         if (ost->encoding_needed) {
             av_freep(&ost->st->codec->stats_in);
             avcodec_close(ost->st->codec);
@@ -2541,10 +2516,11 @@ static int transcode(AVFormatContext **output_files,
 
  fail:
     av_freep(&bit_buffer);
+    av_freep(&no_packet);
 
-    if (ost_table) {
-        for(i=0;i<nb_ostreams;i++) {
-            ost = ost_table[i];
+    if (output_streams) {
+        for (i = 0; i < nb_output_streams; i++) {
+            ost = &output_streams[i];
             if (ost) {
                 if (ost->st->stream_copy)
                     av_freep(&ost->st->codec->extradata);
@@ -2564,10 +2540,8 @@ static int transcode(AVFormatContext **output_files,
                 if (ost->reformat_ctx)
                     av_audio_convert_free(ost->reformat_ctx);
                 av_dict_free(&ost->opts);
-                av_free(ost);
             }
         }
-        av_free(ost_table);
     }
     return ret;
 }
@@ -2911,21 +2885,7 @@ static int opt_map_metadata(const char *opt, const char *arg)
 
 static int opt_input_ts_scale(const char *opt, const char *arg)
 {
-    unsigned int stream;
-    double scale;
-    char *p;
-
-    stream = strtol(arg, &p, 0);
-    if (*p)
-        p++;
-    scale= strtod(p, &p);
-
-    if(stream >= MAX_STREAMS)
-        exit_program(1);
-
-    ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1);
-    ts_scale[stream] = scale;
-    return 0;
+    return av_dict_set(&ts_scale, opt, arg, 0);
 }
 
 static int opt_recording_time(const char *opt, const char *arg)
@@ -2998,11 +2958,97 @@ static AVCodec *choose_codec(AVFormatContext *s, AVStream *st, enum AVMediaType
     return NULL;
 }
 
+/**
+ * Add all the streams from the given input file to the global
+ * list of input streams.
+ */
+static void add_input_streams(AVFormatContext *ic)
+{
+    int i, rfps, rfps_base, ret;
+
+    for (i = 0; i < ic->nb_streams; i++) {
+        AVStream *st = ic->streams[i];
+        AVCodecContext *dec = st->codec;
+        AVDictionaryEntry *e = NULL;
+        InputStream *ist;
+        char *scale = NULL;
+
+        dec->thread_count = thread_count;
+
+        input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
+        ist = &input_streams[nb_input_streams - 1];
+        ist->st = st;
+        ist->file_index = nb_input_files;
+        ist->discard = 1;
+        ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
+
+        while (e = av_dict_get(ts_scale, "", e, AV_DICT_IGNORE_SUFFIX)) {
+            char *p = strchr(e->key, ':');
+
+            if ((ret = check_stream_specifier(ic, st, p ? p + 1 : "")) > 0)
+                scale = e->value;
+            else if (ret < 0)
+                exit_program(1);
+        }
+        if (scale)
+            ist->ts_scale = strtod(scale, NULL);
+
+        ist->dec = choose_codec(ic, st, dec->codec_type, codec_names);
+
+        switch (dec->codec_type) {
+        case AVMEDIA_TYPE_AUDIO:
+            if(!ist->dec)
+                ist->dec = avcodec_find_decoder(dec->codec_id);
+            if(audio_disable)
+                st->discard= AVDISCARD_ALL;
+            break;
+        case AVMEDIA_TYPE_VIDEO:
+            if(!ist->dec)
+                ist->dec = avcodec_find_decoder(dec->codec_id);
+            rfps      = ic->streams[i]->r_frame_rate.num;
+            rfps_base = ic->streams[i]->r_frame_rate.den;
+            if (dec->lowres) {
+                dec->flags |= CODEC_FLAG_EMU_EDGE;
+            }
+            if(me_threshold)
+                dec->debug |= FF_DEBUG_MV;
+
+            if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->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)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
+
+                    (float)rfps / rfps_base, rfps, rfps_base);
+            }
+
+            if(video_disable)
+                st->discard= AVDISCARD_ALL;
+            else if(video_discard)
+                st->discard= video_discard;
+            break;
+        case AVMEDIA_TYPE_DATA:
+            break;
+        case AVMEDIA_TYPE_SUBTITLE:
+            if(!ist->dec)
+                ist->dec = avcodec_find_decoder(dec->codec_id);
+            if(subtitle_disable)
+                st->discard = AVDISCARD_ALL;
+            break;
+        case AVMEDIA_TYPE_ATTACHMENT:
+        case AVMEDIA_TYPE_UNKNOWN:
+            break;
+        default:
+            abort();
+        }
+    }
+}
+
 static int opt_input_file(const char *opt, const char *filename)
 {
     AVFormatContext *ic;
     AVInputFormat *file_iformat = NULL;
-    int err, i, ret, rfps, rfps_base;
+    int err, i, ret;
     int64_t timestamp;
     uint8_t buf[128];
     AVDictionary **opts;
@@ -3115,72 +3161,7 @@ static int opt_input_file(const char *opt, const char *filename)
     }
 
     /* update the current parameters so that they match the one of the input stream */
-    for(i=0;i<ic->nb_streams;i++) {
-        AVStream *st = ic->streams[i];
-        AVCodecContext *dec = st->codec;
-        InputStream *ist;
-
-        dec->thread_count = thread_count;
-
-        input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1);
-        ist = &input_streams[nb_input_streams - 1];
-        ist->st = st;
-        ist->file_index = nb_input_files;
-        ist->discard = 1;
-        ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
-
-        if (i < nb_ts_scale)
-            ist->ts_scale = ts_scale[i];
-
-        ist->dec = choose_codec(ic, st, dec->codec_type, codec_names);
-
-        switch (dec->codec_type) {
-        case AVMEDIA_TYPE_AUDIO:
-            if(!ist->dec)
-                ist->dec = avcodec_find_decoder(dec->codec_id);
-            if(audio_disable)
-                st->discard= AVDISCARD_ALL;
-            break;
-        case AVMEDIA_TYPE_VIDEO:
-            if(!ist->dec)
-                ist->dec = avcodec_find_decoder(dec->codec_id);
-            rfps      = ic->streams[i]->r_frame_rate.num;
-            rfps_base = ic->streams[i]->r_frame_rate.den;
-            if (dec->lowres) {
-                dec->flags |= CODEC_FLAG_EMU_EDGE;
-            }
-            if(me_threshold)
-                dec->debug |= FF_DEBUG_MV;
-
-            if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->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)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num,
-
-                    (float)rfps / rfps_base, rfps, rfps_base);
-            }
-
-            if(video_disable)
-                st->discard= AVDISCARD_ALL;
-            else if(video_discard)
-                st->discard= video_discard;
-            break;
-        case AVMEDIA_TYPE_DATA:
-            break;
-        case AVMEDIA_TYPE_SUBTITLE:
-            if(!ist->dec)
-                ist->dec = avcodec_find_decoder(dec->codec_id);
-            if(subtitle_disable)
-                st->discard = AVDISCARD_ALL;
-            break;
-        case AVMEDIA_TYPE_ATTACHMENT:
-        case AVMEDIA_TYPE_UNKNOWN:
-            break;
-        default:
-            abort();
-        }
-    }
+    add_input_streams(ic);
 
     /* dump the file content */
     if (verbose >= 0)
@@ -3200,8 +3181,7 @@ static int opt_input_file(const char *opt, const char *filename)
     audio_sample_rate = 0;
     audio_channels    = 0;
     audio_sample_fmt  = AV_SAMPLE_FMT_NONE;
-    av_freep(&ts_scale);
-    nb_ts_scale = 0;
+    av_dict_free(&ts_scale);
 
     for (i = 0; i < orig_nb_streams; i++)
         av_dict_free(&opts[i]);
@@ -3246,17 +3226,9 @@ static OutputStream *new_output_stream(AVFormatContext *oc, enum AVMediaType typ
         exit_program(1);
     }
 
-    output_streams_for_file[nb_output_files] =
-        grow_array(output_streams_for_file[nb_output_files],
-                   sizeof(*output_streams_for_file[nb_output_files]),
-                   &nb_output_streams_for_file[nb_output_files],
-                   oc->nb_streams);
-    ost = output_streams_for_file[nb_output_files][idx] =
-        av_mallocz(sizeof(OutputStream));
-    if (!ost) {
-        fprintf(stderr, "Could not alloc output stream\n");
-        exit_program(1);
-    }
+    output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams,
+                                nb_output_streams + 1);
+    ost = &output_streams[nb_output_streams - 1];
     ost->file_index = nb_output_files;
     ost->index = idx;
     ost->st    = st;
@@ -3516,7 +3488,7 @@ static int opt_streamid(const char *opt, const char *arg)
 static int copy_chapters(int infile, int outfile)
 {
     AVFormatContext *is = input_files[infile].ctx;
-    AVFormatContext *os = output_files[outfile];
+    AVFormatContext *os = output_files[outfile].ctx;
     int i;
 
     for (i = 0; i < is->nb_chapters; i++) {
@@ -3595,11 +3567,6 @@ static int opt_output_file(const char *opt, const char *filename)
     OutputStream *ost;
     InputStream  *ist;
 
-    if(nb_output_files >= FF_ARRAY_ELEMS(output_files)){
-        fprintf(stderr, "Too many output files\n");
-        exit_program(1);
-    }
-
     if (!strcmp(filename, "-"))
         filename = "pipe:";
 
@@ -3697,8 +3664,13 @@ static int opt_output_file(const char *opt, const char *filename)
     av_dict_copy(&oc->metadata, metadata, 0);
     av_dict_free(&metadata);
 
-    av_dict_copy(&output_opts[nb_output_files], format_opts, 0);
-    output_files[nb_output_files++] = oc;
+
+    output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1);
+    output_files[nb_output_files - 1].ctx       = oc;
+    output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams;
+    output_files[nb_output_files - 1].recording_time = recording_time;
+    output_files[nb_output_files - 1].start_time     = start_time;
+    av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0);
 
     /* check filename in case of an image number is expected */
     if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
@@ -3810,9 +3782,9 @@ static int opt_output_file(const char *opt, const char *filename)
         av_dict_copy(&oc->metadata, input_files[0].ctx->metadata,
                      AV_DICT_DONT_OVERWRITE);
     if (metadata_streams_autocopy)
-        for (i = 0; i < oc->nb_streams; i++) {
-            InputStream *ist = &input_streams[output_streams_for_file[nb_output_files-1][i]->source_index];
-            av_dict_copy(&oc->streams[i]->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
+        for (i = output_files[nb_output_files - 1].ost_index; i < nb_output_streams; i++) {
+            InputStream *ist = &input_streams[output_streams[i].source_index];
+            av_dict_copy(&output_streams[i].st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE);
         }
 
     frame_rate    = (AVRational){0, 0};
@@ -3822,6 +3794,8 @@ static int opt_output_file(const char *opt, const char *filename)
     audio_channels    = 0;
     audio_sample_fmt  = AV_SAMPLE_FMT_NONE;
     chapters_input_file = INT_MAX;
+    recording_time = INT64_MAX;
+    start_time     = 0;
 
     av_freep(&meta_data_maps);
     nb_meta_data_maps = 0;
@@ -4203,7 +4177,7 @@ static const OptionDef options[] = {
     { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, //
     { "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" },
     { "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" },
-    { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" },
+    { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "scale" },
     { "metadata", HAS_ARG, {(void*)opt_metadata}, "add metadata", "string=string" },
     { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[AVMEDIA_TYPE_DATA]}, "set the number of data frames to record", "number" },
     { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
index c5045b1..1708e1b 100644 (file)
@@ -260,6 +260,8 @@ library:
     @tab Multimedia format used in Westwood Studios games.
 @item Westwood Studios VQA      @tab   @tab X
     @tab Multimedia format used in Westwood Studios games.
+@item XMV                       @tab   @tab X
+    @tab Microsoft video container used in Xbox games.
 @item xWMA                      @tab   @tab X
     @tab Microsoft audio container used by XAudio 2.
 @item YUV4MPEG pipe             @tab X @tab X
index e895b78..8e2c29f 100644 (file)
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -736,7 +736,6 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
 {
     int i, err;
     AVFormatContext *ic = NULL;
-    int nopts = 0;
 
     err = avformat_open_input(&ic, filename, NULL, NULL);
     if (err < 0)
@@ -768,9 +767,6 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
             } else
                 choose_pixel_fmt(st, codec);
         }
-
-        if(st->codec->flags & CODEC_FLAG_BITEXACT)
-            nopts = 1;
     }
 
     av_close_input_file(ic);
@@ -1725,6 +1721,14 @@ static int output_packet(InputStream *ist, int ist_index,
                 int frame_size;
 
                 ost = ost_table[i];
+
+                /* finish if recording time exhausted */
+                if (recording_time != INT64_MAX &&
+                        av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000})
+                    >= 0) {
+                    ist->is_past_recording_time = 1;
+                    continue;
+                }
                 if (ost->source_index == ist_index) {
 #if CONFIG_AVFILTER
                 frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO ||
@@ -2804,17 +2808,6 @@ static int transcode(AVFormatContext **output_files,
             }
         }
 
-        /* finish if recording time exhausted */
-        if (recording_time != INT64_MAX &&
-            (pkt.pts != AV_NOPTS_VALUE ?
-                av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000})
-                    :
-                av_compare_ts(ist->pts, AV_TIME_BASE_Q, recording_time + start_time, (AVRational){1, 1000000})
-            )>= 0) {
-            ist->is_past_recording_time = 1;
-            goto discard_packet;
-        }
-
         //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
         if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
 
index e0e19a2..147c1b3 100644 (file)
@@ -635,6 +635,8 @@ OBJS-$(CONFIG_MPEGVIDEO_PARSER)        += mpegvideo_parser.o    \
                                           mpeg12.o mpeg12data.o \
                                           mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_PNM_PARSER)              += pnm_parser.o pnm.o
+OBJS-$(CONFIG_RV30_PARSER)             += rv34_parser.o
+OBJS-$(CONFIG_RV40_PARSER)             += rv34_parser.o
 OBJS-$(CONFIG_VC1_PARSER)              += vc1_parser.o vc1.o vc1data.o \
                                           msmpeg4.o msmpeg4data.o mpeg4video.o \
                                           h263.o mpegvideo.o error_resilience.o
index 8995501..8ca6181 100644 (file)
@@ -409,6 +409,8 @@ void avcodec_register_all(void)
     REGISTER_PARSER  (MPEGAUDIO, mpegaudio);
     REGISTER_PARSER  (MPEGVIDEO, mpegvideo);
     REGISTER_PARSER  (PNM, pnm);
+    REGISTER_PARSER  (RV30, rv30);
+    REGISTER_PARSER  (RV40, rv40);
     REGISTER_PARSER  (VC1, vc1);
     REGISTER_PARSER  (VP3, vp3);
     REGISTER_PARSER  (VP8, vp8);
index 3a59d5f..0f91020 100644 (file)
@@ -655,7 +655,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
 
     print_short_term(h);
     print_long_term(h);
-    return err;
+    return h->s.avctx->error_recognition >= FF_ER_EXPLODE ? err : 0;
 }
 
 int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb){
diff --git a/libavcodec/rv34_parser.c b/libavcodec/rv34_parser.c
new file mode 100644 (file)
index 0000000..ce86043
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * RV30/40 parser
+ * Copyright (c) 2011 Konstantin Shishkov
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * RV30/40 parser
+ */
+
+#include "parser.h"
+#include "libavutil/intreadwrite.h"
+
+typedef struct {
+    ParseContext pc;
+    int64_t key_dts;
+    int key_pts;
+} RV34ParseContext;
+
+static const int rv_to_av_frame_type[4] = {
+    AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B,
+};
+
+static int rv34_parse(AVCodecParserContext *s,
+                      AVCodecContext *avctx,
+                      const uint8_t **poutbuf, int *poutbuf_size,
+                      const uint8_t *buf, int buf_size)
+{
+    RV34ParseContext *pc = s->priv_data;
+    int type, pts, hdr;
+
+    if (buf_size < 13 + *buf * 8) {
+        *poutbuf = buf;
+        *poutbuf_size = buf_size;
+        return buf_size;
+    }
+
+    hdr = AV_RB32(buf + 9 + *buf * 8);
+    if (avctx->codec_id == CODEC_ID_RV30) {
+        type = (hdr >> 27) & 3;
+        pts  = (hdr >>  7) & 0x1FFF;
+    } else {
+        type = (hdr >> 29) & 3;
+        pts  = (hdr >>  6) & 0x1FFF;
+    }
+
+    if (type != 3 && s->pts != AV_NOPTS_VALUE) {
+        pc->key_dts = s->pts;
+        pc->key_pts = pts;
+    } else {
+        if (type != 3)
+            s->pts = pc->key_dts + ((pts - pc->key_pts) & 0x1FFF);
+        else
+            s->pts = pc->key_dts - ((pc->key_pts - pts) & 0x1FFF);
+    }
+    s->pict_type = rv_to_av_frame_type[type];
+
+    *poutbuf = buf;
+    *poutbuf_size = buf_size;
+    return buf_size;
+}
+
+#ifdef CONFIG_RV30_PARSER
+AVCodecParser ff_rv30_parser = {
+    { CODEC_ID_RV30 },
+    sizeof(RV34ParseContext),
+    NULL,
+    rv34_parse,
+};
+#endif
+
+#ifdef CONFIG_RV40_PARSER
+AVCodecParser ff_rv40_parser = {
+    { CODEC_ID_RV40 },
+    sizeof(RV34ParseContext),
+    NULL,
+    rv34_parse,
+};
+#endif
index 1f5a4f6..794b549 100644 (file)
@@ -20,6 +20,7 @@
 ;******************************************************************************
 
 %include "x86inc.asm"
+%include "x86util.asm"
 
 SECTION_RODATA
 pb_f: times 16 db 15
@@ -1054,39 +1055,6 @@ emu_edge mmx
 ;                           int32_t max, unsigned int len)
 ;-----------------------------------------------------------------------------
 
-%macro PMINSD_MMX 3 ; dst, src, tmp
-    mova      %3, %2
-    pcmpgtd   %3, %1
-    pxor      %1, %2
-    pand      %1, %3
-    pxor      %1, %2
-%endmacro
-
-%macro PMAXSD_MMX 3 ; dst, src, tmp
-    mova      %3, %1
-    pcmpgtd   %3, %2
-    pand      %1, %3
-    pandn     %3, %2
-    por       %1, %3
-%endmacro
-
-%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp
-    PMINSD_MMX %1, %3, %4
-    PMAXSD_MMX %1, %2, %4
-%endmacro
-
-%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused
-    cvtdq2ps  %1, %1
-    minps     %1, %3
-    maxps     %1, %2
-    cvtps2dq  %1, %1
-%endmacro
-
-%macro CLIPD_SSE41 3-4 ;  src/dst, min, max, unused
-    pminsd  %1, %3
-    pmaxsd  %1, %2
-%endmacro
-
 %macro SPLATD_MMX 1
     punpckldq  %1, %1
 %endmacro
index 9f5bfb4..d597c62 100644 (file)
@@ -305,6 +305,7 @@ OBJS-$(CONFIG_WTV_DEMUXER)               += wtvdec.o wtv.o asfdec.o asf.o asfcry
                                             avlanguage.o mpegts.o isom.o riff.o
 OBJS-$(CONFIG_WV_DEMUXER)                += wv.o apetag.o
 OBJS-$(CONFIG_XA_DEMUXER)                += xa.o
+OBJS-$(CONFIG_XMV_DEMUXER)               += xmv.o
 OBJS-$(CONFIG_XWMA_DEMUXER)              += xwma.o riff.o
 OBJS-$(CONFIG_YOP_DEMUXER)               += yop.o
 OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER)        += yuv4mpeg.o
index a9fa117..c64c355 100644 (file)
@@ -227,6 +227,7 @@ void av_register_all(void)
     REGISTER_DEMUXER  (WTV, wtv);
     REGISTER_DEMUXER  (WV, wv);
     REGISTER_DEMUXER  (XA, xa);
+    REGISTER_DEMUXER  (XMV, xmv);
     REGISTER_DEMUXER  (XWMA, xwma);
     REGISTER_DEMUXER  (YOP, yop);
     REGISTER_MUXDEMUX (YUV4MPEGPIPE, yuv4mpegpipe);
index 461c45c..7f25af7 100644 (file)
@@ -293,20 +293,21 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb,
 //        av_log(s, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0'));
         if (st->codec->codec_id == CODEC_ID_NONE)
             goto fail1;
-        st->codec->width = avio_rb16(pb);
+        st->codec->width  = avio_rb16(pb);
         st->codec->height = avio_rb16(pb);
-        st->codec->time_base.num= 1;
-        fps= avio_rb16(pb);
+        avio_skip(pb, 2); // looks like bits per sample
+        avio_skip(pb, 4); // always zero?
         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
-        avio_rb32(pb);
-        avio_skip(pb, 2);
-        avio_rb16(pb);
+        st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS;
+        fps = avio_rb32(pb);
 
         if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0)
             return ret;
 
-//        av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2);
-        st->codec->time_base.den = fps * st->codec->time_base.num;
+        av_reduce(&st->codec->time_base.num, &st->codec->time_base.den,
+                  0x10000, fps, (1 << 30) - 1);
+        st->avg_frame_rate.num = st->codec->time_base.den;
+        st->avg_frame_rate.den = st->codec->time_base.num;
     }
 
 skip:
@@ -570,7 +571,8 @@ skip:
 
 static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
                                    RMDemuxContext *rm, RMStream *vst,
-                                   AVPacket *pkt, int len, int *pseq)
+                                   AVPacket *pkt, int len, int *pseq,
+                                   int64_t *timestamp)
 {
     int hdr, seq, pic_num, len2, pos;
     int type;
@@ -590,8 +592,10 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb,
         return -1;
     rm->remaining_len = len;
     if(type&1){     // frame, not slice
-        if(type == 3)  // frame as a part of packet
+        if(type == 3){  // frame as a part of packet
             len= len2;
+            *timestamp = pos;
+        }
         if(rm->remaining_len < len)
             return -1;
         rm->remaining_len -= len;
@@ -699,7 +703,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
 
     if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
         rm->current_stream= st->id;
-        if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq))
+        if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, &timestamp))
             return -1; //got partial frame
     } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
         if ((st->codec->codec_id == CODEC_ID_RA_288) ||
@@ -774,7 +778,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb,
     }
 #endif
 
-    pkt->pts= timestamp;
+    pkt->pts = timestamp;
     if (flags & 2)
         pkt->flags |= AV_PKT_FLAG_KEY;
 
index 5b6031b..f811c31 100644 (file)
@@ -24,7 +24,7 @@
 #include "libavutil/avutil.h"
 
 #define LIBAVFORMAT_VERSION_MAJOR 53
-#define LIBAVFORMAT_VERSION_MINOR  7
+#define LIBAVFORMAT_VERSION_MINOR  8
 #define LIBAVFORMAT_VERSION_MICRO  0
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
diff --git a/libavformat/xmv.c b/libavformat/xmv.c
new file mode 100644 (file)
index 0000000..a6081af
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ * Microsoft XMV demuxer
+ * Copyright (c) 2011 Sven Hesse <drmccoy@drmccoy.de>
+ * Copyright (c) 2011 Matthew Hoops <clone2727@gmail.com>
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Microsoft XMV demuxer
+ */
+
+#include <stdint.h>
+
+#include "libavutil/intreadwrite.h"
+
+#include "avformat.h"
+#include "riff.h"
+
+#define XMV_MIN_HEADER_SIZE 36
+
+#define XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT 1
+#define XMV_AUDIO_ADPCM51_FRONTCENTERLOW 2
+#define XMV_AUDIO_ADPCM51_REARLEFTRIGHT  4
+
+#define XMV_AUDIO_ADPCM51 (XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT | \
+                           XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \
+                           XMV_AUDIO_ADPCM51_REARLEFTRIGHT)
+
+typedef struct XMVAudioTrack {
+    uint16_t compression;
+    uint16_t channels;
+    uint32_t sample_rate;
+    uint16_t bits_per_sample;
+    uint32_t bit_rate;
+    uint16_t flags;
+    uint16_t block_align;
+    uint16_t block_samples;
+
+    enum CodecID codec_id;
+} XMVAudioTrack;
+
+typedef struct XMVVideoPacket {
+    /* The decoder stream index for this video packet. */
+    int stream_index;
+
+    uint32_t data_size;
+    uint32_t data_offset;
+
+    uint32_t current_frame;
+    uint32_t frame_count;
+
+    /* Does the video packet contain extra data? */
+    int has_extradata;
+
+    /* Extra data */
+    uint8_t extradata[4];
+
+    int64_t last_pts;
+    int64_t pts;
+} XMVVideoPacket;
+
+typedef struct XMVAudioPacket {
+    /* The decoder stream index for this audio packet. */
+    int stream_index;
+
+    /* The audio track this packet encodes. */
+    XMVAudioTrack *track;
+
+    uint32_t data_size;
+    uint32_t data_offset;
+
+    uint32_t frame_size;
+
+    uint32_t block_count;
+} XMVAudioPacket;
+
+typedef struct XMVDemuxContext {
+    uint16_t audio_track_count;
+
+    XMVAudioTrack *audio_tracks;
+
+    uint32_t this_packet_size;
+    uint32_t next_packet_size;
+
+    uint32_t this_packet_offset;
+    uint32_t next_packet_offset;
+
+    uint16_t current_stream;
+    uint16_t stream_count;
+
+    XMVVideoPacket  video;
+    XMVAudioPacket *audio;
+} XMVDemuxContext;
+
+static int xmv_probe(AVProbeData *p)
+{
+    uint32_t file_version;
+
+    if (p->buf_size < XMV_MIN_HEADER_SIZE)
+        return 0;
+
+    file_version = AV_RL32(p->buf + 16);
+    if ((file_version == 0) || (file_version > 4))
+        return 0;
+
+    if (!memcmp(p->buf + 12, "xobX", 4))
+        return AVPROBE_SCORE_MAX;
+
+    return 0;
+}
+
+static int xmv_read_header(AVFormatContext *s,
+                           AVFormatParameters *ap)
+{
+    XMVDemuxContext *xmv = s->priv_data;
+    AVIOContext     *pb  = s->pb;
+    AVStream        *vst = NULL;
+
+    uint32_t file_version;
+    uint32_t this_packet_size;
+    uint16_t audio_track;
+
+    avio_skip(pb, 4); /* Next packet size */
+
+    this_packet_size = avio_rl32(pb);
+
+    avio_skip(pb, 4); /* Max packet size */
+    avio_skip(pb, 4); /* "xobX" */
+
+    file_version = avio_rl32(pb);
+    if ((file_version != 4) && (file_version != 2))
+        av_log_ask_for_sample(s, "Found uncommon version %d\n", file_version);
+
+
+    /* Video track */
+
+    vst = av_new_stream(s, 0);
+    if (!vst)
+        return AVERROR(ENOMEM);
+
+    av_set_pts_info(vst, 32, 1, 1000);
+
+    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+    vst->codec->codec_id   = CODEC_ID_WMV2;
+    vst->codec->codec_tag  = MKBETAG('W', 'M', 'V', '2');
+    vst->codec->width      = avio_rl32(pb);
+    vst->codec->height     = avio_rl32(pb);
+
+    vst->duration          = avio_rl32(pb);
+
+    xmv->video.stream_index = vst->index;
+
+    /* Audio tracks */
+
+    xmv->audio_track_count = avio_rl16(pb);
+
+    avio_skip(pb, 2); /* Unknown (padding?) */
+
+    xmv->audio_tracks = av_malloc(xmv->audio_track_count * sizeof(XMVAudioTrack));
+    if (!xmv->audio_tracks)
+        return AVERROR(ENOMEM);
+
+    xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket));
+    if (!xmv->audio)
+        return AVERROR(ENOMEM);
+
+    for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
+        XMVAudioTrack  *track  = &xmv->audio_tracks[audio_track];
+        XMVAudioPacket *packet = &xmv->audio       [audio_track];
+        AVStream *ast = NULL;
+
+        track->compression     = avio_rl16(pb);
+        track->channels        = avio_rl16(pb);
+        track->sample_rate     = avio_rl32(pb);
+        track->bits_per_sample = avio_rl16(pb);
+        track->flags           = avio_rl16(pb);
+
+        track->bit_rate      = track->bits_per_sample *
+                               track->sample_rate *
+                               track->channels;
+        track->block_align   = 36 * track->channels;
+        track->block_samples = 64;
+        track->codec_id      = ff_wav_codec_get_id(track->compression,
+                                                   track->bits_per_sample);
+
+        packet->track        = track;
+        packet->stream_index = -1;
+
+        packet->frame_size  = 0;
+        packet->block_count = 0;
+
+        /* TODO: ADPCM'd 5.1 sound is encoded in three separate streams.
+         *       Those need to be interleaved to a proper 5.1 stream. */
+        if (track->flags & XMV_AUDIO_ADPCM51)
+            av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream "
+                                      "(0x%04X)\n", track->flags);
+
+        ast = av_new_stream(s, audio_track);
+        if (!ast)
+            return AVERROR(ENOMEM);
+
+        ast->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
+        ast->codec->codec_id              = track->codec_id;
+        ast->codec->codec_tag             = track->compression;
+        ast->codec->channels              = track->channels;
+        ast->codec->sample_rate           = track->sample_rate;
+        ast->codec->bits_per_coded_sample = track->bits_per_sample;
+        ast->codec->bit_rate              = track->bit_rate;
+        ast->codec->block_align           = 36 * track->channels;
+
+        av_set_pts_info(ast, 32, track->block_samples, track->sample_rate);
+
+        packet->stream_index = ast->index;
+
+        ast->duration = vst->duration;
+    }
+
+
+    /** Initialize the packet context */
+
+    xmv->next_packet_offset = avio_tell(pb);
+
+    xmv->next_packet_size = this_packet_size - xmv->next_packet_offset;
+    xmv->this_packet_size = 0;
+
+    xmv->video.current_frame = 0;
+    xmv->video.frame_count   = 0;
+    xmv->video.pts           = 0;
+    xmv->video.last_pts      = 0;
+
+    xmv->current_stream = 0;
+    xmv->stream_count   = xmv->audio_track_count + 1;
+
+    return 0;
+}
+
+static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb)
+{
+    /* Read the XMV extradata */
+
+    uint32_t data = avio_rl32(pb);
+
+    int mspel_bit        = !!(data & 0x01);
+    int loop_filter      = !!(data & 0x02);
+    int abt_flag         = !!(data & 0x04);
+    int j_type_bit       = !!(data & 0x08);
+    int top_left_mv_flag = !!(data & 0x10);
+    int per_mb_rl_bit    = !!(data & 0x20);
+    int slice_count      = (data >> 6) & 7;
+
+    /* Write it back as standard WMV2 extradata */
+
+    data = 0;
+
+    data |= mspel_bit        << 15;
+    data |= loop_filter      << 14;
+    data |= abt_flag         << 13;
+    data |= j_type_bit       << 12;
+    data |= top_left_mv_flag << 11;
+    data |= per_mb_rl_bit    << 10;
+    data |= slice_count      <<  7;
+
+    AV_WB32(extradata, data);
+}
+
+static int xmv_process_packet_header(AVFormatContext *s)
+{
+    XMVDemuxContext *xmv = s->priv_data;
+    AVIOContext     *pb  = s->pb;
+
+    uint8_t  data[8];
+    uint16_t audio_track;
+    uint32_t data_offset;
+
+    /* Next packet size */
+    xmv->next_packet_size = avio_rl32(pb);
+
+    /* Packet video header */
+
+    if (avio_read(pb, data, 8) != 8)
+        return AVERROR(EIO);
+
+    xmv->video.data_size     = AV_RL32(data) & 0x007FFFFF;
+
+    xmv->video.current_frame = 0;
+    xmv->video.frame_count   = (AV_RL32(data) >> 23) & 0xFF;
+
+    xmv->video.has_extradata = (data[3] & 0x80) != 0;
+
+    /* Adding the audio data sizes and the video data size keeps you 4 bytes
+     * short for every audio track. But as playing around with XMV files with
+     * ADPCM audio showed, taking the extra 4 bytes from the audio data gives
+     * you either completely distorted audio or click (when skipping the
+     * remaining 68 bytes of the ADPCM block). Substracting 4 bytes for every
+     * audio track from the video data works at least for the audio. Probably
+     * some alignment thing?
+     * The video data has (always?) lots of padding, so it should work out...
+     */
+    xmv->video.data_size -= xmv->audio_track_count * 4;
+
+    xmv->current_stream = 0;
+    if (!xmv->video.frame_count) {
+        xmv->video.frame_count = 1;
+        xmv->current_stream    = 1;
+    }
+
+    /* Packet audio header */
+
+    for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
+        XMVAudioPacket *packet = &xmv->audio[audio_track];
+
+        if (avio_read(pb, data, 4) != 4)
+            return AVERROR(EIO);
+
+        packet->data_size = AV_RL32(data) & 0x007FFFFF;
+        if ((packet->data_size == 0) && (audio_track != 0))
+            /* This happens when I create an XMV with several identical audio
+             * streams. From the size calculations, duplicating the previous
+             * stream's size works out, but the track data itself is silent.
+             * Maybe this should also redirect the offset to the previous track?
+             */
+            packet->data_size = xmv->audio[audio_track - 1].data_size;
+
+        /** Carve up the audio data in frame_count slices */
+        packet->frame_size  = packet->data_size  / xmv->video.frame_count;
+        packet->frame_size -= packet->frame_size % packet->track->block_align;
+    }
+
+    /* Packet data offsets */
+
+    data_offset = avio_tell(pb);
+
+    xmv->video.data_offset = data_offset;
+    data_offset += xmv->video.data_size;
+
+    for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) {
+        xmv->audio[audio_track].data_offset = data_offset;
+        data_offset += xmv->audio[audio_track].data_size;
+    }
+
+    /* Video frames header */
+
+    /* Read new video extra data */
+    if (xmv->video.data_size > 0) {
+        if (xmv->video.has_extradata) {
+            xmv_read_extradata(xmv->video.extradata, pb);
+
+            xmv->video.data_size   -= 4;
+            xmv->video.data_offset += 4;
+
+            if (xmv->video.stream_index >= 0) {
+                AVStream *vst = s->streams[xmv->video.stream_index];
+
+                assert(xmv->video.stream_index < s->nb_streams);
+
+                if (vst->codec->extradata_size < 4) {
+                    av_free(vst->codec->extradata);
+
+                    vst->codec->extradata =
+                        av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE);
+                    vst->codec->extradata_size = 4;
+                }
+
+                memcpy(vst->codec->extradata, xmv->video.extradata, 4);
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int xmv_fetch_new_packet(AVFormatContext *s)
+{
+    XMVDemuxContext *xmv = s->priv_data;
+    AVIOContext     *pb  = s->pb;
+    int result;
+
+    /* Seek to it */
+    xmv->this_packet_offset = xmv->next_packet_offset;
+    if (avio_seek(pb, xmv->this_packet_offset, SEEK_SET) != xmv->this_packet_offset)
+        return AVERROR(EIO);
+
+    /* Update the size */
+    xmv->this_packet_size = xmv->next_packet_size;
+    if (xmv->this_packet_size < (12 + xmv->audio_track_count * 4))
+        return AVERROR(EIO);
+
+    /* Process the header */
+    result = xmv_process_packet_header(s);
+    if (result)
+        return result;
+
+    /* Update the offset */
+    xmv->next_packet_offset = xmv->this_packet_offset + xmv->this_packet_size;
+
+    return 0;
+}
+
+static int xmv_fetch_audio_packet(AVFormatContext *s,
+                                  AVPacket *pkt, uint32_t stream)
+{
+    XMVDemuxContext *xmv   = s->priv_data;
+    AVIOContext     *pb    = s->pb;
+    XMVAudioPacket  *audio = &xmv->audio[stream];
+
+    uint32_t data_size;
+    uint32_t block_count;
+    int result;
+
+    /* Seek to it */
+    if (avio_seek(pb, audio->data_offset, SEEK_SET) != audio->data_offset)
+        return AVERROR(EIO);
+
+    if ((xmv->video.current_frame + 1) < xmv->video.frame_count)
+        /* Not the last frame, get at most frame_size bytes. */
+        data_size = FFMIN(audio->frame_size, audio->data_size);
+    else
+        /* Last frame, get the rest. */
+        data_size = audio->data_size;
+
+    /* Read the packet */
+    result = av_get_packet(pb, pkt, data_size);
+    if (result <= 0)
+        return result;
+
+    pkt->stream_index = audio->stream_index;
+
+    /* Calculate the PTS */
+
+    block_count = data_size / audio->track->block_align;
+
+    pkt->duration = block_count;
+    pkt->pts      = audio->block_count;
+    pkt->dts      = AV_NOPTS_VALUE;
+
+    audio->block_count += block_count;
+
+    /* Advance offset */
+    audio->data_size   -= data_size;
+    audio->data_offset += data_size;
+
+    return 0;
+}
+
+static int xmv_fetch_video_packet(AVFormatContext *s,
+                                  AVPacket *pkt)
+{
+    XMVDemuxContext *xmv   = s->priv_data;
+    AVIOContext     *pb    = s->pb;
+    XMVVideoPacket  *video = &xmv->video;
+
+    int result;
+    uint32_t frame_header;
+    uint32_t frame_size, frame_timestamp;
+    uint32_t i;
+
+    /* Seek to it */
+    if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset)
+        return AVERROR(EIO);
+
+    /* Read the frame header */
+    frame_header = avio_rl32(pb);
+
+    frame_size      = (frame_header & 0x1FFFF) * 4 + 4;
+    frame_timestamp = (frame_header >> 17);
+
+    if ((frame_size + 4) > video->data_size)
+        return AVERROR(EIO);
+
+    /* Create the packet */
+    result = av_new_packet(pkt, frame_size);
+    if (result)
+        return result;
+
+    /* Contrary to normal WMV2 video, the bit stream in XMV's
+     * WMV2 is little-endian.
+     * TODO: This manual swap is of course suboptimal.
+     */
+    for (i = 0; i < frame_size; i += 4)
+        AV_WB32(pkt->data + i, avio_rl32(pb));
+
+    pkt->stream_index = video->stream_index;
+
+    /* Calculate the PTS */
+
+    video->last_pts = frame_timestamp + video->pts;
+
+    pkt->duration = 0;
+    pkt->pts      = video->last_pts;
+    pkt->dts      = AV_NOPTS_VALUE;
+
+    video->pts += frame_timestamp;
+
+    /* Keyframe? */
+    pkt->flags = (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY;
+
+    /* Advance offset */
+    video->data_size   -= frame_size + 4;
+    video->data_offset += frame_size + 4;
+
+    return 0;
+}
+
+static int xmv_read_packet(AVFormatContext *s,
+                           AVPacket *pkt)
+{
+    XMVDemuxContext *xmv = s->priv_data;
+    int result;
+
+    if (xmv->video.current_frame == xmv->video.frame_count) {
+        /* No frames left in this packet, so we fetch a new one */
+
+        result = xmv_fetch_new_packet(s);
+        if (result)
+            return result;
+    }
+
+    if (xmv->current_stream == 0) {
+        /* Fetch a video frame */
+
+        result = xmv_fetch_video_packet(s, pkt);
+        if (result)
+            return result;
+
+    } else {
+        /* Fetch an audio frame */
+
+        result = xmv_fetch_audio_packet(s, pkt, xmv->current_stream - 1);
+        if (result)
+            return result;
+    }
+
+    /* Increase our counters */
+    if (++xmv->current_stream >= xmv->stream_count) {
+        xmv->current_stream       = 0;
+        xmv->video.current_frame += 1;
+    }
+
+    return 0;
+}
+
+static int xmv_read_close(AVFormatContext *s)
+{
+    XMVDemuxContext *xmv = s->priv_data;
+
+    av_free(xmv->audio);
+    av_free(xmv->audio_tracks);
+
+    return 0;
+}
+
+AVInputFormat ff_xmv_demuxer = {
+    .name           = "xmv",
+    .long_name      = NULL_IF_CONFIG_SMALL("Microsoft XMV"),
+    .priv_data_size = sizeof(XMVDemuxContext),
+    .read_probe     = xmv_probe,
+    .read_header    = xmv_read_header,
+    .read_packet    = xmv_read_packet,
+    .read_close     = xmv_read_close,
+};
index 1cede4d..fc4781b 100644 (file)
     pmaxsw %1, %2
     pminsw %1, %3
 %endmacro
+
+%macro PMINSD_MMX 3 ; dst, src, tmp
+    mova      %3, %2
+    pcmpgtd   %3, %1
+    pxor      %1, %2
+    pand      %1, %3
+    pxor      %1, %2
+%endmacro
+
+%macro PMAXSD_MMX 3 ; dst, src, tmp
+    mova      %3, %1
+    pcmpgtd   %3, %2
+    pand      %1, %3
+    pandn     %3, %2
+    por       %1, %3
+%endmacro
+
+%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp
+    PMINSD_MMX %1, %3, %4
+    PMAXSD_MMX %1, %2, %4
+%endmacro
+
+%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused
+    cvtdq2ps  %1, %1
+    minps     %1, %3
+    maxps     %1, %2
+    cvtps2dq  %1, %1
+%endmacro
+
+%macro CLIPD_SSE41 3-4 ;  src/dst, min, max, unused
+    pminsd  %1, %3
+    pmaxsd  %1, %2
+%endmacro
index 8a5bac3..439aa91 100644 (file)
@@ -400,7 +400,7 @@ void ff_sws_init_swScale_altivec(SwsContext *c)
         return;
 
     if (c->srcBpc == 8 && c->dstBpc <= 10) {
-        c->hScale       = hScale_altivec_real;
+        c->hyScale = c->hcScale = hScale_altivec_real;
     }
     if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat) &&
         dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 &&
index e94a6f7..0f88648 100644 (file)
@@ -2212,7 +2212,7 @@ static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth,
         int shift= isAnyRGB(c->srcFormat) || c->srcFormat==PIX_FMT_PAL8 ? 13 : av_pix_fmt_descriptors[c->srcFormat].comp[0].depth_minus1;
         c->hScale16(dst, dstWidth, (const uint16_t*)src, srcW, xInc, hLumFilter, hLumFilterPos, hLumFilterSize, shift);
     } else if (!c->hyscale_fast) {
-        c->hScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
+        c->hyScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize);
     } else { // fast bilinear upscale / crap downscale
         c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc);
     }
@@ -2258,8 +2258,8 @@ static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2
         c->hScale16(dst1, dstWidth, (const uint16_t*)src1, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
         c->hScale16(dst2, dstWidth, (const uint16_t*)src2, srcW, xInc, hChrFilter, hChrFilterPos, hChrFilterSize, shift);
     } else if (!c->hcscale_fast) {
-        c->hScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
-        c->hScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
+        c->hcScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize);
+        c->hcScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize);
     } else { // fast bilinear upscale / crap downscale
         c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc);
     }
@@ -2929,16 +2929,16 @@ static av_cold void sws_init_swScale_c(SwsContext *c)
 
     if (c->srcBpc == 8) {
         if (c->dstBpc <= 10) {
-            c->hScale       = hScale8To15_c;
+            c->hyScale = c->hcScale = hScale8To15_c;
             if (c->flags & SWS_FAST_BILINEAR) {
                 c->hyscale_fast = hyscale_fast_c;
                 c->hcscale_fast = hcscale_fast_c;
             }
         } else {
-            c->hScale = hScale8To19_c;
+            c->hyScale = c->hcScale = hScale8To19_c;
         }
     } else {
-        c->hScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c;
+        c->hyScale = c->hcScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c;
     }
 
     if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
index a936f96..c572acb 100644 (file)
@@ -483,9 +483,14 @@ typedef struct SwsContext {
      *                   (and input coefficients thus padded with zeroes)
      *                   to simplify creating SIMD code.
      */
-    void (*hScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
-                   const int16_t *filter, const int16_t *filterPos,
-                   int filterSize);
+    /** @{ */
+    void (*hyScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
+                    const int16_t *filter, const int16_t *filterPos,
+                    int filterSize);
+    void (*hcScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src,
+                    const int16_t *filter, const int16_t *filterPos,
+                    int filterSize);
+    /** @} */
 
     void (*hScale16)(int16_t *dst, int dstW, const uint16_t *src, int srcW,
                    int xInc, const int16_t *filter, const int16_t *filterPos,
index 4163647..7ba1901 100644 (file)
@@ -2474,7 +2474,7 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c)
 
     if (c->srcBpc == 8 && c->dstBpc <= 10) {
 #if !COMPILE_TEMPLATE_MMX2
-    c->hScale       = RENAME(hScale      );
+    c->hyScale = c->hcScale = RENAME(hScale      );
 #endif /* !COMPILE_TEMPLATE_MMX2 */
 
     // Use the new MMX scaler if the MMX2 one can't be used (it is faster than the x86 ASM one).
index 9013f99..caea4c2 100644 (file)
@@ -62,4 +62,3 @@
 0, 171000, 921600, 0x5639e670
 1, 171429, 1000, 0xa491f3ef
 1, 175510, 1000, 0x2c036e18
-1, 179592, 1000, 0x52d65e2a
index 1d0d59f..f321423 100644 (file)
 1, 265680, 768, 0xfd6c7597
 0, 267267, 1327, 0x7d15307c
 1, 267840, 768, 0x8d766d40
-0, 270270, 1225, 0x1b5d0f5f
index 990a530..c63c525 100644 (file)
 0, 0, 276480, 0x5f7a0d4f
-0, 7500, 276480, 0x5f7a0d4f
-0, 15000, 276480, 0x5f7a0d4f
-0, 22500, 276480, 0x5f7a0d4f
-0, 30000, 276480, 0x5f7a0d4f
-0, 37500, 276480, 0x5f7a0d4f
-0, 45000, 276480, 0x5f7a0d4f
-0, 52500, 276480, 0x5f7a0d4f
-0, 60000, 276480, 0x5f7a0d4f
-0, 67500, 276480, 0x5f7a0d4f
-0, 75000, 276480, 0x5f7a0d4f
-0, 82500, 276480, 0x5f7a0d4f
-0, 90000, 276480, 0x5f7a0d4f
-0, 97500, 276480, 0x5f7a0d4f
-0, 105000, 276480, 0x5f7a0d4f
-0, 112500, 276480, 0x5f7a0d4f
-0, 120000, 276480, 0x5f7a0d4f
-0, 127500, 276480, 0x5f7a0d4f
-0, 135000, 276480, 0x75641594
-0, 142500, 276480, 0x32ee3526
-0, 150000, 276480, 0x5ce39368
-0, 157500, 276480, 0x4ec1e418
-0, 165000, 276480, 0x85cbc3b5
-0, 172500, 276480, 0x377c7b46
-0, 180000, 276480, 0x756a4a2e
-0, 187500, 276480, 0xcb379547
-0, 195000, 276480, 0x99c085be
-0, 202500, 276480, 0xe479ffed
-0, 210000, 276480, 0x1e4fae19
-0, 217500, 276480, 0x776412ef
-0, 225000, 276480, 0x58ce0f38
-0, 232500, 276480, 0x5ab69b27
-0, 240000, 276480, 0xc3db9706
-0, 247500, 276480, 0xc9c57884
-0, 255000, 276480, 0x000b5269
-0, 262500, 276480, 0x27ff7a5d
-0, 270000, 276480, 0x70647530
-0, 277500, 276480, 0x97612c4b
-0, 285000, 276480, 0xdf4e04d7
-0, 292500, 276480, 0xbd98f57c
-0, 300000, 276480, 0x5163b29b
-0, 307500, 276480, 0x99170e64
-0, 315000, 276480, 0x8a4e991f
-0, 322500, 276480, 0x6a45425f
-0, 330000, 276480, 0x7bf6b1ef
-0, 337500, 276480, 0x6de1e34b
-0, 345000, 276480, 0xdcaaa99a
-0, 352500, 276480, 0xd1e98808
-0, 360000, 276480, 0x6e2d524e
-0, 367500, 276480, 0x22c50a3d
-0, 375000, 276480, 0x62b76407
-0, 382500, 276480, 0x51e9b3eb
-0, 390000, 276480, 0x441f7afd
-0, 397500, 276480, 0xfb01efc6
-0, 405000, 276480, 0x294bb441
-0, 412500, 276480, 0xe04ac45e
-0, 420000, 276480, 0x58f275ea
-0, 427500, 276480, 0xf0b3b71b
-0, 435000, 276480, 0x674e34e4
-0, 442500, 276480, 0x41dda2d9
-0, 450000, 276480, 0xf46ba7fb
-0, 457500, 276480, 0x28b54815
-0, 465000, 276480, 0xaf2b5d89
-0, 472500, 276480, 0x8facba58
-0, 480000, 276480, 0x28a63236
-0, 487500, 276480, 0x1ad43fd7
-0, 495000, 276480, 0x71507bd2
-0, 502500, 276480, 0x35626022
-0, 510000, 276480, 0x7c1139b3
-0, 517500, 276480, 0x7fd73a99
-0, 525000, 276480, 0xb52e1aa2
-0, 532500, 276480, 0xd6f82cae
-0, 540000, 276480, 0xf88f75d4
-0, 547500, 276480, 0x04a8e3ee
-0, 555000, 276480, 0xa29f5b01
-0, 562500, 276480, 0x754ceaf5
-0, 570000, 276480, 0x5a38b4af
-0, 577500, 276480, 0xfcebc261
-0, 585000, 276480, 0x3d3ca985
-0, 592500, 276480, 0x94a03c75
-0, 600000, 276480, 0x2f98911c
-0, 607500, 276480, 0x923b9937
-0, 615000, 276480, 0xefab7ffd
-0, 622500, 276480, 0x6b9fbc80
-0, 630000, 276480, 0xe4bdbd1e
-0, 637500, 276480, 0x225a56c0
-0, 645000, 276480, 0xf58b1b7c
-0, 652500, 276480, 0xbaffcdcc
-0, 660000, 276480, 0xeb6eb88f
-0, 667500, 276480, 0xdb753d35
-0, 675000, 276480, 0xea80a82e
-0, 682500, 276480, 0x2aae902a
-0, 690000, 276480, 0x9b9ee961
-0, 697500, 276480, 0xaa12b6fd
-0, 705000, 276480, 0x50c31e73
-0, 712500, 276480, 0xdd9fb89f
-0, 720000, 276480, 0xaf82399a
-0, 727500, 276480, 0x7ce5f23c
-0, 735000, 276480, 0x5aaa7519
-0, 742500, 276480, 0xe45a5599
-0, 750000, 276480, 0x704411fb
-0, 757500, 276480, 0x9d7430a1
-0, 765000, 276480, 0x2c230702
-0, 772500, 276480, 0x4a4f76cd
-0, 780000, 276480, 0x27f54854
-0, 787500, 276480, 0x694d76e3
-0, 795000, 276480, 0x525463e2
-0, 802500, 276480, 0x819898f9
-0, 810000, 276480, 0xeeed00fc
-0, 817500, 276480, 0xb6f99ee3
-0, 825000, 276480, 0xefc83107
-0, 832500, 276480, 0xbb22e024
-0, 840000, 276480, 0x300f922a
-0, 847500, 276480, 0x826fc3bd
-0, 855000, 276480, 0x679a53f8
-0, 862500, 276480, 0x976c9e93
-0, 870000, 276480, 0xb194656e
-0, 877500, 276480, 0xf002c5ca
-0, 885000, 276480, 0xb243dda5
-0, 892500, 276480, 0x1700efbb
-0, 900000, 276480, 0x8f316c66
+0, 3754, 276480, 0x5f7a0d4f
+0, 7507, 276480, 0x5f7a0d4f
+0, 11261, 276480, 0x5f7a0d4f
+0, 15015, 276480, 0x5f7a0d4f
+0, 18769, 276480, 0x5f7a0d4f
+0, 22522, 276480, 0x5f7a0d4f
+0, 26276, 276480, 0x5f7a0d4f
+0, 30030, 276480, 0x5f7a0d4f
+0, 33784, 276480, 0x5f7a0d4f
+0, 37537, 276480, 0x5f7a0d4f
+0, 41291, 276480, 0x5f7a0d4f
+0, 45045, 276480, 0x5f7a0d4f
+0, 48799, 276480, 0x5f7a0d4f
+0, 52552, 276480, 0x5f7a0d4f
+0, 56306, 276480, 0x5f7a0d4f
+0, 60060, 276480, 0x5f7a0d4f
+0, 63814, 276480, 0x5f7a0d4f
+0, 67567, 276480, 0x5f7a0d4f
+0, 71321, 276480, 0x5f7a0d4f
+0, 75075, 276480, 0x5f7a0d4f
+0, 78829, 276480, 0x5f7a0d4f
+0, 82582, 276480, 0x5f7a0d4f
+0, 86336, 276480, 0x5f7a0d4f
+0, 90090, 276480, 0x5f7a0d4f
+0, 93844, 276480, 0x5f7a0d4f
+0, 97597, 276480, 0x5f7a0d4f
+0, 101351, 276480, 0x5f7a0d4f
+0, 105105, 276480, 0x5f7a0d4f
+0, 108859, 276480, 0x5f7a0d4f
+0, 112612, 276480, 0x5f7a0d4f
+0, 116366, 276480, 0x5f7a0d4f
+0, 120120, 276480, 0x5f7a0d4f
+0, 123874, 276480, 0x75641594
+0, 127627, 276480, 0x32ee3526
+0, 131381, 276480, 0xcb53479a
+0, 135135, 276480, 0x7ca9658e
+0, 138889, 276480, 0x5ce39368
+0, 142642, 276480, 0x4ec1e418
+0, 146396, 276480, 0xb3790499
+0, 150150, 276480, 0xa9f1506f
+0, 153904, 276480, 0x85cbc3b5
+0, 157657, 276480, 0x377c7b46
+0, 161411, 276480, 0x1a61d8db
+0, 165165, 276480, 0xe1de7f0a
+0, 168919, 276480, 0x756a4a2e
+0, 172672, 276480, 0xcb379547
+0, 176426, 276480, 0xbae14484
+0, 180180, 276480, 0x8e12331c
+0, 183934, 276480, 0x99c085be
+0, 187687, 276480, 0xe479ffed
+0, 191441, 276480, 0x99c82949
+0, 195195, 276480, 0xac7672dd
+0, 198949, 276480, 0x1e4fae19
+0, 202702, 276480, 0x776412ef
+0, 206456, 276480, 0x7d9b579f
+0, 210210, 276480, 0x1cd1ab29
+0, 213964, 276480, 0x58ce0f38
+0, 217717, 276480, 0x5ab69b27
+0, 221471, 276480, 0x0afad610
+0, 225225, 276480, 0x9eca3f11
+0, 228979, 276480, 0xc3db9706
+0, 232732, 276480, 0xc9c57884
+0, 236486, 276480, 0xd9fbb2cf
+0, 240240, 276480, 0xdc07f3c9
+0, 243994, 276480, 0x000b5269
+0, 247747, 276480, 0x27ff7a5d
+0, 251501, 276480, 0xd92e2017
+0, 255255, 276480, 0x18d4b27d
+0, 259009, 276480, 0x70647530
+0, 262762, 276480, 0x97612c4b
+0, 266516, 276480, 0xc9d4ac78
+0, 270270, 276480, 0x4ec4d57f
+0, 274024, 276480, 0xdf4e04d7
+0, 277777, 276480, 0xbd98f57c
+0, 281531, 276480, 0x7247ea3e
+0, 285285, 276480, 0xa5d670ec
+0, 289039, 276480, 0x5163b29b
+0, 292792, 276480, 0x99170e64
+0, 296546, 276480, 0x37f4c0b0
+0, 300300, 276480, 0x7a4f2561
+0, 304053, 276480, 0x8a4e991f
+0, 307807, 276480, 0x6a45425f
+0, 311561, 276480, 0x1f0e2bb6
+0, 315315, 276480, 0xd75482c6
+0, 319068, 276480, 0x7bf6b1ef
+0, 322822, 276480, 0x6de1e34b
+0, 326576, 276480, 0x4526c89b
+0, 330330, 276480, 0xf964e18e
+0, 334083, 276480, 0xdcaaa99a
+0, 337837, 276480, 0xd1e98808
+0, 341591, 276480, 0x556b2365
+0, 345345, 276480, 0x0cf65540
+0, 349098, 276480, 0x6e2d524e
+0, 352852, 276480, 0x22c50a3d
+0, 356606, 276480, 0x293f19af
+0, 360360, 276480, 0xf4b1c461
+0, 364113, 276480, 0x62b76407
+0, 367867, 276480, 0x51e9b3eb
+0, 371621, 276480, 0x7b910bc7
+0, 375375, 276480, 0x6dd14ca6
+0, 379128, 276480, 0x441f7afd
+0, 382882, 276480, 0xfb01efc6
+0, 386636, 276480, 0x4f73ccea
+0, 390390, 276480, 0x5ac8e06f
+0, 394143, 276480, 0x294bb441
+0, 397897, 276480, 0xe04ac45e
+0, 401651, 276480, 0xa7a38d41
+0, 405405, 276480, 0xf688a3ed
+0, 409158, 276480, 0x58f275ea
+0, 412912, 276480, 0xf0b3b71b
+0, 416666, 276480, 0x3ce773bf
+0, 420420, 276480, 0x01840548
+0, 424173, 276480, 0x674e34e4
+0, 427927, 276480, 0x41dda2d9
+0, 431681, 276480, 0xc5b60838
+0, 435435, 276480, 0x9b209f41
+0, 439188, 276480, 0xf46ba7fb
+0, 442942, 276480, 0x28b54815
+0, 446696, 276480, 0xb605a933
+0, 450450, 276480, 0x34484aff
+0, 454203, 276480, 0xaf2b5d89
+0, 457957, 276480, 0x8facba58
+0, 461711, 276480, 0xbbe3e99f
+0, 465465, 276480, 0x02162c7c
+0, 469218, 276480, 0x28a63236
+0, 472972, 276480, 0x1ad43fd7
+0, 476726, 276480, 0xe37883e5
+0, 480480, 276480, 0x2b8a89c5
+0, 484233, 276480, 0x71507bd2
+0, 487987, 276480, 0x35626022
+0, 491741, 276480, 0x461fc3e7
+0, 495495, 276480, 0xce5af1ec
+0, 499248, 276480, 0x7c1139b3
+0, 503002, 276480, 0x7fd73a99
+0, 506756, 276480, 0x4ae4c3a6
+0, 510510, 276480, 0xcb60725a
+0, 514263, 276480, 0xb52e1aa2
+0, 518017, 276480, 0xd6f82cae
+0, 521771, 276480, 0x6310e665
+0, 525525, 276480, 0xfa88a483
+0, 529278, 276480, 0xf88f75d4
+0, 533032, 276480, 0x04a8e3ee
+0, 536786, 276480, 0x54766a12
+0, 540540, 276480, 0x0b41f0d7
+0, 544293, 276480, 0xa29f5b01
+0, 548047, 276480, 0x754ceaf5
+0, 551801, 276480, 0x150c0423
+0, 555555, 276480, 0xde084059
+0, 559308, 276480, 0x5a38b4af
+0, 563062, 276480, 0xfcebc261
+0, 566816, 276480, 0x0eb9770d
+0, 570570, 276480, 0x046394ae
+0, 574323, 276480, 0x3d3ca985
+0, 578077, 276480, 0x94a03c75
+0, 581831, 276480, 0x800eea2d
+0, 585585, 276480, 0x6a841f41
+0, 589338, 276480, 0x2f98911c
+0, 593092, 276480, 0x923b9937
+0, 596846, 276480, 0xe82f8e0f
+0, 600600, 276480, 0xee82d657
+0, 604353, 276480, 0xefab7ffd
+0, 608107, 276480, 0x6b9fbc80
+0, 611861, 276480, 0x4a1ada47
+0, 615614, 276480, 0x6d4b49d7
+0, 619368, 276480, 0xe4bdbd1e
+0, 623122, 276480, 0x225a56c0
+0, 626876, 276480, 0xd4adadad
+0, 630629, 276480, 0xff4e1a8c
+0, 634383, 276480, 0xf58b1b7c
+0, 638137, 276480, 0xbaffcdcc
+0, 641891, 276480, 0x374f88f0
+0, 645644, 276480, 0x3d861ae6
+0, 649398, 276480, 0xeb6eb88f
+0, 653152, 276480, 0xdb753d35
+0, 656906, 276480, 0x9aa543af
+0, 660659, 276480, 0xb24c8016
+0, 664413, 276480, 0xea80a82e
+0, 668167, 276480, 0x2aae902a
+0, 671921, 276480, 0x5bba3cfb
+0, 675674, 276480, 0x5c6e97a9
+0, 679428, 276480, 0x9b9ee961
+0, 683182, 276480, 0xaa12b6fd
+0, 686936, 276480, 0xe9d2439f
+0, 690689, 276480, 0xbf09053c
+0, 694443, 276480, 0x50c31e73
+0, 698197, 276480, 0xdd9fb89f
+0, 701951, 276480, 0x3e4e5aec
+0, 705704, 276480, 0x0b752d28
+0, 709458, 276480, 0xaf82399a
+0, 713212, 276480, 0x7ce5f23c
+0, 716966, 276480, 0xad135d0f
+0, 720719, 276480, 0x55dadd30
+0, 724473, 276480, 0x5aaa7519
+0, 728227, 276480, 0xe45a5599
+0, 731981, 276480, 0xc8e89913
+0, 735734, 276480, 0x2f447fd3
+0, 739488, 276480, 0x704411fb
+0, 743242, 276480, 0x9d7430a1
+0, 746996, 276480, 0x24dd5fd3
+0, 750749, 276480, 0x51cb657c
+0, 754503, 276480, 0x2c230702
+0, 758257, 276480, 0x4a4f76cd
+0, 762011, 276480, 0xdcd71e88
+0, 765764, 276480, 0x87160f99
+0, 769518, 276480, 0x27f54854
+0, 773272, 276480, 0x694d76e3
+0, 777026, 276480, 0xcbe93c19
+0, 780779, 276480, 0x50742e1b
+0, 784533, 276480, 0x525463e2
+0, 788287, 276480, 0x819898f9
+0, 792041, 276480, 0x08fac755
+0, 795794, 276480, 0x35c46927
+0, 799548, 276480, 0xeeed00fc
+0, 803302, 276480, 0xb6f99ee3
+0, 807056, 276480, 0xd87f4c73
+0, 810809, 276480, 0xde97d9fd
+0, 814563, 276480, 0xefc83107
+0, 818317, 276480, 0xbb22e024
+0, 822071, 276480, 0x53a7cfcb
+0, 825824, 276480, 0xbe1fbb19
+0, 829578, 276480, 0x300f922a
+0, 833332, 276480, 0x826fc3bd
+0, 837086, 276480, 0x679aa57a
+0, 840839, 276480, 0x5497097b
+0, 844593, 276480, 0x679a53f8
+0, 848347, 276480, 0x976c9e93
+0, 852101, 276480, 0xe80f87f2
+0, 855854, 276480, 0xdc2d7c6c
+0, 859608, 276480, 0xb194656e
+0, 863362, 276480, 0xf002c5ca
+0, 867116, 276480, 0x43fc1c64
+0, 870869, 276480, 0xf62d8581
+0, 874623, 276480, 0xb243dda5
+0, 878377, 276480, 0x1700efbb
+0, 882131, 276480, 0x9ebe6ba2
+0, 885884, 276480, 0x8f316c66
+0, 889638, 276480, 0x6348ecf5
+0, 893392, 276480, 0x34b5b78a
+0, 897146, 276480, 0xcbf66922
index 6c99871..a3c5dcf 100644 (file)
 0, 0, 126720, 0xcefaec47
-0, 7500, 126720, 0xa416ece5
-0, 15000, 126720, 0xa416ece5
-0, 22500, 126720, 0xa416ece5
-0, 30000, 126720, 0xcc10f4b7
-0, 37500, 126720, 0xeb6fb8d7
-0, 45000, 126720, 0xda71b917
-0, 52500, 126720, 0xbb1abbb7
-0, 60000, 126720, 0x273fbc37
-0, 67500, 126720, 0x16eebbd7
-0, 75000, 126720, 0x105eb927
-0, 82500, 126720, 0x7fa3ae27
-0, 90000, 126720, 0xd115a757
-0, 97500, 126720, 0x04e7897c
-0, 105000, 126720, 0x68cfda2b
-0, 112500, 126720, 0xe572dfc9
-0, 120000, 126720, 0xbc3cc34f
-0, 127500, 126720, 0xcf8cb0e2
-0, 135000, 126720, 0x75ae61b6
-0, 142500, 126720, 0x554fe3e4
-0, 150000, 126720, 0x72ecea95
-0, 157500, 126720, 0x5d00b5fe
-0, 165000, 126720, 0xe39bba0d
-0, 172500, 126720, 0x9c21bad8
-0, 180000, 126720, 0x72f2a47d
-0, 187500, 126720, 0x4f639ebe
-0, 195000, 126720, 0x534a10cc
-0, 202500, 126720, 0xfdca11d3
-0, 210000, 126720, 0x0c735615
-0, 217500, 126720, 0x0eaf0c1b
-0, 225000, 126720, 0xce5e6794
-0, 232500, 126720, 0x14cf7974
-0, 240000, 126720, 0xbc513f2a
-0, 247500, 126720, 0xbc303fae
-0, 255000, 126720, 0xd9f67585
-0, 262500, 126720, 0x3378251f
-0, 270000, 126720, 0xb3ed5911
-0, 277500, 126720, 0xc15a3577
-0, 285000, 126720, 0x0a24f256
-0, 292500, 126720, 0xfab9c45d
-0, 300000, 126720, 0x45464610
-0, 307500, 126720, 0xfe2e057d
-0, 315000, 126720, 0x23efdc35
-0, 322500, 126720, 0x4d888b2e
-0, 330000, 126720, 0xdd0d74df
-0, 337500, 126720, 0x08382b8e
+0, 3003, 126720, 0xa416ece5
+0, 6006, 126720, 0xa416ece5
+0, 9009, 126720, 0xa416ece5
+0, 12012, 126720, 0x60d6ed27
+0, 15015, 126720, 0x259af497
+0, 18018, 126720, 0x5e6ff4d7
+0, 21021, 126720, 0xcc10f4b7
+0, 24024, 126720, 0x763ab817
+0, 27027, 126720, 0xeb6fb8d7
+0, 30030, 126720, 0xda71b917
+0, 33033, 126720, 0x0967b8f7
+0, 36036, 126720, 0x4b62b947
+0, 39039, 126720, 0xbb1abbb7
+0, 42042, 126720, 0x273fbc37
+0, 45045, 126720, 0x16eebbd7
+0, 48048, 126720, 0x105eb927
+0, 51051, 126720, 0x7fa3ae27
+0, 54054, 126720, 0x722e99f7
+0, 57057, 126720, 0x5ac9a827
+0, 60060, 126720, 0x07beba77
+0, 63063, 126720, 0x29d6a887
+0, 66066, 126720, 0xa5caab87
+0, 69069, 126720, 0x9ca7aac7
+0, 72072, 126720, 0xb7debcd7
+0, 75075, 126720, 0xd115a757
+0, 78078, 126720, 0x6ddaef32
+0, 81081, 126720, 0xde1bb900
+0, 84084, 126720, 0xac6c071b
+0, 87087, 126720, 0x04e7897c
+0, 90090, 126720, 0x5eee050f
+0, 93093, 126720, 0xe675be59
+0, 96096, 126720, 0xdc3e0837
+0, 99099, 126720, 0x68cfda2b
+0, 102102, 126720, 0xe572dfc9
+0, 105105, 126720, 0x582fb176
+0, 108108, 126720, 0xa9477df0
+0, 111111, 126720, 0xbc3cc34f
+0, 114114, 126720, 0xcf8cb0e2
+0, 117117, 126720, 0xcff1db35
+0, 120120, 126720, 0xc6e10f9f
+0, 123123, 126720, 0x75ae61b6
+0, 126126, 126720, 0x12af3119
+0, 129129, 126720, 0x85597543
+0, 132132, 126720, 0x68c27aca
+0, 135135, 126720, 0x554fe3e4
+0, 138138, 126720, 0x72ecea95
+0, 141141, 126720, 0xf4d003d1
+0, 144144, 126720, 0x9bf6a605
+0, 147147, 126720, 0x5d00b5fe
+0, 150150, 126720, 0x93f7b040
+0, 153153, 126720, 0x0d6ad154
+0, 156156, 126720, 0x4be8b4ea
+0, 159159, 126720, 0xe39bba0d
+0, 162162, 126720, 0x9c21bad8
+0, 165165, 126720, 0xa567f25b
+0, 168168, 126720, 0x7a82663a
+0, 171171, 126720, 0x72f2a47d
+0, 174174, 126720, 0x4f639ebe
+0, 177177, 126720, 0xab0fce83
+0, 180180, 126720, 0x6cf87d39
+0, 183183, 126720, 0x534a10cc
+0, 186186, 126720, 0x6bbcf44c
+0, 189189, 126720, 0xfdca11d3
+0, 192192, 126720, 0x7e58f5a6
+0, 195195, 126720, 0x5fd753d8
+0, 198198, 126720, 0x0c735615
+0, 201201, 126720, 0x2a034ebf
+0, 204204, 126720, 0xeaf3dd0b
+0, 207207, 126720, 0x0eaf0c1b
+0, 210210, 126720, 0xce5e6794
+0, 213213, 126720, 0xf27c31c3
+0, 216216, 126720, 0xb64af168
+0, 219219, 126720, 0x14cf7974
+0, 222222, 126720, 0x1c2a513d
+0, 225225, 126720, 0xa3f515ab
+0, 228228, 126720, 0xcfd62765
+0, 231231, 126720, 0xbc513f2a
+0, 234234, 126720, 0xbc303fae
+0, 237237, 126720, 0x2f8f69b9
+0, 240240, 126720, 0x0a22cc69
+0, 243243, 126720, 0xd9f67585
+0, 246246, 126720, 0x20403001
+0, 249249, 126720, 0xf92b2a25
+0, 252252, 126720, 0x3c170aad
+0, 255255, 126720, 0x3378251f
+0, 258258, 126720, 0xb3ed5911
+0, 261261, 126720, 0x35d24ef8
+0, 264264, 126720, 0x8da30275
+0, 267267, 126720, 0xc15a3577
+0, 270270, 126720, 0xf2942f53
+0, 273273, 126720, 0x44d8304a
+0, 276276, 126720, 0xd688a932
+0, 279279, 126720, 0x0a24f256
+0, 282282, 126720, 0xfab9c45d
+0, 285285, 126720, 0x10e939ce
+0, 288288, 126720, 0x97fcaa3a
+0, 291291, 126720, 0x45464610
+0, 294294, 126720, 0xfe2e057d
+0, 297297, 126720, 0x0b6718ae
+0, 300300, 126720, 0x5284da7b
+0, 303303, 126720, 0x23efdc35
+0, 306306, 126720, 0xc387b2b3
+0, 309309, 126720, 0xc9e92bf1
+0, 312312, 126720, 0xfbf20a01
+0, 315315, 126720, 0x4d888b2e
+0, 318318, 126720, 0xdd0d74df
+0, 321321, 126720, 0x49d07aa4
+0, 324324, 126720, 0x08382b8e