Merge remote-tracking branch 'qatar/master'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 14 Jun 2012 22:09:39 +0000 (00:09 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 14 Jun 2012 22:14:21 +0000 (00:14 +0200)
* qatar/master:
  Avoid C99 variable declarations within for statements.
  rtmp: Read and handle incoming packets while writing data
  doc: document THREAD_TYPE fate variable
  rtpdec: Don't require frames to start with a Mode A packet
  avconv: don't try to free threads that were not initialized.

Conflicts:
doc/fate.texi
ffplay.c
libavdevice/dv1394.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
doc/fate.texi
ffmpeg.c
ffplay.c
libavcodec/pthread.c
libavdevice/dv1394.h
libavformat/rtmppkt.c
libavformat/rtmppkt.h
libavformat/rtmpproto.c

diff --combined doc/fate.texi
  \input texinfo @c -*- texinfo -*-
  
 -@settitle FATE Automated Testing Environment
 +@settitle FFmpeg Automated Testing Environment
  @titlepage
 -@center @titlefont{FATE Automated Testing Environment}
 +@center @titlefont{FFmpeg Automated Testing Environment}
  @end titlepage
  
 +@node Top
  @top
  
  @contents
  
  @chapter Introduction
  
 -FATE provides a regression testsuite embedded within the Libav build system.
 -It can be run locally and optionally configured to send reports to a web
 -aggregator and viewer @url{http://fate.libav.org}.
 +  FATE is an extended regression suite on the client-side and a means
 +for results aggregation and presentation on the server-side.
  
 -It is advised to run FATE before submitting patches to the current codebase
 -and provide new tests when submitting patches to add additional features.
 +  The first part of this document explains how you can use FATE from
 +your FFmpeg source directory to test your ffmpeg binary. The second
 +part describes how you can run FATE to submit the results to FFmpeg's
 +FATE server.
  
 -@chapter Running FATE
 +  In any way you can have a look at the publicly viewable FATE results
 +by visiting this website:
  
 -@section Samples and References
 -In order to run, FATE needs a large amount of data (samples and references)
 -that is provided separately from the actual source distribution.
 +  @url{http://fate.ffmpeg.org/}
  
 -To inform the build system about the testsuite location, pass
 -@option{--samples=<path to the samples>} to @command{configure} or set the
 -@var{SAMPLES} Make variable or the @var{LIBAV_SAMPLES} environment variable
 -to a suitable value.
 +  This is especially recommended for all people contributing source
 +code to FFmpeg, as it can be seen if some test on some platform broke
 +with there recent contribution. This usually happens on the platforms
 +the developers could not test on.
 +
 +  The second part of this document describes how you can run FATE to
 +submit your results to FFmpeg's FATE server. If you want to submit your
 +results be sure to check that your combination of CPU, OS and compiler
 +is not already listed on the above mentioned website.
 +
 +  In the third part you can find a comprehensive listing of FATE makefile
 +targets and variables.
  
 -To use a custom wrapper to run the test, pass @option{--target-exec} to
 -@command{configure} or set the @var{TARGET_EXEC} Make variable.
  
 -The dataset is available through @command{rsync}, is possible to fetch
 -the current sample using the straight rsync command or through a specific
 -@ref{Makefile target}.
 +@chapter Using FATE from your FFmpeg source directory
 +
 +  If you want to run FATE on your machine you need to have the samples
 +in place. You can get the samples via the build target fate-rsync.
 +Use this command from the top-level source directory:
  
  @example
 -# rsync -aL rsync://fate-suite.libav.org/fate-suite/ fate-suite
 +make fate-rsync SAMPLES=fate-suite/
 +make fate       SAMPLES=fate-suite/
  @end example
  
 +  The above commands set the samples location by passing a makefile
 +variable via command line. It is also possible to set the samples
 +location at source configuration time by invoking configure with
 +`--samples=<path to the samples directory>'. Afterwards you can
 +invoke the makefile targets without setting the SAMPLES makefile
 +variable. This is illustrated by the following commands:
 +
  @example
 -# make fate-rsync SAMPLES=fate-suite
 +./configure --samples=fate-suite/
 +make fate-rsync
 +make fate
  @end example
  
 +  Yet another way to tell FATE about the location of the sample
 +directory is by making sure the environment variable FATE_SAMPLES
 +contains the path to your samples directory. This can be achieved
 +by e.g. putting that variable in your shell profile or by setting
 +it in your interactive session.
 +
 +@example
 +FATE_SAMPLES=fate-suite/ make fate
 +@end example
 +
 +@float NOTE
 +Do not put a '~' character in the samples path to indicate a home
 +directory. Because of shell nuances, this will cause FATE to fail.
 +@end float
 +
 +To use a custom wrapper to run the test, pass @option{--target-exec} to
 +@command{configure} or set the @var{TARGET_EXEC} Make variable.
 +
 +
 +@chapter Submitting the results to the FFmpeg result aggregation server
 +
 +  To submit your results to the server you should run fate through the
 +shell script tests/fate.sh from the FFmpeg sources. This script needs
 +to be invoked with a configuration file as its first argument.
 +
 +@example
 +tests/fate.sh /path/to/fate_config
 +@end example
 +
 +  A configuration file template with comments describing the individual
 +configuration variables can be found at @file{tests/fate_config.sh.template}.
 +
 +@ifhtml
 +  The mentioned configuration template is also available here:
 +@verbatiminclude ../tests/fate_config.sh.template
 +@end ifhtml
 +
 +  Create a configuration that suits your needs, based on the configuration
 +template. The `slot' configuration variable can be any string that is not
 +yet used, but it is suggested that you name it adhering to the following
 +pattern <arch>-<os>-<compiler>-<compiler version>. The configuration file
 +itself will be sourced in a shell script, therefore all shell features may
 +be used. This enables you to setup the environment as you need it for your
 +build.
 +
 +  For your first test runs the `fate_recv' variable should be empty or
 +commented out. This will run everything as normal except that it will omit
 +the submission of the results to the server. The following files should be
 +present in $workdir as specified in the configuration file:
 +
 +@itemize
 +    @item configure.log
 +    @item compile.log
 +    @item test.log
 +    @item report
 +    @item version
 +@end itemize
 +
 +  When you have everything working properly you can create an SSH key and
 +send its public part to the FATE server administrator.
  
 -@chapter Manual Run
 -FATE regression test can be run through @command{make}.
 -Specific Makefile targets and Makefile variables are available:
 +  Configure your SSH client to use public key authentication with that key
 +when connecting to the FATE server. Also do not forget to check the identity
 +of the server and to accept its host key. This can usually be achieved by
 +running your SSH client manually and killing it after you accepted the key.
 +The FATE server's fingerprint is:
 +
 +  b1:31:c8:79:3f:04:1d:f8:f2:23:26:5a:fd:55:fa:92
 +
 +  The only thing left is to automate the execution of the fate.sh script and
 +the synchronisation of the samples directory.
 +
 +
 +@chapter FATE makefile targets and variables
 +
 +@section Makefile targets
  
 -@anchor{Makefile target}
 -@section FATE Makefile targets
  @table @option
 -@item fate-list
 -List all fate/regression test targets.
  @item fate-rsync
 -Shortcut to download the fate test samples to the specified testsuite location.
 +    Download/synchronize sample files to the configured samples directory.
 +
 +@item fate-list
 +    Will list all fate/regression test targets.
 +
  @item fate
 -Run the FATE test suite (requires the fate-suite dataset).
 +    Run the FATE test suite (requires the fate-suite dataset).
  @end table
  
 -@section FATE Makefile variables
 +@section Makefile variables
 +
  @table @option
  @item V
 -Verbosity level, can be set to 0, 1 or 2.
 -@table @option
 -    @item 0
 -    show just the test arguments
 -    @item 1
 -    show just the command used in the test
 -    @item 2
 -    show everything
 -@end table
 +    Verbosity level, can be set to 0, 1 or 2.
 +    @itemize
 +        @item 0: show just the test arguments
 +        @item 1: show just the command used in the test
 +        @item 2: show everything
 +    @end itemize
 +
  @item SAMPLES
 -Specify or override the path to the FATE samples at make time, it has a
 -meaning only while running the regression tests.
 +    Specify or override the path to the FATE samples at make time, it has a
 +    meaning only while running the regression tests.
 +
  @item THREADS
 -Specify how many threads to use while running regression tests, it is
 -quite useful to detect thread-related regressions.
 +    Specify how many threads to use while running regression tests, it is
 +    quite useful to detect thread-related regressions.
+ @item THREAD_TYPE
 -Specify which threading strategy test, either @var{slice} or @var{frame},
 -by default @var{slice+frame}
++    Specify which threading strategy test, either @var{slice} or @var{frame},
++    by default @var{slice+frame}
  @item CPUFLAGS
 -Specify a mask to be applied to autodetected CPU flags.
 +    Specify CPU flags.
  @item TARGET_EXEC
 -Specify or override the wrapper used to run the tests.
 +    Specify or override the wrapper used to run the tests.
 +    The @var{TARGET_EXEC} option provides a way to run FATE wrapped in
 +    @command{valgrind}, @command{qemu-user} or @command{wine} or on remote targets
 +    through @command{ssh}.
  @end table
  
 +Example:
  @example
 -    make V=1 SAMPLES=/var/fate/samples THREADS=2 CPUFLAGS=mmx fate
 -@end example
 -
 -@chapter Automated Tests
 -In order to automatically testing specific configurations, e.g. multiple
 -compilers, @command{tests/fate.sh} is provided.
 -
 -This shell script builds Libav, runs the regression tests and prepares
 -a report that can be sent to @url{http://fate.libav.org/} or directly
 -examined locally.
 -
 -@section Testing Profiles
 -The configuration file passed to @command{fate.sh} is shell scripts as well.
 -
 -It must provide at least a @var{slot} identifier, the @var{repo} from
 -which fetch the sources, the @var{samples} directory, a @var{workdir} with
 -enough space to build and run all the tests.
 -Optional submit command @var{fate_recv} and a @var{comment} to describe
 -the testing profile are available.
 -
 -Additional optional parameter to tune the Libav building and reporting process
 -can be passed.
 -
 -@example
 -slot=                                   # some unique identifier
 -repo=git://git.libav.org/libav.git      # the source repository
 -samples=/path/to/fate/samples
 -workdir=                                # directory in which to do all the work
 -fate_recv="ssh -T fate@@fate.libav.org"  # command to submit report
 -comment=                                # optional description
 -
 -# the following are optional and map to configure options
 -arch=
 -cpu=
 -cross_prefix=
 -cc=
 -target_os=
 -sysroot=
 -target_exec=
 -target_path=
 -extra_cflags=
 -extra_ldflags=
 -extra_libs=
 -extra_conf=     # extra configure options not covered above
 -
 -#make=          # name of GNU make if not 'make'
 -makeopts=       # extra options passed to 'make'
 -#tar=           # command to create a tar archive from its arguments on
 -                # stdout, defaults to 'tar c'
 +make V=1 SAMPLES=/var/fate/samples THREADS=2 CPUFLAGS=mmx fate
  @end example
 -
 -@section Special Instances
 -The @var{TARGET_EXEC} option provides a way to run FATE wrapped in
 -@command{valgrind}, @command{qemu-user} or @command{wine} or on remote targets
 -through @command{ssh}.
 -
 -@section Submitting Reports
 -In order to send reports you need to create an @command{ssh} key and send it
 -to @email{root@@libav.org}.
 -The current server fingerprint is @var{a4:99:d7:d3:1c:92:0d:56:d6:d5:61:be:01:ae:7d:e6}
diff --combined ffmpeg.c
+++ b/ffmpeg.c
@@@ -1,28 -1,24 +1,28 @@@
  /*
 - * avconv main
 - * Copyright (c) 2000-2011 The libav developers.
 + * Copyright (c) 2000-2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 +/**
 + * @file
 + * multimedia converter based on the FFmpeg libraries
 + */
 +
  #include "config.h"
  #include <ctype.h>
  #include <string.h>
@@@ -35,7 -31,7 +35,7 @@@
  #include "libavformat/avformat.h"
  #include "libavdevice/avdevice.h"
  #include "libswscale/swscale.h"
 -#include "libavresample/avresample.h"
 +#include "libswresample/swresample.h"
  #include "libavutil/opt.h"
  #include "libavutil/audioconvert.h"
  #include "libavutil/parseutils.h"
  #include "libavutil/avstring.h"
  #include "libavutil/libm.h"
  #include "libavutil/imgutils.h"
 +#include "libavutil/timestamp.h"
 +#include "libavutil/bprint.h"
  #include "libavformat/os_support.h"
  
 +#include "libavformat/ffm.h" // not public API
 +
 +# include "libavfilter/avcodec.h"
  # include "libavfilter/avfilter.h"
  # include "libavfilter/avfiltergraph.h"
  # include "libavfilter/buffersrc.h"
  # include "libavfilter/buffersink.h"
 -# include "libavfilter/vsrc_buffer.h"
  
  #if HAVE_SYS_RESOURCE_H
  #include <sys/types.h>
  #include <sys/select.h>
  #endif
  
 +#if HAVE_TERMIOS_H
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <sys/time.h>
 +#include <termios.h>
 +#elif HAVE_KBHIT
 +#include <conio.h>
 +#endif
 +
  #if HAVE_PTHREADS
  #include <pthread.h>
  #endif
  #define VSYNC_PASSTHROUGH 0
  #define VSYNC_CFR         1
  #define VSYNC_VFR         2
 +#define VSYNC_DROP        0xff
 +
 +#define SINKA
  
 -const char program_name[] = "avconv";
 +const char program_name[] = "ffmpeg";
  const int program_birth_year = 2000;
  
  /* select an input stream for an output stream */
@@@ -117,40 -97,34 +117,40 @@@ typedef struct StreamMap 
      char *linklabel;       /** name of an output link, for mapping lavfi outputs */
  } StreamMap;
  
 -/**
 - * select an input file for an output file
 - */
 -typedef struct MetadataMap {
 -    int  file;      ///< file index
 -    char type;      ///< type of metadata to copy -- (g)lobal, (s)tream, (c)hapter or (p)rogram
 -    int  index;     ///< stream/chapter/program number
 -} MetadataMap;
 +typedef struct {
 +    int  file_idx,  stream_idx,  channel_idx; // input
 +    int ofile_idx, ostream_idx;               // output
 +} AudioChannelMap;
  
  static const OptionDef options[];
  
 +#define MAX_STREAMS 1024    /* arbitrary sanity check value */
 +
 +static int frame_bits_per_raw_sample = 0;
  static int video_discard = 0;
  static int same_quant = 0;
  static int do_deinterlace = 0;
  static int intra_dc_precision = 8;
  static int qp_hist = 0;
 +static int intra_only = 0;
 +static const char *video_codec_name    = NULL;
 +static const char *audio_codec_name    = NULL;
 +static const char *subtitle_codec_name = NULL;
  
  static int file_overwrite = 0;
 +static int no_file_overwrite = 0;
  static int do_benchmark = 0;
 +static int do_benchmark_all = 0;
  static int do_hex_dump = 0;
  static int do_pkt_dump = 0;
 +static int do_psnr = 0;
  static int do_pass = 0;
 -static char *pass_logfilename_prefix = NULL;
 +static const char *pass_logfilename_prefix;
  static int video_sync_method = VSYNC_AUTO;
  static int audio_sync_method = 0;
  static float audio_drift_threshold = 0.1;
  static int copy_ts = 0;
 -static int copy_tb = 1;
 +static int copy_tb = -1;
  static int opt_shortest = 0;
  static char *vstats_filename;
  static FILE *vstats_file;
@@@ -159,8 -133,6 +159,8 @@@ static int audio_volume = 256
  
  static int exit_on_error = 0;
  static int using_stdin = 0;
 +static int run_as_daemon  = 0;
 +static volatile int received_nb_signals = 0;
  static int64_t video_size = 0;
  static int64_t audio_size = 0;
  static int64_t extra_size = 0;
@@@ -169,18 -141,15 +169,18 @@@ static int nb_frames_drop = 0
  static int input_sync;
  
  static float dts_delta_threshold = 10;
 +static float dts_error_threshold = 3600*30;
  
  static int print_stats = 1;
 +static int debug_ts = 0;
 +static int current_time;
  
  #if HAVE_PTHREADS
  /* signal to input threads that they should exit; set by the main thread */
  static int transcoding_finished;
  #endif
  
 -#define DEFAULT_PASS_LOGFILENAME_PREFIX "av2pass"
 +#define DEFAULT_PASS_LOGFILENAME_PREFIX "ffmpeg2pass"
  
  typedef struct InputFilter {
      AVFilterContext    *filter;
@@@ -224,17 -193,13 +224,17 @@@ typedef struct InputStream 
       * several frames in a packet) of the next frame in current packet */
      int64_t       next_dts;
      /* dts of the last packet read for this stream */
 -    int64_t       last_dts;
 -    PtsCorrectionContext pts_ctx;
 +    int64_t       dts;
 +
 +    int64_t       next_pts;  /* synthetic pts for the next decode frame */
 +    int64_t       pts;       /* current pts of the decoded frame */
      double ts_scale;
      int is_start;            /* is 1 at the start and after a discontinuity */
 +    int saw_first_ts;
      int showed_multi_packet_warning;
      AVDictionary *opts;
      AVRational framerate;               /* framerate forced with -r */
 +    int top_field_first;
  
      int resample_height;
      int resample_width;
  
      /* a pool of free buffers for decoded data */
      FrameBuffer *buffer_pool;
 +    int dr1;
  
      /* decoded data from this stream goes into all those filters
       * currently video and audio only */
  typedef struct InputFile {
      AVFormatContext *ctx;
      int eof_reached;      /* true if eof reached */
 -    int ist_index;        /* index of first stream in ist_table */
 +    int ist_index;        /* index of first stream in input_streams */
      int buffer_size;      /* current total buffer size */
      int64_t ts_offset;
 -    int nb_streams;       /* number of stream that avconv is aware of; may be different
 +    int nb_streams;       /* number of stream that ffmpeg is aware of; may be different
                               from ctx.nb_streams if new streams appear during av_read_frame() */
      int rate_emu;
  
@@@ -284,6 -248,7 +284,6 @@@ typedef struct OutputStream 
      int frame_number;
      /* input pts and corresponding output pts
         for A/V sync */
 -    // double sync_ipts;        /* dts from the AVPacket of the demuxer in second units */
      struct InputStream *sync_ist; /* input stream to sync against */
      int64_t sync_opts;       /* output frame counter, could be changed to some true timestamp */ // FIXME look at frame_number
      /* pts of the first frame encoded for this stream, used for limiting
      int forced_kf_count;
      int forced_kf_index;
  
 +    /* audio only */
 +    int audio_channels_map[SWR_CH_MAX];  /* list of the channels id to pick from the source stream */
 +    int audio_channels_mapped;           /* number of channels in audio_channels_map */
 +
      FILE *logfile;
  
      OutputFilter *filter;
      char *avfilter;
  
      int64_t sws_flags;
 +    int64_t swr_dither_method;
 +    double swr_dither_scale;
      AVDictionary *opts;
      int is_past_recording_time;
      int stream_copy;
      const char *attachment_filename;
      int copy_initial_nonkeyframes;
  
 -    enum PixelFormat pix_fmts[2];
 +    int keep_pix_fmt;
  } OutputStream;
  
  
 +#if HAVE_TERMIOS_H
 +
 +/* init terminal so that we can grab keys */
 +static struct termios oldtty;
 +static int restore_tty;
 +#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 */
 -    uint64_t limit_filesize;
 +    uint64_t limit_filesize; /* filesize limit expressed in bytes */
  } OutputFile;
  
  static InputStream **input_streams = NULL;
@@@ -388,8 -340,9 +388,8 @@@ typedef struct OptionsContext 
      /* output options */
      StreamMap *stream_maps;
      int     nb_stream_maps;
 -    /* first item specifies output metadata, second is input */
 -    MetadataMap (*meta_data_maps)[2];
 -    int nb_meta_data_maps;
 +    AudioChannelMap *audio_channel_maps; /* one info entry per -map_channel */
 +    int           nb_audio_channel_maps; /* number of (valid) -map_channel settings */
      int metadata_global_manual;
      int metadata_streams_manual;
      int metadata_chapters_manual;
      int        nb_filters;
  } OptionsContext;
  
 +static void do_video_stats(AVFormatContext *os, OutputStream *ost, int frame_size);
 +
  #define MATCH_PER_STREAM_OPT(name, type, outvar, fmtctx, st)\
  {\
      int i, ret;\
      }\
  }
  
 -static void reset_options(OptionsContext *o)
 +static int64_t getutime(void)
 +{
 +#if HAVE_GETRUSAGE
 +    struct rusage rusage;
 +
 +    getrusage(RUSAGE_SELF, &rusage);
 +    return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
 +#elif HAVE_GETPROCESSTIMES
 +    HANDLE proc;
 +    FILETIME c, e, k, u;
 +    proc = GetCurrentProcess();
 +    GetProcessTimes(proc, &c, &e, &k, &u);
 +    return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
 +#else
 +    return av_gettime();
 +#endif
 +}
 +
 +static void update_benchmark(const char *fmt, ...)
 +{
 +    if (do_benchmark_all) {
 +        int64_t t = getutime();
 +        va_list va;
 +        char buf[1024];
 +
 +        if (fmt) {
 +            va_start(va, fmt);
 +            vsnprintf(buf, sizeof(buf), fmt, va);
 +            va_end(va);
 +            printf("bench: %8"PRIu64" %s \n", t - current_time, buf);
 +        }
 +        current_time = t;
 +    }
 +}
 +
 +static void reset_options(OptionsContext *o, int is_input)
  {
      const OptionDef *po = options;
 +    OptionsContext bak= *o;
      int i;
  
      /* all OPT_SPEC and OPT_STRING can be freed in generic way */
      for (i = 0; i < o->nb_stream_maps; i++)
          av_freep(&o->stream_maps[i].linklabel);
      av_freep(&o->stream_maps);
 -    av_freep(&o->meta_data_maps);
 +    av_freep(&o->audio_channel_maps);
      av_freep(&o->streamid_map);
  
      memset(o, 0, sizeof(*o));
  
 +    if(is_input) o->recording_time = bak.recording_time;
 +    else         o->recording_time = INT64_MAX;
      o->mux_max_delay  = 0.7;
 -    o->recording_time = INT64_MAX;
      o->limit_filesize = UINT64_MAX;
      o->chapters_input_file = INT_MAX;
  
      init_opts();
  }
  
 +static enum PixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum PixelFormat target)
 +{
 +    if (codec && codec->pix_fmts) {
 +        const enum PixelFormat *p = codec->pix_fmts;
 +        int has_alpha= av_pix_fmt_descriptors[target].nb_components % 2 == 0;
 +        enum PixelFormat best= PIX_FMT_NONE;
 +        if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
 +            if (st->codec->codec_id == CODEC_ID_MJPEG) {
 +                p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
 +            } else if (st->codec->codec_id == CODEC_ID_LJPEG) {
 +                p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
 +                                                 PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
 +            }
 +        }
 +        for (; *p != PIX_FMT_NONE; p++) {
 +            best= avcodec_find_best_pix_fmt2(best, *p, target, has_alpha, NULL);
 +            if (*p == target)
 +                break;
 +        }
 +        if (*p == PIX_FMT_NONE) {
 +            if (target != PIX_FMT_NONE)
 +                av_log(NULL, AV_LOG_WARNING,
 +                       "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
 +                       av_pix_fmt_descriptors[target].name,
 +                       codec->name,
 +                       av_pix_fmt_descriptors[best].name);
 +            return best;
 +        }
 +    }
 +    return target;
 +}
 +
 +static char *choose_pix_fmts(OutputStream *ost)
 +{
 +     if (ost->keep_pix_fmt) {
 +        if (ost->filter)
 +            avfilter_graph_set_auto_convert(ost->filter->graph->graph,
 +                                            AVFILTER_AUTO_CONVERT_NONE);
 +        if (ost->st->codec->pix_fmt == PIX_FMT_NONE)
 +            return NULL;
 +        return av_strdup(av_get_pix_fmt_name(ost->st->codec->pix_fmt));
 +    }
 +    if (ost->st->codec->pix_fmt != PIX_FMT_NONE) {
 +        return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc, ost->st->codec->pix_fmt)));
 +    } else if (ost->enc && ost->enc->pix_fmts) {
 +        const enum PixelFormat *p;
 +        AVIOContext *s = NULL;
 +        uint8_t *ret;
 +        int len;
 +
 +        if (avio_open_dyn_buf(&s) < 0)
 +            exit_program(1);
 +
 +        p = ost->enc->pix_fmts;
 +        if (ost->st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
 +            if (ost->st->codec->codec_id == CODEC_ID_MJPEG) {
 +                p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
 +            } else if (ost->st->codec->codec_id == CODEC_ID_LJPEG) {
 +                p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
 +                                                    PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
 +            }
 +        }
 +
 +        for (; *p != PIX_FMT_NONE; p++) {
 +            const char *name = av_get_pix_fmt_name(*p);
 +            avio_printf(s, "%s:", name);
 +        }
 +        len = avio_close_dyn_buf(s, &ret);
 +        ret[len - 1] = 0;
 +        return ret;
 +    } else
 +        return NULL;
 +}
 +
  /**
   * Define a function for building a string containing a list of
   * allowed formats,
@@@ -647,8 -487,8 +647,8 @@@ static char *choose_ ## var ## s(Output
  #define GET_PIX_FMT_NAME(pix_fmt)\
      const char *name = av_get_pix_fmt_name(pix_fmt);
  
 -DEF_CHOOSE_FORMAT(enum PixelFormat, pix_fmt, pix_fmts, PIX_FMT_NONE,
 -                  GET_PIX_FMT_NAME, ":")
 +// DEF_CHOOSE_FORMAT(enum PixelFormat, pix_fmt, pix_fmts, PIX_FMT_NONE,
 +//                   GET_PIX_FMT_NAME, ":")
  
  #define GET_SAMPLE_FMT_NAME(sample_fmt)\
      const char *name = av_get_sample_fmt_name(sample_fmt)
@@@ -707,7 -547,7 +707,7 @@@ static FilterGraph *init_simple_filterg
  
  static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
  {
 -    InputStream *ist;
 +    InputStream *ist = NULL;
      enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx);
      int i;
  
          int file_idx = strtol(in->name, &p, 0);
  
          if (file_idx < 0 || file_idx >= nb_input_files) {
 -            av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtegraph description %s.\n",
 +            av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
                     file_idx, fg->graph_desc);
              exit_program(1);
          }
          }
          if (i == nb_input_streams) {
              av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
 -                   "unlabeled input pad %d on filter %s", in->pad_idx,
 +                   "unlabeled input pad %d on filter %s\n", in->pad_idx,
                     in->filter_ctx->name);
              exit_program(1);
          }
@@@ -783,19 -623,11 +783,19 @@@ static int configure_output_video_filte
      AVFilterContext *last_filter = out->filter_ctx;
      int pad_idx = out->pad_idx;
      int ret;
 +    AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
  
 -
 +#if FF_API_OLD_VSINK_API
      ret = avfilter_graph_create_filter(&ofilter->filter,
                                         avfilter_get_by_name("buffersink"),
 -                                       "out", NULL, pix_fmts, fg->graph);
 +                                       "ffmpeg_buffersink", NULL, NULL, fg->graph);
 +#else
 +    ret = avfilter_graph_create_filter(&ofilter->filter,
 +                                       avfilter_get_by_name("buffersink"),
 +                                       "ffmpeg_buffersink", NULL, buffersink_params, fg->graph);
 +#endif
 +    av_freep(&buffersink_params);
 +
      if (ret < 0)
          return ret;
  
          av_freep(&pix_fmts);
      }
  
 -    if (ost->frame_rate.num) {
 +    if (ost->frame_rate.num && 0) {
          AVFilterContext *fps;
          char args[255];
  
@@@ -866,44 -698,11 +866,44 @@@ static int configure_output_audio_filte
      int ret;
  
      ret = avfilter_graph_create_filter(&ofilter->filter,
 -                                       avfilter_get_by_name("abuffersink"),
 -                                       "out", NULL, NULL, fg->graph);
 +                                       avfilter_get_by_name("abuffersink_old"),
 +                                       "ffmpeg_abuffersink_old", NULL, NULL, fg->graph);
      if (ret < 0)
          return ret;
  
 +#define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do {                 \
 +    AVFilterContext *filt_ctx;                                              \
 +                                                                            \
 +    av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi "            \
 +           "similarly to -af " filter_name "=%s.\n", arg);                  \
 +                                                                            \
 +    ret = avfilter_graph_create_filter(&filt_ctx,                           \
 +                                       avfilter_get_by_name(filter_name),   \
 +                                       filter_name, arg, NULL, fg->graph);  \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0);                 \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    last_filter = filt_ctx;                                                 \
 +    pad_idx = 0;                                                            \
 +} while (0)
 +    if (ost->audio_channels_mapped) {
 +        int i;
 +        AVBPrint pan_buf;
 +        av_bprint_init(&pan_buf, 256, 8192);
 +        av_bprintf(&pan_buf, "0x%"PRIx64,
 +                   av_get_default_channel_layout(ost->audio_channels_mapped));
 +        for (i = 0; i < ost->audio_channels_mapped; i++)
 +            if (ost->audio_channels_map[i] != -1)
 +                av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]);
 +
 +        AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str);
 +        av_bprint_finalize(&pan_buf, NULL);
 +    }
 +
      if (codec->channels && !codec->channel_layout)
          codec->channel_layout = av_get_default_channel_layout(codec->channels);
  
          pad_idx = 0;
      }
  
 -    if (audio_sync_method > 0) {
 -        AVFilterContext *async;
 -        char args[256];
 -        int  len = 0;
 -
 -        av_log(NULL, AV_LOG_WARNING, "-async has been deprecated. Used the "
 -               "asyncts audio filter instead.\n");
 +    if (audio_sync_method > 0 && 0) {
 +        char args[256] = {0};
  
 +        av_strlcatf(args, sizeof(args), "min_comp=0.001:min_hard_comp=%f", audio_drift_threshold);
          if (audio_sync_method > 1)
 -            len += snprintf(args + len, sizeof(args) - len, "compensate=1:"
 -                            "max_comp=%d:", audio_sync_method);
 -        snprintf(args + len, sizeof(args) - len, "min_delta=%f",
 -                 audio_drift_threshold);
 -
 -        ret = avfilter_graph_create_filter(&async,
 -                                           avfilter_get_by_name("asyncts"),
 -                                           "async", args, NULL, fg->graph);
 -        if (ret < 0)
 -            return ret;
 +            av_strlcatf(args, sizeof(args), ":max_soft_comp=%d", -audio_sync_method);
 +        AUTO_INSERT_FILTER("-async", "aresample", args);
 +    }
  
 -        ret = avfilter_link(last_filter, pad_idx, async, 0);
 -        if (ret < 0)
 -            return ret;
 +    if (audio_volume != 256 && 0) {
 +        char args[256];
  
 -        last_filter = async;
 -        pad_idx = 0;
 +        snprintf(args, sizeof(args), "%f", audio_volume / 256.);
 +        AUTO_INSERT_FILTER("-vol", "volume", args);
      }
  
      if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
@@@ -1004,30 -815,20 +1004,30 @@@ static int configure_input_video_filter
      AVRational tb = ist->framerate.num ? (AVRational){ist->framerate.den,
                                                        ist->framerate.num} :
                                           ist->st->time_base;
 +    AVRational fr = ist->framerate.num ? ist->framerate :
 +                                         ist->st->r_frame_rate;
      AVRational sar;
 -    char args[255];
 +    AVBPrint args;
      int pad_idx = in->pad_idx;
      int ret;
  
      sar = ist->st->sample_aspect_ratio.num ?
            ist->st->sample_aspect_ratio :
            ist->st->codec->sample_aspect_ratio;
 -    snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
 +    if(!sar.den)
 +        sar = (AVRational){0,1};
 +    av_bprint_init(&args, 0, 1);
 +    av_bprintf(&args,
 +             "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:"
 +             "pixel_aspect=%d/%d:sws_param=flags=%d", ist->st->codec->width,
               ist->st->codec->height, ist->st->codec->pix_fmt,
 -             tb.num, tb.den, sar.num, sar.den);
 +             tb.num, tb.den, sar.num, sar.den,
 +             SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
 +    if (fr.num && fr.den)
 +        av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den);
  
      if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, in->name,
 -                                            args, NULL, fg->graph)) < 0)
 +                                            args.str, NULL, fg->graph)) < 0)
          return ret;
  
      if (ist->framerate.num) {
@@@ -1073,52 -874,32 +1073,52 @@@ static int configure_input_audio_filter
                                              fg->graph)) < 0)
          return ret;
  
 -    if (audio_sync_method > 0) {
 -        AVFilterContext *async;
 -        char args[256];
 -        int  len = 0;
 +#define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do {                 \
 +    AVFilterContext *filt_ctx;                                              \
 +                                                                            \
 +    av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi "            \
 +           "similarly to -af " filter_name "=%s.\n", arg);                  \
 +                                                                            \
 +    ret = avfilter_graph_create_filter(&filt_ctx,                           \
 +                                       avfilter_get_by_name(filter_name),   \
 +                                       filter_name, arg, NULL, fg->graph);  \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    ret = avfilter_link(filt_ctx, 0, first_filter, pad_idx);                \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    first_filter = filt_ctx;                                                  \
 +} while (0)
  
 -        av_log(NULL, AV_LOG_WARNING, "-async has been deprecated. Used the "
 -               "asyncts audio filter instead.\n");
 +    if (audio_sync_method > 0) {
 +        char args[256] = {0};
  
 +        av_strlcatf(args, sizeof(args), "min_comp=0.001:min_hard_comp=%f", audio_drift_threshold);
          if (audio_sync_method > 1)
 -            len += snprintf(args + len, sizeof(args) - len, "compensate=1:"
 -                            "max_comp=%d:", audio_sync_method);
 -        snprintf(args + len, sizeof(args) - len, "min_delta=%f",
 -                 audio_drift_threshold);
 -
 -        ret = avfilter_graph_create_filter(&async,
 -                                           avfilter_get_by_name("asyncts"),
 -                                           "async", args, NULL, fg->graph);
 -        if (ret < 0)
 -            return ret;
 +            av_strlcatf(args, sizeof(args), ":max_soft_comp=%f", audio_sync_method/(double)ist->st->codec->sample_rate);
 +        AUTO_INSERT_FILTER_INPUT("-async", "aresample", args);
 +    }
 +
 +//     if (ost->audio_channels_mapped) {
 +//         int i;
 +//         AVBPrint pan_buf;
 +//         av_bprint_init(&pan_buf, 256, 8192);
 +//         av_bprintf(&pan_buf, "0x%"PRIx64,
 +//                    av_get_default_channel_layout(ost->audio_channels_mapped));
 +//         for (i = 0; i < ost->audio_channels_mapped; i++)
 +//             if (ost->audio_channels_map[i] != -1)
 +//                 av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]);
 +//         AUTO_INSERT_FILTER_INPUT("-map_channel", "pan", pan_buf.str);
 +//         av_bprint_finalize(&pan_buf, NULL);
 +//     }
  
 -        ret = avfilter_link(async, 0, first_filter, pad_idx);
 -        if (ret < 0)
 -            return ret;
 +    if (audio_volume != 256) {
 +        char args[256];
  
 -        first_filter = async;
 -        pad_idx = 0;
 +        snprintf(args, sizeof(args), "%f", audio_volume / 256.);
 +        AUTO_INSERT_FILTER_INPUT("-vol", "volume", args);
      }
      if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
          return ret;
@@@ -1222,54 -1003,22 +1222,54 @@@ static int ist_in_filtergraph(FilterGra
  
  static void term_exit(void)
  {
 -    av_log(NULL, AV_LOG_QUIET, "");
 +    av_log(NULL, AV_LOG_QUIET, "%s", "");
 +#if HAVE_TERMIOS_H
 +    if(restore_tty)
 +        tcsetattr (0, TCSANOW, &oldtty);
 +#endif
  }
  
  static volatile int received_sigterm = 0;
 -static volatile int received_nb_signals = 0;
  
 -static void
 -sigterm_handler(int sig)
 +static void sigterm_handler(int sig)
  {
      received_sigterm = sig;
      received_nb_signals++;
      term_exit();
 +    if(received_nb_signals > 3)
 +        exit(123);
  }
  
  static void term_init(void)
  {
 +#if HAVE_TERMIOS_H
 +    if(!run_as_daemon){
 +        struct termios tty;
 +        int istty = 1;
 +#if HAVE_ISATTY
 +        istty = isatty(0) && isatty(2);
 +#endif
 +        if (istty && tcgetattr (0, &tty) == 0) {
 +            oldtty = tty;
 +            restore_tty = 1;
 +            atexit(term_exit);
 +
 +            tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
 +                             |INLCR|IGNCR|ICRNL|IXON);
 +            tty.c_oflag |= OPOST;
 +            tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
 +            tty.c_cflag &= ~(CSIZE|PARENB);
 +            tty.c_cflag |= CS8;
 +            tty.c_cc[VMIN] = 1;
 +            tty.c_cc[VTIME] = 0;
 +
 +            tcsetattr (0, TCSANOW, &tty);
 +        }
 +        signal(SIGQUIT, sigterm_handler); /* Quit (POSIX).  */
 +    }
 +#endif
 +    avformat_network_deinit();
 +
      signal(SIGINT , sigterm_handler); /* Interrupt (ANSI).    */
      signal(SIGTERM, sigterm_handler); /* Termination (ANSI).  */
  #ifdef SIGXCPU
  #endif
  }
  
 +/* read a key without blocking */
 +static int read_key(void)
 +{
 +    unsigned char ch;
 +#if HAVE_TERMIOS_H
 +    int n = 1;
 +    struct timeval tv;
 +    fd_set rfds;
 +
 +    FD_ZERO(&rfds);
 +    FD_SET(0, &rfds);
 +    tv.tv_sec = 0;
 +    tv.tv_usec = 0;
 +    n = select(1, &rfds, NULL, NULL, &tv);
 +    if (n > 0) {
 +        n = read(0, &ch, 1);
 +        if (n == 1)
 +            return ch;
 +
 +        return n;
 +    }
 +#elif HAVE_KBHIT
 +#    if HAVE_PEEKNAMEDPIPE
 +    static int is_pipe;
 +    static HANDLE input_handle;
 +    DWORD dw, nchars;
 +    if(!input_handle){
 +        input_handle = GetStdHandle(STD_INPUT_HANDLE);
 +        is_pipe = !GetConsoleMode(input_handle, &dw);
 +    }
 +
 +    if (stdin->_cnt > 0) {
 +        read(0, &ch, 1);
 +        return ch;
 +    }
 +    if (is_pipe) {
 +        /* When running under a GUI, you will end here. */
 +        if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL))
 +            return -1;
 +        //Read it
 +        if(nchars != 0) {
 +            read(0, &ch, 1);
 +            return ch;
 +        }else{
 +            return -1;
 +        }
 +    }
 +#    endif
 +    if(kbhit())
 +        return(getch());
 +#endif
 +    return -1;
 +}
 +
  static int decode_interrupt_cb(void *ctx)
  {
      return received_nb_signals > 1;
  
  static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
  
 -void exit_program(int ret)
 +void av_noreturn exit_program(int ret)
  {
      int i, j;
  
          }
          output_streams[i]->bitstream_filters = NULL;
  
 -        av_freep(&output_streams[i]->avfilter);
          av_freep(&output_streams[i]->filtered_frame);
 +        av_freep(&output_streams[i]->avfilter);
          av_freep(&output_streams[i]);
      }
      for (i = 0; i < nb_input_files; i++) {
@@@ -1441,25 -1136,43 +1441,25 @@@ static void assert_codec_experimental(A
      }
  }
  
 -/**
 - * Update the requested input sample format based on the output sample format.
 - * This is currently only used to request float output from decoders which
 - * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT.
 - * Ideally this will be removed in the future when decoders do not do format
 - * conversion and only output in their native format.
 - */
 -static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec,
 -                              AVCodecContext *enc)
 +static void choose_sample_fmt(AVStream *st, AVCodec *codec)
  {
 -    /* if sample formats match or a decoder sample format has already been
 -       requested, just return */
 -    if (enc->sample_fmt == dec->sample_fmt ||
 -        dec->request_sample_fmt > AV_SAMPLE_FMT_NONE)
 -        return;
 -
 -    /* if decoder supports more than one output format */
 -    if (dec_codec && dec_codec->sample_fmts &&
 -        dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE &&
 -        dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) {
 -        const enum AVSampleFormat *p;
 -        int min_dec = -1, min_inc = -1;
 -
 -        /* find a matching sample format in the encoder */
 -        for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) {
 -            if (*p == enc->sample_fmt) {
 -                dec->request_sample_fmt = *p;
 -                return;
 -            } else if (*p > enc->sample_fmt) {
 -                min_inc = FFMIN(min_inc, *p - enc->sample_fmt);
 -            } else
 -                min_dec = FFMIN(min_dec, enc->sample_fmt - *p);
 +    if (codec && codec->sample_fmts) {
 +        const enum AVSampleFormat *p = codec->sample_fmts;
 +        for (; *p != -1; p++) {
 +            if (*p == st->codec->sample_fmt)
 +                break;
 +        }
 +        if (*p == -1) {
 +            if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
 +                av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
 +            if(av_get_sample_fmt_name(st->codec->sample_fmt))
 +            av_log(NULL, AV_LOG_WARNING,
 +                   "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
 +                   av_get_sample_fmt_name(st->codec->sample_fmt),
 +                   codec->name,
 +                   av_get_sample_fmt_name(codec->sample_fmts[0]));
 +            st->codec->sample_fmt = codec->sample_fmts[0];
          }
 -
 -        /* if none match, provide the one that matches quality closest */
 -        dec->request_sample_fmt = min_inc > 0 ? enc->sample_fmt + min_inc :
 -                                  enc->sample_fmt - min_dec;
      }
  }
  
@@@ -1469,18 -1182,6 +1469,18 @@@ static void write_frame(AVFormatContex
      AVCodecContext          *avctx = ost->st->codec;
      int ret;
  
 +    if ((avctx->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
 +        (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
 +        pkt->pts = pkt->dts = AV_NOPTS_VALUE;
 +
 +    if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
 +        int64_t max = ost->st->cur_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
 +        if (ost->st->cur_dts && ost->st->cur_dts != AV_NOPTS_VALUE &&  max > pkt->dts) {
 +            av_log(s, max - pkt->dts > 2 ? AV_LOG_WARNING : AV_LOG_DEBUG, "Audio timestamp %"PRId64" < %"PRId64" invalid, cliping\n", pkt->dts, max);
 +            pkt->pts = pkt->dts = max;
 +        }
 +    }
 +
      /*
       * Audio encoders may split the packets --  #frames in != #packets out.
       * But there is no reordering, so we can limit the number of output packets
              av_free_packet(pkt);
              new_pkt.destruct = av_destruct_packet;
          } else if (a < 0) {
 -            av_log(NULL, AV_LOG_ERROR, "%s failed for stream %d, codec %s",
 +            av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s",
                     bsfc->filter->name, pkt->stream_index,
                     avctx->codec ? avctx->codec->name : "copy");
              print_error("", a);
@@@ -1549,21 -1250,18 +1549,21 @@@ static void do_audio_out(AVFormatContex
      av_init_packet(&pkt);
      pkt.data = NULL;
      pkt.size = 0;
 -
 +#if 0
      if (!check_recording_time(ost))
          return;
 -
 +#endif
      if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0)
          frame->pts = ost->sync_opts;
      ost->sync_opts = frame->pts + frame->nb_samples;
  
 +    av_assert0(pkt.size || !pkt.data);
 +    update_benchmark(NULL);
      if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
 -        av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n");
 +        av_log(NULL, AV_LOG_FATAL, "Audio encoding failed (avcodec_encode_audio2)\n");
          exit_program(1);
      }
 +    update_benchmark("encode_audio %d.%d", ost->file_index, ost->index);
  
      if (got_packet) {
          if (pkt.pts != AV_NOPTS_VALUE)
          if (pkt.duration > 0)
              pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
  
 +        if (debug_ts) {
 +            av_log(NULL, AV_LOG_INFO, "encoder -> type:audio "
 +                   "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n",
 +                   av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base),
 +                   av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
 +        }
 +
          write_frame(s, &pkt, ost);
  
          audio_size += pkt.size;
 +        av_free_packet(&pkt);
      }
  }
  
@@@ -1661,6 -1351,8 +1661,6 @@@ static void do_subtitle_out(AVFormatCon
  
      for (i = 0; i < nb; i++) {
          ost->sync_opts = av_rescale_q(pts, ist->st->time_base, enc->time_base);
 -        if (!check_recording_time(ost))
 -            return;
  
          sub->pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q);
          // start_display_time is required to be 0
          pkt.data = subtitle_out;
          pkt.size = subtitle_out_size;
          pkt.pts  = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base);
 +        pkt.duration = av_rescale_q(sub->end_display_time, (AVRational){ 1, 1000 }, ost->st->time_base);
          if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
              /* XXX: the pts correction is handled here. Maybe handling
                 it in the codec would be better */
  static void do_video_out(AVFormatContext *s,
                           OutputStream *ost,
                           AVFrame *in_picture,
 -                         int *frame_size, float quality)
 +                         float quality)
  {
      int ret, format_video_sync;
      AVPacket pkt;
      AVCodecContext *enc = ost->st->codec;
 +    int nb_frames;
 +    double sync_ipts, delta;
 +    double duration = 0;
 +    int frame_size = 0;
 +    InputStream *ist = NULL;
 +
 +    if (ost->source_index >= 0)
 +        ist = input_streams[ost->source_index];
 +
 +    if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num)
 +        duration = 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base));
  
 -    *frame_size = 0;
 +    sync_ipts = in_picture->pts;
 +    delta = sync_ipts - ost->sync_opts + duration;
 +
 +    /* by default, we output a single frame */
 +    nb_frames = 1;
  
      format_video_sync = video_sync_method;
      if (format_video_sync == VSYNC_AUTO)
 -        format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH :
 -                            (s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR;
 -    if (format_video_sync != VSYNC_PASSTHROUGH &&
 -        ost->frame_number &&
 -        in_picture->pts != AV_NOPTS_VALUE &&
 -        in_picture->pts < ost->sync_opts) {
 +        format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : 1;
 +
 +    switch (format_video_sync) {
 +    case VSYNC_CFR:
 +        // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
 +        if (delta < -1.1)
 +            nb_frames = 0;
 +        else if (delta > 1.1)
 +            nb_frames = lrintf(delta);
 +        break;
 +    case VSYNC_VFR:
 +        if (delta <= -0.6)
 +            nb_frames = 0;
 +        else if (delta > 0.6)
 +            ost->sync_opts = lrint(sync_ipts);
 +        break;
 +    case VSYNC_DROP:
 +    case VSYNC_PASSTHROUGH:
 +        ost->sync_opts = lrint(sync_ipts);
 +        break;
 +    default:
 +        av_assert0(0);
 +    }
 +
 +    nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
 +    if (nb_frames == 0) {
          nb_frames_drop++;
          av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n");
          return;
 +    } else if (nb_frames > 1) {
 +        nb_frames_dup += nb_frames - 1;
 +        av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
      }
  
 -    if (in_picture->pts == AV_NOPTS_VALUE)
 -        in_picture->pts = ost->sync_opts;
 -    ost->sync_opts = in_picture->pts;
 -
 -
 -    if (!ost->frame_number)
 -        ost->first_pts = in_picture->pts;
  
 +duplicate_frame:
      av_init_packet(&pkt);
      pkt.data = NULL;
      pkt.size = 0;
  
 -    if (!check_recording_time(ost) ||
 -        ost->frame_number >= ost->max_frames)
 -        return;
 +    in_picture->pts = ost->sync_opts;
  
      if (s->oformat->flags & AVFMT_RAWPICTURE &&
          enc->codec->id == CODEC_ID_RAWVIDEO) {
          pkt.flags |= AV_PKT_FLAG_KEY;
  
          write_frame(s, &pkt, ost);
 +        video_size += pkt.size;
      } else {
          int got_packet;
          AVFrame big_picture;
              big_picture.pict_type = AV_PICTURE_TYPE_I;
              ost->forced_kf_index++;
          }
 +        update_benchmark(NULL);
          ret = avcodec_encode_video2(enc, &pkt, &big_picture, &got_packet);
 +        update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
          if (ret < 0) {
              av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
              exit_program(1);
          }
  
          if (got_packet) {
 +            if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
 +                pkt.pts = ost->sync_opts;
 +
              if (pkt.pts != AV_NOPTS_VALUE)
                  pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
              if (pkt.dts != AV_NOPTS_VALUE)
                  pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
  
 +            if (debug_ts) {
 +                av_log(NULL, AV_LOG_INFO, "encoder -> type:video "
 +                    "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n",
 +                    av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base),
 +                    av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
 +            }
 +
              write_frame(s, &pkt, ost);
 -            *frame_size = pkt.size;
 +            frame_size = pkt.size;
              video_size += pkt.size;
 +            av_free_packet(&pkt);
  
              /* if two pass, output log */
              if (ost->logfile && enc->stats_out) {
       * flush, we need to limit them here, before they go into encoder.
       */
      ost->frame_number++;
 +
 +    if(--nb_frames)
 +        goto duplicate_frame;
 +
 +    if (vstats_filename && frame_size)
 +        do_video_stats(output_files[ost->file_index]->ctx, ost, frame_size);
  }
  
  static double psnr(double d)
@@@ -1897,113 -1538,73 +1897,113 @@@ static int poll_filters(void
  {
      AVFilterBufferRef *picref;
      AVFrame *filtered_frame = NULL;
 -    int i, frame_size;
 +    int i, ret, ret_all;
 +    unsigned nb_success, nb_eof;
 +    int64_t frame_pts;
  
 -    for (i = 0; i < nb_output_streams; i++) {
 -        OutputStream *ost = output_streams[i];
 -        OutputFile    *of = output_files[ost->file_index];
 -        int ret = 0;
 +    while (1) {
 +        /* Reap all buffers present in the buffer sinks */
 +        for (i = 0; i < nb_output_streams; i++) {
 +            OutputStream *ost = output_streams[i];
 +            OutputFile    *of = output_files[ost->file_index];
 +            int ret = 0;
  
 -        if (!ost->filter)
 -            continue;
 +            if (!ost->filter)
 +                continue;
  
 -        if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
 -            return AVERROR(ENOMEM);
 -        } else
 -            avcodec_get_frame_defaults(ost->filtered_frame);
 -        filtered_frame = ost->filtered_frame;
 -
 -        while (ret >= 0 && !ost->is_past_recording_time) {
 -            if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
 -                !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
 -                ret = av_buffersink_read_samples(ost->filter->filter, &picref,
 -                                                 ost->st->codec->frame_size);
 -            else
 -                ret = av_buffersink_read(ost->filter->filter, &picref);
 +            if (!ost->filtered_frame && !(ost->filtered_frame = avcodec_alloc_frame())) {
 +                return AVERROR(ENOMEM);
 +            } else
 +                avcodec_get_frame_defaults(ost->filtered_frame);
 +            filtered_frame = ost->filtered_frame;
 +
 +            while (!ost->is_past_recording_time) {
 +                if (ost->enc->type == AVMEDIA_TYPE_AUDIO &&
 +                    !(ost->enc->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE))
 +                    ret = av_buffersink_read_samples(ost->filter->filter, &picref,
 +                                                    ost->st->codec->frame_size);
 +                else
 +#ifdef SINKA
 +                    ret = av_buffersink_read(ost->filter->filter, &picref);
 +#else
 +                    ret = av_buffersink_get_buffer_ref(ost->filter->filter, &picref,
 +                                                       AV_BUFFERSINK_FLAG_NO_REQUEST);
 +#endif
 +                if (ret < 0) {
 +                    if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
 +                        char buf[256];
 +                        av_strerror(ret, buf, sizeof(buf));
 +                        av_log(NULL, AV_LOG_WARNING,
 +                               "Error in av_buffersink_get_buffer_ref(): %s\n", buf);
 +                    }
 +                    break;
 +                }
 +                frame_pts = AV_NOPTS_VALUE;
 +                if (picref->pts != AV_NOPTS_VALUE) {
 +                    filtered_frame->pts = frame_pts = av_rescale_q(picref->pts,
 +                                                    ost->filter->filter->inputs[0]->time_base,
 +                                                    ost->st->codec->time_base) -
 +                                        av_rescale_q(of->start_time,
 +                                                    AV_TIME_BASE_Q,
 +                                                    ost->st->codec->time_base);
 +
 +                    if (of->start_time && filtered_frame->pts < 0) {
 +                        avfilter_unref_buffer(picref);
 +                        continue;
 +                    }
 +                }
 +                //if (ost->source_index >= 0)
 +                //    *filtered_frame= *input_streams[ost->source_index]->decoded_frame; //for me_threshold
  
 -            if (ret < 0)
 -                break;
  
 -            avfilter_copy_buf_props(filtered_frame, picref);
 -            if (picref->pts != AV_NOPTS_VALUE)
 -                filtered_frame->pts = av_rescale_q(picref->pts,
 -                                                   ost->filter->filter->inputs[0]->time_base,
 -                                                   ost->st->codec->time_base) -
 -                                      av_rescale_q(of->start_time,
 -                                                   AV_TIME_BASE_Q,
 -                                                   ost->st->codec->time_base);
 +                switch (ost->filter->filter->inputs[0]->type) {
 +                case AVMEDIA_TYPE_VIDEO:
 +                    avfilter_fill_frame_from_video_buffer_ref(filtered_frame, picref);
 +                    filtered_frame->pts = frame_pts;
 +                    if (!ost->frame_aspect_ratio)
 +                        ost->st->codec->sample_aspect_ratio = picref->video->sample_aspect_ratio;
 +
 +                    do_video_out(of->ctx, ost, filtered_frame,
 +                                 same_quant ? ost->last_quality :
 +                                              ost->st->codec->global_quality);
 +                    break;
 +                case AVMEDIA_TYPE_AUDIO:
 +                    avfilter_copy_buf_props(filtered_frame, picref);
 +                    filtered_frame->pts = frame_pts;
 +                    do_audio_out(of->ctx, ost, filtered_frame);
 +                    break;
 +                default:
 +                    // TODO support subtitle filters
 +                    av_assert0(0);
 +                }
  
 -            if (of->start_time && filtered_frame->pts < of->start_time) {
                  avfilter_unref_buffer(picref);
 -                continue;
              }
 -
 -            switch (ost->filter->filter->inputs[0]->type) {
 -            case AVMEDIA_TYPE_VIDEO:
 -                if (!ost->frame_aspect_ratio)
 -                    ost->st->codec->sample_aspect_ratio = picref->video->pixel_aspect;
 -
 -                do_video_out(of->ctx, ost, filtered_frame, &frame_size,
 -                             same_quant ? ost->last_quality :
 -                                          ost->st->codec->global_quality);
 -                if (vstats_filename && frame_size)
 -                    do_video_stats(of->ctx, ost, frame_size);
 -                break;
 -            case AVMEDIA_TYPE_AUDIO:
 -                do_audio_out(of->ctx, ost, filtered_frame);
 -                break;
 -            default:
 -                // TODO support subtitle filters
 -                av_assert0(0);
 +        }
 +        /* Request frames through all the graphs */
 +        ret_all = nb_success = nb_eof = 0;
 +        for (i = 0; i < nb_filtergraphs; i++) {
 +            ret = avfilter_graph_request_oldest(filtergraphs[i]->graph);
 +            if (!ret) {
 +                nb_success++;
 +            } else if (ret == AVERROR_EOF) {
 +                nb_eof++;
 +            } else if (ret != AVERROR(EAGAIN)) {
 +                char buf[256];
 +                av_strerror(ret, buf, sizeof(buf));
 +                av_log(NULL, AV_LOG_WARNING,
 +                       "Error in request_frame(): %s\n", buf);
 +                ret_all = ret;
              }
 -
 -            avfilter_unref_buffer(picref);
          }
 +        if (!nb_success)
 +            break;
 +        /* Try again if anything succeeded */
      }
 -    return 0;
 +    return nb_eof == nb_filtergraphs ? AVERROR_EOF : ret_all;
  }
  
 -static void print_report(int is_last_report, int64_t timer_start)
 +static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time)
  {
      char buf[1024];
      OutputStream *ost;
      int64_t total_size;
      AVCodecContext *enc;
      int frame_number, vid, i;
 -    double bitrate, ti1, pts;
 +    double bitrate;
 +    int64_t pts = INT64_MAX;
      static int64_t last_time = -1;
      static int qp_histogram[52];
 +    int hours, mins, secs, us;
  
      if (!print_stats && !is_last_report)
          return;
  
      if (!is_last_report) {
 -        int64_t cur_time;
 -        /* display the report every 0.5 seconds */
 -        cur_time = av_gettime();
          if (last_time == -1) {
              last_time = cur_time;
              return;
      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
 +    if (total_size < 0) // FIXME improve avio_size() so it works with non seekable output too
          total_size = avio_tell(oc->pb);
 +        if (total_size < 0)
 +            total_size = 0;
 +    }
  
      buf[0] = '\0';
 -    ti1 = 1e10;
      vid = 0;
      for (i = 0; i < nb_output_streams; i++) {
          float q = -1;
              snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ", q);
          }
          if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) {
 -            float t = (av_gettime() - timer_start) / 1000000.0;
 +            float fps, t = (cur_time-timer_start) / 1000000.0;
  
              frame_number = ost->frame_number;
 -            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3d q=%3.1f ",
 -                     frame_number, (t > 1) ? (int)(frame_number / t + 0.5) : 0, q);
 +            fps = t > 1 ? frame_number / t : 0;
 +            snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d fps=%3.*f q=%3.1f ",
 +                     frame_number, fps < 9.95, fps, q);
              if (is_last_report)
                  snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
              if (qp_hist) {
              vid = 1;
          }
          /* compute min output value */
 -        pts = (double)ost->st->pts.val * av_q2d(ost->st->time_base);
 -        if ((pts < ti1) && (pts > 0))
 -            ti1 = pts;
 +        pts = FFMIN(pts, av_rescale_q(ost->st->pts.val,
 +                                      ost->st->time_base, AV_TIME_BASE_Q));
      }
 -    if (ti1 < 0.01)
 -        ti1 = 0.01;
  
 -    bitrate = (double)(total_size * 8) / ti1 / 1000.0;
 +    secs = pts / AV_TIME_BASE;
 +    us = pts % AV_TIME_BASE;
 +    mins = secs / 60;
 +    secs %= 60;
 +    hours = mins / 60;
 +    mins %= 60;
  
 +    bitrate = pts ? total_size * 8 / (pts / 1000.0) : 0;
 +
 +    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
 +             "size=%8.0fkB time=", total_size / 1024.0);
      snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
 -            "size=%8.0fkB time=%0.2f bitrate=%6.1fkbits/s",
 -            (double)total_size / 1024, ti1, bitrate);
 +             "%02d:%02d:%02d.%02d ", hours, mins, secs,
 +             (100 * us) / AV_TIME_BASE);
 +    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
 +             "bitrate=%6.1fkbits/s", bitrate);
  
      if (nb_frames_dup || nb_frames_drop)
          snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
                 extra_size / 1024.0,
                 100.0 * (total_size - raw) / raw
          );
 +        if(video_size + audio_size + extra_size == 0){
 +            av_log(NULL, AV_LOG_WARNING, "Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)\n");
 +        }
      }
  }
  
@@@ -2182,14 -1770,12 +2182,14 @@@ static void flush_encoders(void
                  pkt.data = NULL;
                  pkt.size = 0;
  
 +                update_benchmark(NULL);
                  ret = encode(enc, &pkt, NULL, &got_packet);
 +                update_benchmark("flush %s %d.%d", desc, ost->file_index, ost->index);
                  if (ret < 0) {
                      av_log(NULL, AV_LOG_FATAL, "%s encoding failed\n", desc);
                      exit_program(1);
                  }
 -                *size += ret;
 +                *size += pkt.size;
                  if (ost->logfile && enc->stats_out) {
                      fprintf(ost->logfile, "%s", enc->stats_out);
                  }
@@@ -2221,16 -1807,9 +2221,16 @@@ static int check_output_constraints(Inp
      if (ost->source_index != ist_index)
          return 0;
  
 -    if (of->start_time && ist->last_dts < of->start_time)
 +    if (of->start_time && ist->pts < of->start_time)
          return 0;
  
 +    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;
 +        return 0;
 +    }
 +
      return 1;
  }
  
@@@ -2238,7 -1817,6 +2238,7 @@@ static void do_streamcopy(InputStream *
  {
      OutputFile *of = output_files[ost->file_index];
      int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
 +    AVPicture pict;
      AVPacket opkt;
  
      av_init_packet(&opkt);
          !ost->copy_initial_nonkeyframes)
          return;
  
 -    if (of->recording_time != INT64_MAX &&
 -        ist->last_dts >= of->recording_time + of->start_time) {
 -        ost->is_past_recording_time = 1;
 -        return;
 -    }
 -
      /* force the input stream PTS */
      if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
          audio_size += pkt->size;
          opkt.pts = AV_NOPTS_VALUE;
  
      if (pkt->dts == AV_NOPTS_VALUE)
 -        opkt.dts = av_rescale_q(ist->last_dts, AV_TIME_BASE_Q, ost->st->time_base);
 +        opkt.dts = av_rescale_q(ist->dts, 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.data = pkt->data;
          opkt.size = pkt->size;
      }
 +    if (of->ctx->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(of->ctx, &opkt, ost);
      ost->st->codec->frame_number++;
  static void rate_emu_sleep(InputStream *ist)
  {
      if (input_files[ist->file_index]->rate_emu) {
 -        int64_t pts = av_rescale(ist->last_dts, 1000000, AV_TIME_BASE);
 +        int64_t pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
          int64_t now = av_gettime() - ist->start;
          if (pts > now)
              usleep(pts - now);
@@@ -2326,6 -1903,7 +2326,6 @@@ static int decode_audio(InputStream *is
  {
      AVFrame *decoded_frame;
      AVCodecContext *avctx = ist->st->codec;
 -    int bps = av_get_bytes_per_sample(ist->st->codec->sample_fmt);
      int i, ret, resample_changed;
  
      if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
          avcodec_get_frame_defaults(ist->decoded_frame);
      decoded_frame = ist->decoded_frame;
  
 +    update_benchmark(NULL);
      ret = avcodec_decode_audio4(avctx, decoded_frame, got_output, pkt);
 +    update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index);
      if (ret < 0) {
          return ret;
      }
 +    if (avctx->sample_rate <= 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Sample rate %d invalid\n", avctx->sample_rate);
 +        return AVERROR_INVALIDDATA;
 +    }
  
      if (!*got_output) {
          /* no audio frame */
          if (!pkt->size)
              for (i = 0; i < ist->nb_filters; i++)
 -                av_buffersrc_buffer(ist->filters[i]->filter, NULL);
 +                av_buffersrc_add_ref(ist->filters[i]->filter, NULL,
 +                                     AV_BUFFERSRC_FLAG_NO_COPY);
          return ret;
      }
  
      /* if the decoder provides a pts, use it instead of the last packet pts.
         the decoder could be delaying output by a packet or more. */
      if (decoded_frame->pts != AV_NOPTS_VALUE)
 -        ist->next_dts = decoded_frame->pts;
 +        ist->dts = ist->next_dts = ist->pts = ist->next_pts = decoded_frame->pts;
      else if (pkt->pts != AV_NOPTS_VALUE) {
          decoded_frame->pts = pkt->pts;
          pkt->pts           = AV_NOPTS_VALUE;
 -    }
 +    }else
 +        decoded_frame->pts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);
  
 -    // preprocess audio (volume)
 -    if (audio_volume != 256) {
 -        int decoded_data_size = decoded_frame->nb_samples * avctx->channels * bps;
 -        void *samples = decoded_frame->data[0];
 -        switch (avctx->sample_fmt) {
 -        case AV_SAMPLE_FMT_U8:
 -        {
 -            uint8_t *volp = samples;
 -            for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
 -                int v = (((*volp - 128) * audio_volume + 128) >> 8) + 128;
 -                *volp++ = av_clip_uint8(v);
 -            }
 -            break;
 -        }
 -        case AV_SAMPLE_FMT_S16:
 -        {
 -            int16_t *volp = samples;
 -            for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
 -                int v = ((*volp) * audio_volume + 128) >> 8;
 -                *volp++ = av_clip_int16(v);
 -            }
 -            break;
 -        }
 -        case AV_SAMPLE_FMT_S32:
 -        {
 -            int32_t *volp = samples;
 -            for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
 -                int64_t v = (((int64_t)*volp * audio_volume + 128) >> 8);
 -                *volp++ = av_clipl_int32(v);
 -            }
 -            break;
 -        }
 -        case AV_SAMPLE_FMT_FLT:
 -        {
 -            float *volp = samples;
 -            float scale = audio_volume / 256.f;
 -            for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
 -                *volp++ *= scale;
 -            }
 -            break;
 -        }
 -        case AV_SAMPLE_FMT_DBL:
 -        {
 -            double *volp = samples;
 -            double scale = audio_volume / 256.;
 -            for (i = 0; i < (decoded_data_size / sizeof(*volp)); i++) {
 -                *volp++ *= scale;
 -            }
 -            break;
 -        }
 -        default:
 -            av_log(NULL, AV_LOG_FATAL,
 -                   "Audio volume adjustment on sample format %s is not supported.\n",
 -                   av_get_sample_fmt_name(ist->st->codec->sample_fmt));
 -            exit_program(1);
 -        }
 -    }
 +
 +#if 1
 +    /* increment next_dts to use for the case where the input stream does not
 +       have timestamps or there are multiple frames in the packet */
 +    ist->next_pts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
 +                     avctx->sample_rate;
 +    ist->next_dts += ((int64_t)AV_TIME_BASE * decoded_frame->nb_samples) /
 +                     avctx->sample_rate;
 +#endif
  
      rate_emu_sleep(ist);
  
      }
  
      for (i = 0; i < ist->nb_filters; i++)
 -        av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame);
 +        av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, 0);
  
      return ret;
  }
@@@ -2428,8 -2046,6 +2428,8 @@@ static int decode_video(InputStream *is
      AVFrame *decoded_frame;
      void *buffer_to_free = NULL;
      int i, ret = 0, resample_changed;
 +    int64_t best_effort_timestamp;
 +    AVRational *frame_sample_aspect;
      float quality;
  
      if (!ist->decoded_frame && !(ist->decoded_frame = avcodec_alloc_frame()))
      else
          avcodec_get_frame_defaults(ist->decoded_frame);
      decoded_frame = ist->decoded_frame;
 +    pkt->dts  = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);
  
 +    update_benchmark(NULL);
      ret = avcodec_decode_video2(ist->st->codec,
                                  decoded_frame, got_output, pkt);
 +    update_benchmark("decode_video %d.%d", ist->file_index, ist->st->index);
      if (ret < 0)
          return ret;
  
          /* no picture yet */
          if (!pkt->size)
              for (i = 0; i < ist->nb_filters; i++)
 -                av_buffersrc_buffer(ist->filters[i]->filter, NULL);
 +                av_buffersrc_add_ref(ist->filters[i]->filter, NULL, AV_BUFFERSRC_FLAG_NO_COPY);
          return ret;
      }
 -    decoded_frame->pts = guess_correct_pts(&ist->pts_ctx, decoded_frame->pkt_pts,
 -                                           decoded_frame->pkt_dts);
 +
 +    if(ist->top_field_first>=0)
 +        decoded_frame->top_field_first = ist->top_field_first;
 +
 +    best_effort_timestamp= av_frame_get_best_effort_timestamp(decoded_frame);
 +    if(best_effort_timestamp != AV_NOPTS_VALUE)
 +        ist->next_pts = ist->pts = av_rescale_q(decoded_frame->pts = best_effort_timestamp, ist->st->time_base, AV_TIME_BASE_Q);
 +
      pkt->size = 0;
      pre_process_video_frame(ist, (AVPicture *)decoded_frame, &buffer_to_free);
  
              }
      }
  
 +    frame_sample_aspect= av_opt_ptr(avcodec_get_frame_class(), decoded_frame, "sample_aspect_ratio");
      for (i = 0; i < ist->nb_filters; i++) {
 +        int changed =      ist->st->codec->width   != ist->filters[i]->filter->outputs[0]->w
 +                        || ist->st->codec->height  != ist->filters[i]->filter->outputs[0]->h
 +                        || ist->st->codec->pix_fmt != ist->filters[i]->filter->outputs[0]->format;
          // XXX what an ugly hack
          if (ist->filters[i]->graph->nb_outputs == 1)
              ist->filters[i]->graph->outputs[0]->ost->last_quality = quality;
  
 -        if (ist->st->codec->codec->capabilities & CODEC_CAP_DR1) {
 +        if (!frame_sample_aspect->num)
 +            *frame_sample_aspect = ist->st->sample_aspect_ratio;
 +        if (ist->dr1 && decoded_frame->type==FF_BUFFER_TYPE_USER && !changed) {
              FrameBuffer      *buf = decoded_frame->opaque;
              AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
                                          decoded_frame->data, decoded_frame->linesize,
              fb->buf->priv           = buf;
              fb->buf->free           = filter_release_buffer;
  
 +            av_assert0(buf->refcount>0);
              buf->refcount++;
 -            av_buffersrc_buffer(ist->filters[i]->filter, fb);
 +            av_buffersrc_add_ref(ist->filters[i]->filter, fb,
 +                                 AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT |
 +                                 AV_BUFFERSRC_FLAG_NO_COPY);
          } else
 -            av_buffersrc_write_frame(ist->filters[i]->filter, decoded_frame);
 +        if(av_buffersrc_add_frame(ist->filters[i]->filter, decoded_frame, 0)<0) {
 +            av_log(NULL, AV_LOG_FATAL, "Failed to inject frame into filter network\n");
 +            exit_program(1);
 +        }
 +
      }
  
      av_free(buffer_to_free);
@@@ -2560,24 -2154,12 +2560,24 @@@ static int transcode_subtitles(InputStr
  /* pkt = NULL means EOF (needed to flush decoder buffers) */
  static int output_packet(InputStream *ist, const AVPacket *pkt)
  {
 -    int i;
 +    int ret = 0, i;
      int got_output;
 +
      AVPacket avpkt;
 +    if (!ist->saw_first_ts) {
 +        ist->dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
 +        ist->pts = 0;
 +        if (pkt != NULL && pkt->pts != AV_NOPTS_VALUE && !ist->decoding_needed) {
 +            ist->dts += av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q);
 +            ist->pts = ist->dts; //unused but better to set it to a value thats not totally wrong
 +        }
 +        ist->saw_first_ts = 1;
 +    }
  
      if (ist->next_dts == AV_NOPTS_VALUE)
 -        ist->next_dts = ist->last_dts;
 +        ist->next_dts = ist->dts;
 +    if (ist->next_pts == AV_NOPTS_VALUE)
 +        ist->next_pts = ist->pts;
  
      if (pkt == NULL) {
          /* EOF handling */
          avpkt = *pkt;
      }
  
 -    if (pkt->dts != AV_NOPTS_VALUE)
 -        ist->next_dts = ist->last_dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 +    if (pkt->dts != AV_NOPTS_VALUE) {
 +        ist->next_dts = ist->dts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 +        if (ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ist->decoding_needed)
 +            ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
 +    }
  
      // while we have more to decode or while the decoder did output something on EOF
      while (ist->decoding_needed && (avpkt.size > 0 || (!pkt && got_output))) {
 -        int ret = 0;
 +        int duration;
      handle_eof:
  
 -        ist->last_dts = ist->next_dts;
 +        ist->pts = ist->next_pts;
 +        ist->dts = ist->next_dts;
  
          if (avpkt.size && avpkt.size != pkt->size) {
              av_log(NULL, ist->showed_multi_packet_warning ? AV_LOG_VERBOSE : AV_LOG_WARNING,
              break;
          case AVMEDIA_TYPE_VIDEO:
              ret = decode_video    (ist, &avpkt, &got_output);
 -            if (avpkt.duration)
 -                ist->next_dts += av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
 -            else if (ist->st->r_frame_rate.num)
 -                ist->next_dts += av_rescale_q(1, (AVRational){ist->st->r_frame_rate.den,
 -                                                              ist->st->r_frame_rate.num},
 -                                              AV_TIME_BASE_Q);
 -            else if (ist->st->codec->time_base.num != 0) {
 -                int ticks      = ist->st->parser ? ist->st->parser->repeat_pict + 1 :
 -                                                   ist->st->codec->ticks_per_frame;
 -                ist->next_dts += av_rescale_q(ticks, ist->st->codec->time_base, AV_TIME_BASE_Q);
 -            }
 +            if (avpkt.duration) {
 +                duration = av_rescale_q(avpkt.duration, ist->st->time_base, AV_TIME_BASE_Q);
 +            } else if(ist->st->codec->time_base.num != 0 && ist->st->codec->time_base.den != 0) {
 +                int ticks= ist->st->parser ? ist->st->parser->repeat_pict+1 : ist->st->codec->ticks_per_frame;
 +                duration = ((int64_t)AV_TIME_BASE *
 +                                ist->st->codec->time_base.num * ticks) /
 +                                ist->st->codec->time_base.den;
 +            } else
 +                duration = 0;
 +
 +            if(ist->dts != AV_NOPTS_VALUE && duration) {
 +                ist->next_dts += duration;
 +            }else
 +                ist->next_dts = AV_NOPTS_VALUE;
 +
 +            if (got_output)
 +                ist->next_pts += duration; //FIXME the duration is not correct in some cases
              break;
          case AVMEDIA_TYPE_SUBTITLE:
              ret = transcode_subtitles(ist, &avpkt, &got_output);
  
          if (ret < 0)
              return ret;
 +
 +        avpkt.dts=
 +        avpkt.pts= AV_NOPTS_VALUE;
 +
          // touch data and size only if not EOF
          if (pkt) {
 +            if(ist->st->codec->codec_type != AVMEDIA_TYPE_AUDIO)
 +                ret = avpkt.size;
              avpkt.data += ret;
              avpkt.size -= ret;
          }
      /* handle stream copy */
      if (!ist->decoding_needed) {
          rate_emu_sleep(ist);
 -        ist->last_dts = ist->next_dts;
 +        ist->dts = ist->next_dts;
          switch (ist->st->codec->codec_type) {
          case AVMEDIA_TYPE_AUDIO:
              ist->next_dts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
                               ist->st->codec->sample_rate;
              break;
          case AVMEDIA_TYPE_VIDEO:
 -            if (ist->st->codec->time_base.num != 0) {
 -                int ticks = ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->st->codec->ticks_per_frame;
 +            if (pkt->duration) {
 +                ist->next_dts += av_rescale_q(pkt->duration, ist->st->time_base, AV_TIME_BASE_Q);
 +            } else if(ist->st->codec->time_base.num != 0) {
 +                int ticks= ist->st->parser ? ist->st->parser->repeat_pict + 1 : ist->st->codec->ticks_per_frame;
                  ist->next_dts += ((int64_t)AV_TIME_BASE *
                                    ist->st->codec->time_base.num * ticks) /
                                    ist->st->codec->time_base.den;
              }
              break;
          }
 +        ist->pts = ist->dts;
 +        ist->next_pts = ist->next_dts;
      }
      for (i = 0; pkt && i < nb_output_streams; i++) {
          OutputStream *ost = output_streams[i];
@@@ -2712,18 -2274,27 +2712,18 @@@ static void print_sdp(void
  
  static int init_input_stream(int ist_index, char *error, int error_len)
  {
 -    int i;
      InputStream *ist = input_streams[ist_index];
 +
      if (ist->decoding_needed) {
          AVCodec *codec = ist->dec;
          if (!codec) {
 -            snprintf(error, error_len, "Decoder (codec id %d) not found for input stream #%d:%d",
 -                    ist->st->codec->codec_id, ist->file_index, ist->st->index);
 +            snprintf(error, error_len, "Decoder (codec %s) not found for input stream #%d:%d",
 +                    avcodec_get_name(ist->st->codec->codec_id), ist->file_index, ist->st->index);
              return AVERROR(EINVAL);
          }
  
 -        /* update requested sample format for the decoder based on the
 -           corresponding encoder sample format */
 -        for (i = 0; i < nb_output_streams; i++) {
 -            OutputStream *ost = output_streams[i];
 -            if (ost->source_index == ist_index) {
 -                update_sample_fmt(ist->st->codec, codec, ost->st->codec);
 -                break;
 -            }
 -        }
 -
 -        if (codec->type == AVMEDIA_TYPE_VIDEO && codec->capabilities & CODEC_CAP_DR1) {
 +        ist->dr1 = (codec->capabilities & CODEC_CAP_DR1) && !do_deinterlace;
 +        if (codec->type == AVMEDIA_TYPE_VIDEO && ist->dr1) {
              ist->st->codec->get_buffer     = codec_get_buffer;
              ist->st->codec->release_buffer = codec_release_buffer;
              ist->st->codec->opaque         = &ist->buffer_pool;
          assert_avoptions(ist->opts);
      }
  
 -    ist->last_dts = ist->st->avg_frame_rate.num ? - ist->st->codec->has_b_frames * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
 +    ist->next_pts = AV_NOPTS_VALUE;
      ist->next_dts = AV_NOPTS_VALUE;
 -    init_pts_correction(&ist->pts_ctx);
      ist->is_start = 1;
  
      return 0;
@@@ -2751,6 -2323,16 +2751,6 @@@ static InputStream *get_input_stream(Ou
  {
      if (ost->source_index >= 0)
          return input_streams[ost->source_index];
 -
 -    if (ost->filter) {
 -        FilterGraph *fg = ost->filter->graph;
 -        int i;
 -
 -        for (i = 0; i < fg->nb_inputs; i++)
 -            if (fg->inputs[i]->ist->st->codec->codec_type == ost->st->codec->codec_type)
 -                return fg->inputs[i]->ist;
 -    }
 -
      return NULL;
  }
  
@@@ -2758,7 -2340,7 +2758,7 @@@ static int transcode_init(void
  {
      int ret = 0, i, j, k;
      AVFormatContext *oc;
 -    AVCodecContext *codec, *icodec;
 +    AVCodecContext *codec, *icodec = NULL;
      OutputStream *ost;
      InputStream *ist;
      char error[1024];
                  return AVERROR(ENOMEM);
              }
              memcpy(codec->extradata, icodec->extradata, icodec->extradata_size);
 -            codec->extradata_size = icodec->extradata_size;
 -            if (!copy_tb) {
 -                codec->time_base      = icodec->time_base;
 -                codec->time_base.num *= icodec->ticks_per_frame;
 -                av_reduce(&codec->time_base.num, &codec->time_base.den,
 -                          codec->time_base.num, codec->time_base.den, INT_MAX);
 -            } else
 -                codec->time_base = ist->st->time_base;
 +            codec->extradata_size= icodec->extradata_size;
 +            codec->bits_per_coded_sample  = icodec->bits_per_coded_sample;
 +
 +            codec->time_base = ist->st->time_base;
 +            /*
 +             * Avi is a special case here because it supports variable fps but
 +             * having the fps and timebase differe significantly adds quite some
 +             * overhead
 +             */
 +            if(!strcmp(oc->oformat->name, "avi")) {
 +                if (   copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > 2*av_q2d(ist->st->time_base)
 +                                 && av_q2d(ist->st->time_base) < 1.0/500
 +                    || copy_tb==0){
 +                    codec->time_base = icodec->time_base;
 +                    codec->time_base.num *= icodec->ticks_per_frame;
 +                    codec->time_base.den *= 2;
 +                    codec->ticks_per_frame = 2;
 +                }
 +            } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS)
 +                      && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp")
 +                      && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod")
 +            ) {
 +                if(   copy_tb<0 && av_q2d(icodec->time_base)*icodec->ticks_per_frame > av_q2d(ist->st->time_base)
 +                                && av_q2d(ist->st->time_base) < 1.0/500
 +                   || copy_tb==0){
 +                    codec->time_base = icodec->time_base;
 +                    codec->time_base.num *= icodec->ticks_per_frame;
 +                }
 +            }
 +
 +            if(ost->frame_rate.num)
 +                codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
 +
 +            av_reduce(&codec->time_base.num, &codec->time_base.den,
 +                        codec->time_base.num, codec->time_base.den, INT_MAX);
  
              switch (codec->codec_type) {
              case AVMEDIA_TYPE_AUDIO:
                  codec->frame_size         = icodec->frame_size;
                  codec->audio_service_type = icodec->audio_service_type;
                  codec->block_align        = icodec->block_align;
 +                if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3)
 +                    codec->block_align= 0;
 +                if(codec->codec_id == CODEC_ID_AC3)
 +                    codec->block_align= 0;
                  break;
              case AVMEDIA_TYPE_VIDEO:
                  codec->pix_fmt            = icodec->pix_fmt;
                          ist->st->codec->sample_aspect_ratio.num ?
                          ist->st->codec->sample_aspect_ratio : (AVRational){0, 1};
                  }
 +                ost->st->avg_frame_rate = ist->st->avg_frame_rate;
                  break;
              case AVMEDIA_TYPE_SUBTITLE:
                  codec->width  = icodec->width;
                  abort();
              }
          } else {
 +            if (!ost->enc)
 +                ost->enc = avcodec_find_encoder(codec->codec_id);
              if (!ost->enc) {
                  /* should only happen when a default codec is not present. */
 -                snprintf(error, sizeof(error), "Automatic encoder selection "
 -                         "failed for output stream #%d:%d. Default encoder for "
 -                         "format %s is probably disabled. Please choose an "
 -                         "encoder manually.\n", ost->file_index, ost->index,
 -                         oc->oformat->name);
 +                snprintf(error, sizeof(error), "Encoder (codec %s) not found for output stream #%d:%d",
 +                         avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index);
                  ret = AVERROR(EINVAL);
                  goto dump_format;
              }
                  ist->decoding_needed = 1;
              ost->encoding_needed = 1;
  
 -            /*
 -             * We want CFR output if and only if one of those is true:
 -             * 1) user specified output framerate with -r
 -             * 2) user specified -vsync cfr
 -             * 3) output format is CFR and the user didn't force vsync to
 -             *    something else than CFR
 -             *
 -             * in such a case, set ost->frame_rate
 -             */
 -            if (codec->codec_type == AVMEDIA_TYPE_VIDEO &&
 -                !ost->frame_rate.num && ist &&
 -                (video_sync_method ==  VSYNC_CFR ||
 -                 (video_sync_method ==  VSYNC_AUTO &&
 -                  !(oc->oformat->flags & (AVFMT_NOTIMESTAMPS | AVFMT_VARIABLE_FPS))))) {
 -                ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25, 1};
 +            if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 +                if (ost->filter && !ost->frame_rate.num)
 +                    ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter);
 +                if (ist && !ost->frame_rate.num)
 +                    ost->frame_rate = ist->st->r_frame_rate.num ? ist->st->r_frame_rate : (AVRational){25, 1};
                  if (ost->enc && ost->enc->supported_framerates && !ost->force_fps) {
                      int idx = av_find_nearest_q_idx(ost->frame_rate, ost->enc->supported_framerates);
                      ost->frame_rate = ost->enc->supported_framerates[idx];
                  codec->time_base      = (AVRational){ 1, codec->sample_rate };
                  break;
              case AVMEDIA_TYPE_VIDEO:
 -                codec->time_base = ost->filter->filter->inputs[0]->time_base;
 +                codec->time_base = (AVRational){ost->frame_rate.den, ost->frame_rate.num};
 +                if (ost->filter && !(codec->time_base.num && codec->time_base.den))
 +                    codec->time_base = ost->filter->filter->inputs[0]->time_base;
 +                if (   av_q2d(codec->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH
 +                   && (video_sync_method == VSYNC_CFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){
 +                    av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n"
 +                                               "Please consider specifying a lower framerate, a different muxer or -vsync 2\n");
 +                }
 +                for (j = 0; j < ost->forced_kf_count; j++)
 +                    ost->forced_kf_pts[j] = av_rescale_q(ost->forced_kf_pts[j],
 +                                                         AV_TIME_BASE_Q,
 +                                                         codec->time_base);
  
                  codec->width  = ost->filter->filter->inputs[0]->w;
                  codec->height = ost->filter->filter->inputs[0]->h;
                      ost->filter->filter->inputs[0]->sample_aspect_ratio;
                  codec->pix_fmt = ost->filter->filter->inputs[0]->format;
  
 -                if (codec->width   != icodec->width  ||
 +                if (!icodec ||
 +                    codec->width   != icodec->width  ||
                      codec->height  != icodec->height ||
                      codec->pix_fmt != icodec->pix_fmt) {
 -                    codec->bits_per_raw_sample = 0;
 +                    codec->bits_per_raw_sample = frame_bits_per_raw_sample;
                  }
  
                  break;
                  break;
              }
              /* two pass mode */
 -            if ((codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
 +            if (codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2)) {
                  char logfilename[1024];
                  FILE *f;
  
                  if (!strcmp(ost->enc->name, "libx264")) {
                      av_dict_set(&ost->opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE);
                  } else {
 -                    if (codec->flags & CODEC_FLAG_PASS1) {
 -                        f = fopen(logfilename, "wb");
 -                        if (!f) {
 -                            av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n",
 -                                   logfilename, strerror(errno));
 -                            exit_program(1);
 -                        }
 -                        ost->logfile = f;
 -                    } else {
 +                    if (codec->flags & CODEC_FLAG_PASS2) {
                          char  *logbuffer;
                          size_t logbuffer_size;
                          if (cmdutils_read_file(logfilename, &logbuffer, &logbuffer_size) < 0) {
                          }
                          codec->stats_in = logbuffer;
                      }
 +                    if (codec->flags & CODEC_FLAG_PASS1) {
 +                        f = fopen(logfilename, "wb");
 +                        if (!f) {
 +                            av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n",
 +                                logfilename, strerror(errno));
 +                            exit_program(1);
 +                        }
 +                        ost->logfile = f;
 +                    }
                  }
              }
          }
              assert_avoptions(ost->opts);
              if (ost->st->codec->bit_rate && ost->st->codec->bit_rate < 1000)
                  av_log(NULL, AV_LOG_WARNING, "The bitrate parameter is set too low."
 -                                             "It takes bits/s as argument, not kbits/s\n");
 +                                             " It takes bits/s as argument, not kbits/s\n");
              extra_size += ost->st->codec->extradata_size;
  
              if (ost->st->codec->me_threshold)
              ret = AVERROR(EINVAL);
              goto dump_format;
          }
 -        assert_avoptions(output_files[i]->opts);
 +//         assert_avoptions(output_files[i]->opts);
          if (strcmp(oc->oformat->name, "rtp")) {
              want_sdp = 0;
          }
@@@ -3220,7 -2768,7 +3220,7 @@@ static int select_input_file(uint8_t *n
  
      for (i = 0; i < nb_input_streams; i++) {
          InputStream *ist = input_streams[i];
 -        int64_t ipts     = ist->last_dts;
 +        int64_t ipts     = ist->pts;
  
          if (ist->discard || no_packet[ist->file_index])
              continue;
      return file_index;
  }
  
 +static int check_keyboard_interaction(int64_t cur_time)
 +{
 +    int i, ret, key;
 +    static int64_t last_time;
 +    if (received_nb_signals)
 +        return AVERROR_EXIT;
 +    /* read_key() returns 0 on EOF */
 +    if(cur_time - last_time >= 100000 && !run_as_daemon){
 +        key =  read_key();
 +        last_time = cur_time;
 +    }else
 +        key = -1;
 +    if (key == 'q')
 +        return AVERROR_EXIT;
 +    if (key == '+') av_log_set_level(av_log_get_level()+10);
 +    if (key == '-') av_log_set_level(av_log_get_level()-10);
 +    if (key == 's') qp_hist     ^= 1;
 +    if (key == 'h'){
 +        if (do_hex_dump){
 +            do_hex_dump = do_pkt_dump = 0;
 +        } else if(do_pkt_dump){
 +            do_hex_dump = 1;
 +        } else
 +            do_pkt_dump = 1;
 +        av_log_set_level(AV_LOG_DEBUG);
 +    }
 +    if (key == 'c' || key == 'C'){
 +        char buf[4096], target[64], command[256], arg[256] = {0};
 +        double time;
 +        int k, n = 0;
 +        fprintf(stderr, "\nEnter command: <target> <time> <command>[ <argument>]\n");
 +        i = 0;
 +        while ((k = read_key()) != '\n' && k != '\r' && i < sizeof(buf)-1)
 +            if (k > 0)
 +                buf[i++] = k;
 +        buf[i] = 0;
 +        if (k > 0 &&
 +            (n = sscanf(buf, "%63[^ ] %lf %255[^ ] %255[^\n]", target, &time, command, arg)) >= 3) {
 +            av_log(NULL, AV_LOG_DEBUG, "Processing command target:%s time:%f command:%s arg:%s",
 +                   target, time, command, arg);
 +            for (i = 0; i < nb_filtergraphs; i++) {
 +                FilterGraph *fg = filtergraphs[i];
 +                if (fg->graph) {
 +                    if (time < 0) {
 +                        ret = avfilter_graph_send_command(fg->graph, target, command, arg, buf, sizeof(buf),
 +                                                          key == 'c' ? AVFILTER_CMD_FLAG_ONE : 0);
 +                        fprintf(stderr, "Command reply for stream %d: ret:%d res:%s\n", i, ret, buf);
 +                    } else {
 +                        ret = avfilter_graph_queue_command(fg->graph, target, command, arg, 0, time);
 +                    }
 +                }
 +            }
 +        } else {
 +            av_log(NULL, AV_LOG_ERROR,
 +                   "Parse error, at least 3 arguments were expected, "
 +                   "only %d given in string '%s'\n", n, buf);
 +        }
 +    }
 +    if (key == 'd' || key == 'D'){
 +        int debug=0;
 +        if(key == 'D') {
 +            debug = input_streams[0]->st->codec->debug<<1;
 +            if(!debug) debug = 1;
 +            while(debug & (FF_DEBUG_DCT_COEFF|FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) //unsupported, would just crash
 +                debug += debug;
 +        }else
 +            if(scanf("%d", &debug)!=1)
 +                fprintf(stderr,"error parsing debug value\n");
 +        for(i=0;i<nb_input_streams;i++) {
 +            input_streams[i]->st->codec->debug = debug;
 +        }
 +        for(i=0;i<nb_output_streams;i++) {
 +            OutputStream *ost = output_streams[i];
 +            ost->st->codec->debug = debug;
 +        }
 +        if(debug) av_log_set_level(AV_LOG_DEBUG);
 +        fprintf(stderr,"debug=%d\n", debug);
 +    }
 +    if (key == '?'){
 +        fprintf(stderr, "key    function\n"
 +                        "?      show this help\n"
 +                        "+      increase verbosity\n"
 +                        "-      decrease verbosity\n"
 +                        "c      Send command to filtergraph\n"
 +                        "D      cycle through available debug modes\n"
 +                        "h      dump packets/hex press to cycle through the 3 states\n"
 +                        "q      quit\n"
 +                        "s      Show QP histogram\n"
 +        );
 +    }
 +    return 0;
 +}
 +
  #if HAVE_PTHREADS
  static void *input_thread(void *arg)
  {
@@@ -3372,7 -2827,7 +3372,7 @@@ static void free_input_threads(void
          InputFile *f = input_files[i];
          AVPacket pkt;
  
-         if (f->joined)
+         if (!f->fifo || f->joined)
              continue;
  
          pthread_mutex_lock(&f->fifo_lock);
@@@ -3467,9 -2922,8 +3467,9 @@@ static int transcode(void
      if (ret < 0)
          goto fail;
  
 -    av_log(NULL, AV_LOG_INFO, "Press ctrl-c to stop encoding\n");
 -    term_init();
 +    if (!using_stdin) {
 +        av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
 +    }
  
      timer_start = av_gettime();
  
      for (; received_sigterm == 0;) {
          int file_index, ist_index;
          AVPacket pkt;
 +        int64_t cur_time= av_gettime();
 +
 +        /* if 'q' pressed, exits */
 +        if (!using_stdin)
 +            if (check_keyboard_interaction(cur_time) < 0)
 +                break;
  
          /* check if there's any stream where output is still needed */
          if (!need_output()) {
          if (pkt.dts != AV_NOPTS_VALUE)
              pkt.dts *= ist->ts_scale;
  
 -        //fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n",
 -        //        ist->next_dts,
 -        //        pkt.dts, input_files[ist->file_index].ts_offset,
 -        //        ist->st->codec->codec_type);
 -        if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE
 -            && (is->iformat->flags & AVFMT_TS_DISCONT)) {
 +        if (debug_ts) {
 +            av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s "
 +                    "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s  pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%"PRId64"\n",
 +                    ist_index, av_get_media_type_string(ist->st->codec->codec_type),
 +                    av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &ist->st->time_base),
 +                    av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &ist->st->time_base),
 +                    av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base),
 +                    av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base),
 +                    input_files[ist->file_index]->ts_offset);
 +        }
 +
 +        if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) {
              int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
              int64_t delta   = pkt_dts - ist->next_dts;
 -            if ((FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE || pkt_dts + 1 < ist->last_dts) && !copy_ts) {
 +            if (is->iformat->flags & AVFMT_TS_DISCONT) {
 +            if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE ||
 +                (delta > 1LL*dts_delta_threshold*AV_TIME_BASE &&
 +                 ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
 +                pkt_dts+1<ist->pts){
                  input_files[ist->file_index]->ts_offset -= delta;
                  av_log(NULL, AV_LOG_DEBUG,
                         "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
                  if (pkt.pts != AV_NOPTS_VALUE)
                      pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
              }
 +            } else {
 +                if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE ||
 +                    (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
 +                     pkt_dts+1<ist->pts){
 +                    av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index);
 +                    pkt.dts = AV_NOPTS_VALUE;
 +                }
 +                if (pkt.pts != AV_NOPTS_VALUE){
 +                    int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q);
 +                    delta   = pkt_pts - ist->next_dts;
 +                    if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE ||
 +                        (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) ||
 +                        pkt_pts+1<ist->pts) {
 +                        av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index);
 +                        pkt.pts = AV_NOPTS_VALUE;
 +                    }
 +                }
 +            }
          }
  
          // fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
 -        if (output_packet(ist, &pkt) < 0 || poll_filters() < 0) {
 -            av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d\n",
 -                   ist->file_index, ist->st->index);
 +        if ((ret = output_packet(ist, &pkt)) < 0 ||
 +            ((ret = poll_filters()) < 0 && ret != AVERROR_EOF)) {
 +            char buf[128];
 +            av_strerror(ret, buf, sizeof(buf));
 +            av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n",
 +                   ist->file_index, ist->st->index, buf);
              if (exit_on_error)
                  exit_program(1);
              av_free_packet(&pkt);
          av_free_packet(&pkt);
  
          /* dump report by using the output first video and audio streams */
 -        print_report(0, timer_start);
 +        print_report(0, timer_start, cur_time);
      }
  #if HAVE_PTHREADS
      free_input_threads();
      }
  
      /* dump report by using the first video and audio streams */
 -    print_report(1, timer_start);
 +    print_report(1, timer_start, av_gettime());
  
      /* close each encoder */
      for (i = 0; i < nb_output_streams; i++) {
      return ret;
  }
  
 -static double parse_frame_aspect_ratio(const char *arg)
 +static int opt_frame_crop(const char *opt, const char *arg)
  {
 -    int x = 0, y = 0;
 -    double ar = 0;
 -    const char *p;
 -    char *end;
 -
 -    p = strchr(arg, ':');
 -    if (p) {
 -        x = strtol(arg, &end, 10);
 -        if (end == p)
 -            y = strtol(end + 1, &end, 10);
 -        if (x > 0 && y > 0)
 -            ar = (double)x / (double)y;
 -    } else
 -        ar = strtod(arg, NULL);
 +    av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the crop filter instead\n", opt);
 +    return AVERROR(EINVAL);
 +}
  
 -    if (!ar) {
 -        av_log(NULL, AV_LOG_FATAL, "Incorrect aspect ratio specification.\n");
 -        exit_program(1);
 -    }
 -    return ar;
 +static int opt_pad(const char *opt, const char *arg)
 +{
 +    av_log(NULL, AV_LOG_FATAL, "Option '%s' has been removed, use the pad filter instead\n", opt);
 +    return -1;
 +}
 +
 +static int opt_video_channel(const char *opt, const char *arg)
 +{
 +    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n");
 +    return opt_default("channel", arg);
 +}
 +
 +static int opt_video_standard(const char *opt, const char *arg)
 +{
 +    av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n");
 +    return opt_default("standard", arg);
  }
  
  static int opt_audio_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 +    audio_codec_name = arg;
      return parse_option(o, "codec:a", arg, options);
  }
  
  static int opt_video_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 +    video_codec_name = arg;
      return parse_option(o, "codec:v", arg, options);
  }
  
  static int opt_subtitle_codec(OptionsContext *o, const char *opt, const char *arg)
  {
 +    subtitle_codec_name = arg;
      return parse_option(o, "codec:s", arg, options);
  }
  
@@@ -3744,7 -3158,7 +3744,7 @@@ static int opt_map(OptionsContext *o, c
  {
      StreamMap *m = NULL;
      int i, negative = 0, file_idx;
 -    int sync_file_idx = -1, sync_stream_idx;
 +    int sync_file_idx = -1, sync_stream_idx = 0;
      char *p, *sync;
      char *map;
  
@@@ -3844,66 -3258,6 +3844,66 @@@ static int opt_attach(OptionsContext *o
      return 0;
  }
  
 +static int opt_map_channel(OptionsContext *o, const char *opt, const char *arg)
 +{
 +    int n;
 +    AVStream *st;
 +    AudioChannelMap *m;
 +
 +    o->audio_channel_maps =
 +        grow_array(o->audio_channel_maps, sizeof(*o->audio_channel_maps),
 +                   &o->nb_audio_channel_maps, o->nb_audio_channel_maps + 1);
 +    m = &o->audio_channel_maps[o->nb_audio_channel_maps - 1];
 +
 +    /* muted channel syntax */
 +    n = sscanf(arg, "%d:%d.%d", &m->channel_idx, &m->ofile_idx, &m->ostream_idx);
 +    if ((n == 1 || n == 3) && m->channel_idx == -1) {
 +        m->file_idx = m->stream_idx = -1;
 +        if (n == 1)
 +            m->ofile_idx = m->ostream_idx = -1;
 +        return 0;
 +    }
 +
 +    /* normal syntax */
 +    n = sscanf(arg, "%d.%d.%d:%d.%d",
 +               &m->file_idx,  &m->stream_idx, &m->channel_idx,
 +               &m->ofile_idx, &m->ostream_idx);
 +
 +    if (n != 3 && n != 5) {
 +        av_log(NULL, AV_LOG_FATAL, "Syntax error, mapchan usage: "
 +               "[file.stream.channel|-1][:syncfile:syncstream]\n");
 +        exit_program(1);
 +    }
 +
 +    if (n != 5) // only file.stream.channel specified
 +        m->ofile_idx = m->ostream_idx = -1;
 +
 +    /* check input */
 +    if (m->file_idx < 0 || m->file_idx >= nb_input_files) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file index: %d\n",
 +               m->file_idx);
 +        exit_program(1);
 +    }
 +    if (m->stream_idx < 0 ||
 +        m->stream_idx >= input_files[m->file_idx]->nb_streams) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: invalid input file stream index #%d.%d\n",
 +               m->file_idx, m->stream_idx);
 +        exit_program(1);
 +    }
 +    st = input_files[m->file_idx]->ctx->streams[m->stream_idx];
 +    if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: stream #%d.%d is not an audio stream.\n",
 +               m->file_idx, m->stream_idx);
 +        exit_program(1);
 +    }
 +    if (m->channel_idx < 0 || m->channel_idx >= st->codec->channels) {
 +        av_log(NULL, AV_LOG_FATAL, "mapchan: invalid audio channel #%d.%d.%d\n",
 +               m->file_idx, m->stream_idx, m->channel_idx);
 +        exit_program(1);
 +    }
 +    return 0;
 +}
 +
  /**
   * Parse a metadata specifier in arg.
   * @param type metadata type is written here -- g(lobal)/s(tream)/c(hapter)/p(rogram)
@@@ -3940,7 -3294,7 +3940,7 @@@ static void parse_meta_type(char *arg, 
  static int copy_metadata(char *outspec, char *inspec, AVFormatContext *oc, AVFormatContext *ic, OptionsContext *o)
  {
      AVDictionary **meta_in = NULL;
 -    AVDictionary **meta_out;
 +    AVDictionary **meta_out = NULL;
      int i, ret = 0;
      char type_in, type_out;
      const char *istream_spec = NULL, *ostream_spec = NULL;
      parse_meta_type(inspec,  &type_in,  &idx_in,  &istream_spec);
      parse_meta_type(outspec, &type_out, &idx_out, &ostream_spec);
  
 +    if (!ic) {
 +        if (type_out == 'g' || !*outspec)
 +            o->metadata_global_manual = 1;
 +        if (type_out == 's' || !*outspec)
 +            o->metadata_streams_manual = 1;
 +        if (type_out == 'c' || !*outspec)
 +            o->metadata_chapters_manual = 1;
 +        return 0;
 +    }
 +
      if (type_in == 'g' || type_out == 'g')
          o->metadata_global_manual = 1;
      if (type_in == 's' || type_out == 's')
      return 0;
  }
  
 +static int opt_recording_timestamp(OptionsContext *o, const char *opt, const char *arg)
 +{
 +    char buf[128];
 +    int64_t recording_timestamp = parse_time_or_die(opt, arg, 0) / 1E6;
 +    struct tm time = *gmtime((time_t*)&recording_timestamp);
 +    strftime(buf, sizeof(buf), "creation_time=%FT%T%z", &time);
 +    parse_option(o, "metadata", buf, options);
 +
 +    av_log(NULL, AV_LOG_WARNING, "%s is deprecated, set the 'creation_time' metadata "
 +                                 "tag instead.\n", opt);
 +    return 0;
 +}
 +
  static AVCodec *find_codec_or_die(const char *name, enum AVMediaType type, int encoder)
  {
      const char *codec_string = encoder ? "encoder" : "decoder";
@@@ -4072,7 -3403,6 +4072,7 @@@ static AVCodec *choose_decoder(OptionsC
  static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
  {
      int i;
 +    char *next, *codec_tag = NULL;
  
      for (i = 0; i < ic->nb_streams; i++) {
          AVStream *st = ic->streams[i];
          ist->file_index = nb_input_files;
          ist->discard = 1;
          st->discard  = AVDISCARD_ALL;
 -        ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st);
 +        ist->opts = filter_codec_opts(codec_opts, choose_decoder(o, ic, st), ic, st);
  
          ist->ts_scale = 1.0;
          MATCH_PER_STREAM_OPT(ts_scale, dbl, ist->ts_scale, ic, st);
  
 +        MATCH_PER_STREAM_OPT(codec_tags, str, codec_tag, ic, st);
 +        if (codec_tag) {
 +            uint32_t tag = strtol(codec_tag, &next, 0);
 +            if (*next)
 +                tag = AV_RL32(codec_tag);
 +            st->codec->codec_tag = tag;
 +        }
 +
          ist->dec = choose_decoder(o, ic, st);
  
          switch (dec->codec_type) {
          case AVMEDIA_TYPE_VIDEO:
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            if (dec->lowres) {
 +                dec->flags |= CODEC_FLAG_EMU_EDGE;
 +            }
 +
              ist->resample_height  = dec->height;
              ist->resample_width   = dec->width;
              ist->resample_pix_fmt = dec->pix_fmt;
                  exit_program(1);
              }
  
 +            ist->top_field_first = -1;
 +            MATCH_PER_STREAM_OPT(top_field_first, i, ist->top_field_first, ic, st);
 +
              break;
          case AVMEDIA_TYPE_AUDIO:
              guess_input_channel_layout(ist);
              break;
          case AVMEDIA_TYPE_DATA:
          case AVMEDIA_TYPE_SUBTITLE:
 +            if(!ist->dec)
 +                ist->dec = avcodec_find_decoder(dec->codec_id);
 +            break;
          case AVMEDIA_TYPE_ATTACHMENT:
          case AVMEDIA_TYPE_UNKNOWN:
              break;
  
  static void assert_file_overwrite(const char *filename)
  {
 -    if (!file_overwrite &&
 +    if ((!file_overwrite || no_file_overwrite) &&
          (strchr(filename, ':') == NULL || filename[1] == ':' ||
           av_strstart(filename, "file:", NULL))) {
          if (avio_check(filename, 0) == 0) {
 -            if (!using_stdin) {
 +            if (!using_stdin && (!no_file_overwrite || file_overwrite)) {
                  fprintf(stderr,"File '%s' already exists. Overwrite ? [y/N] ", filename);
                  fflush(stderr);
 +                term_exit();
 +                signal(SIGINT, SIG_DFL);
                  if (!read_yesno()) {
 -                    fprintf(stderr, "Not overwriting - exiting\n");
 +                    av_log(NULL, AV_LOG_FATAL, "Not overwriting - exiting\n");
                      exit_program(1);
                  }
 +                term_init();
              }
              else {
 -                fprintf(stderr,"File '%s' already exists. Exiting.\n", filename);
 +                av_log(NULL, AV_LOG_FATAL, "File '%s' already exists. Exiting.\n", filename);
                  exit_program(1);
              }
          }
@@@ -4270,16 -3577,10 +4270,16 @@@ static int opt_input_file(OptionsContex
      if (o->nb_frame_pix_fmts)
          av_dict_set(&format_opts, "pixel_format", o->frame_pix_fmts[o->nb_frame_pix_fmts - 1].u.str, 0);
  
 +    ic->video_codec_id   = video_codec_name ?
 +        find_codec_or_die(video_codec_name   , AVMEDIA_TYPE_VIDEO   , 0)->id : CODEC_ID_NONE;
 +    ic->audio_codec_id   = audio_codec_name ?
 +        find_codec_or_die(audio_codec_name   , AVMEDIA_TYPE_AUDIO   , 0)->id : CODEC_ID_NONE;
 +    ic->subtitle_codec_id= subtitle_codec_name ?
 +        find_codec_or_die(subtitle_codec_name, AVMEDIA_TYPE_SUBTITLE, 0)->id : CODEC_ID_NONE;
      ic->flags |= AVFMT_FLAG_NONBLOCK;
      ic->interrupt_callback = int_cb;
  
 -    /* open the input file with generic libav function */
 +    /* open the input file with generic avformat function */
      err = avformat_open_input(&ic, filename, file_iformat, &format_opts);
      if (err < 0) {
          print_error(filename, err);
          av_dict_free(&opts[i]);
      av_freep(&opts);
  
 -    reset_options(o);
 +    reset_options(o, 1);
      return 0;
  }
  
 -static void parse_forced_key_frames(char *kf, OutputStream *ost,
 -                                    AVCodecContext *avctx)
 +static void parse_forced_key_frames(char *kf, OutputStream *ost)
  {
      char *p;
      int n = 1, i;
 -    int64_t t;
  
      for (p = kf; *p; p++)
          if (*p == ',')
          av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
          exit_program(1);
      }
 +    p = kf;
      for (i = 0; i < n; i++) {
 -        p = i ? strchr(p, ',') + 1 : kf;
 -        t = parse_time_or_die("force_key_frames", p, 1);
 -        ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
 +        char *next = strchr(p, ',');
 +        if (next) *next++ = 0;
 +        ost->forced_kf_pts[i] = parse_time_or_die("force_key_frames", p, 1);
 +        p = next;
      }
  }
  
@@@ -4438,7 -3739,7 +4438,7 @@@ static void choose_encoder(OptionsConte
      }
  }
  
 -static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type)
 +static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, enum AVMediaType type, int source_index)
  {
      OutputStream *ost;
      AVStream *st = avformat_new_stream(oc, NULL);
      st->codec->codec_type = type;
      choose_encoder(o, oc, ost);
      if (ost->enc) {
 -        ost->opts  = filter_codec_opts(codec_opts, ost->enc->id, oc, st);
 +        ost->opts  = filter_codec_opts(codec_opts, ost->enc, oc, st);
      }
  
      avcodec_get_context_defaults3(st->codec, ost->enc);
          st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  
      av_opt_get_int(sws_opts, "sws_flags", 0, &ost->sws_flags);
 +    av_opt_get_int   (swr_opts, "dither_method", 0, &ost->swr_dither_method);
 +    av_opt_get_double(swr_opts, "dither_scale" , 0, &ost->swr_dither_scale);
  
 -    ost->pix_fmts[0] = ost->pix_fmts[1] = PIX_FMT_NONE;
 +    ost->source_index = source_index;
 +    if (source_index >= 0) {
 +        ost->sync_ist = input_streams[source_index];
 +        input_streams[source_index]->discard = 0;
 +        input_streams[source_index]->st->discard = AVDISCARD_NONE;
 +    }
  
      return ost;
  }
@@@ -4568,31 -3862,30 +4568,31 @@@ static void parse_matrix_coeffs(uint16_
      }
  }
  
 -static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc)
 +static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
  {
      AVStream *st;
      OutputStream *ost;
      AVCodecContext *video_enc;
 +    char *frame_rate = NULL;
  
 -    ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO);
 +    ost = new_output_stream(o, oc, AVMEDIA_TYPE_VIDEO, source_index);
      st  = ost->st;
      video_enc = st->codec;
  
 +    MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
 +    if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) {
 +        av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
 +        exit_program(1);
 +    }
 +
      if (!ost->stream_copy) {
          const char *p = NULL;
 -        char *forced_key_frames = NULL, *frame_rate = NULL, *frame_size = NULL;
 +        char *forced_key_frames = NULL, *frame_size = NULL;
          char *frame_aspect_ratio = NULL, *frame_pix_fmt = NULL;
          char *intra_matrix = NULL, *inter_matrix = NULL;
          const char *filters = "null";
          int i;
  
 -        MATCH_PER_STREAM_OPT(frame_rates, str, frame_rate, oc, st);
 -        if (frame_rate && av_parse_video_rate(&ost->frame_rate, frame_rate) < 0) {
 -            av_log(NULL, AV_LOG_FATAL, "Invalid framerate value: %s\n", frame_rate);
 -            exit_program(1);
 -        }
 -
          MATCH_PER_STREAM_OPT(frame_sizes, str, frame_size, oc, st);
          if (frame_size && av_parse_video_size(&video_enc->width, &video_enc->height, frame_size) < 0) {
              av_log(NULL, AV_LOG_FATAL, "Invalid frame size: %s.\n", frame_size);
          }
  
          MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st);
 -        if (frame_aspect_ratio)
 -            ost->frame_aspect_ratio = parse_frame_aspect_ratio(frame_aspect_ratio);
 +        if (frame_aspect_ratio) {
 +            AVRational q;
 +            if (av_parse_ratio(&q, frame_aspect_ratio, 255, 0, NULL) < 0 ||
 +                q.num <= 0 || q.den <= 0) {
 +                av_log(NULL, AV_LOG_FATAL, "Invalid aspect ratio: %s\n", frame_aspect_ratio);
 +                exit_program(1);
 +            }
 +            ost->frame_aspect_ratio = av_q2d(q);
 +        }
  
 +        video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
          MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
 +        if (frame_pix_fmt && *frame_pix_fmt == '+') {
 +            ost->keep_pix_fmt = 1;
 +            if (!*++frame_pix_fmt)
 +                frame_pix_fmt = NULL;
 +        }
          if (frame_pix_fmt && (video_enc->pix_fmt = av_get_pix_fmt(frame_pix_fmt)) == PIX_FMT_NONE) {
              av_log(NULL, AV_LOG_FATAL, "Unknown pixel format requested: %s.\n", frame_pix_fmt);
              exit_program(1);
          }
          st->sample_aspect_ratio = video_enc->sample_aspect_ratio;
  
 +        if (intra_only)
 +            video_enc->gop_size = 0;
          MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st);
          if (intra_matrix) {
              if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) {
                  av_log(NULL, AV_LOG_FATAL, "error parsing rc_override\n");
                  exit_program(1);
              }
 +            /* FIXME realloc failure */
              video_enc->rc_override =
                  av_realloc(video_enc->rc_override,
                             sizeof(RcOverride) * (i + 1));
              video_enc->rc_initial_buffer_occupancy = video_enc->rc_buffer_size * 3 / 4;
          video_enc->intra_dc_precision = intra_dc_precision - 8;
  
 +        if (do_psnr)
 +            video_enc->flags|= CODEC_FLAG_PSNR;
 +
          /* two pass mode */
          if (do_pass) {
 -            if (do_pass == 1) {
 +            if (do_pass & 1) {
                  video_enc->flags |= CODEC_FLAG_PASS1;
 -            } else {
 +            }
 +            if (do_pass & 2) {
                  video_enc->flags |= CODEC_FLAG_PASS2;
              }
          }
  
          MATCH_PER_STREAM_OPT(forced_key_frames, str, forced_key_frames, oc, st);
          if (forced_key_frames)
 -            parse_forced_key_frames(forced_key_frames, ost, video_enc);
 +            parse_forced_key_frames(forced_key_frames, ost);
  
          MATCH_PER_STREAM_OPT(force_fps, i, ost->force_fps, oc, st);
  
      return ost;
  }
  
 -static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc)
 +static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
  {
 +    int n;
      AVStream *st;
      OutputStream *ost;
      AVCodecContext *audio_enc;
  
 -    ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO);
 +    ost = new_output_stream(o, oc, AVMEDIA_TYPE_AUDIO, source_index);
      st  = ost->st;
  
      audio_enc = st->codec;
          MATCH_PER_STREAM_OPT(audio_sample_rate, i, audio_enc->sample_rate, oc, st);
  
          MATCH_PER_STREAM_OPT(filters, str, filters, oc, st);
 +
 +        av_assert1(filters);
          ost->avfilter = av_strdup(filters);
 +
 +        /* check for channel mapping for this audio stream */
 +        for (n = 0; n < o->nb_audio_channel_maps; n++) {
 +            AudioChannelMap *map = &o->audio_channel_maps[n];
 +            InputStream *ist = input_streams[ost->source_index];
 +            if ((map->channel_idx == -1 || (ist->file_index == map->file_idx && ist->st->index == map->stream_idx)) &&
 +                (map->ofile_idx   == -1 || ost->file_index == map->ofile_idx) &&
 +                (map->ostream_idx == -1 || ost->st->index  == map->ostream_idx)) {
 +                if (ost->audio_channels_mapped < FF_ARRAY_ELEMS(ost->audio_channels_map))
 +                    ost->audio_channels_map[ost->audio_channels_mapped++] = map->channel_idx;
 +                else
 +                    av_log(NULL, AV_LOG_FATAL, "Max channel mapping for output %d.%d reached\n",
 +                           ost->file_index, ost->st->index);
 +            }
 +        }
      }
  
      return ost;
  }
  
 -static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc)
 +static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
  {
      OutputStream *ost;
  
 -    ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA);
 +    ost = new_output_stream(o, oc, AVMEDIA_TYPE_DATA, source_index);
      if (!ost->stream_copy) {
          av_log(NULL, AV_LOG_FATAL, "Data stream encoding not supported yet (only streamcopy)\n");
          exit_program(1);
      return ost;
  }
  
 -static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc)
 +static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
  {
 -    OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT);
 +    OutputStream *ost = new_output_stream(o, oc, AVMEDIA_TYPE_ATTACHMENT, source_index);
      ost->stream_copy = 1;
      return ost;
  }
  
 -static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc)
 +static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, int source_index)
  {
      AVStream *st;
      OutputStream *ost;
      AVCodecContext *subtitle_enc;
  
 -    ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE);
 +    ost = new_output_stream(o, oc, AVMEDIA_TYPE_SUBTITLE, source_index);
      st  = ost->st;
      subtitle_enc = st->codec;
  
      subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE;
  
 +    MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc, st);
 +
      return ost;
  }
  
@@@ -4808,7 -4061,7 +4808,7 @@@ static int opt_streamid(OptionsContext 
          exit_program(1);
      }
      *p++ = '\0';
 -    idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, INT_MAX);
 +    idx = parse_number_or_die(opt, idx_str, OPT_INT, 0, MAX_STREAMS-1);
      o->streamid_map = grow_array(o->streamid_map, sizeof(*o->streamid_map), &o->nb_streamid_map, idx+1);
      o->streamid_map[idx] = parse_number_or_die(opt, p, OPT_INT, 0, INT_MAX);
      return 0;
@@@ -4846,7 -4099,7 +4846,7 @@@ static int copy_chapters(InputFile *ifi
              av_dict_copy(&out_ch->metadata, in_ch->metadata, 0);
  
          os->nb_chapters++;
 -        os->chapters = av_realloc(os->chapters, sizeof(AVChapter) * os->nb_chapters);
 +        os->chapters = av_realloc_f(os->chapters, os->nb_chapters, sizeof(AVChapter));
          if (!os->chapters)
              return AVERROR(ENOMEM);
          os->chapters[os->nb_chapters - 1] = out_ch;
      return 0;
  }
  
 +static int read_ffserver_streams(OptionsContext *o, AVFormatContext *s, const char *filename)
 +{
 +    int i, err;
 +    AVFormatContext *ic = avformat_alloc_context();
 +
 +    ic->interrupt_callback = int_cb;
 +    err = avformat_open_input(&ic, filename, NULL, NULL);
 +    if (err < 0)
 +        return err;
 +    /* copy stream format */
 +    for(i=0;i<ic->nb_streams;i++) {
 +        AVStream *st;
 +        OutputStream *ost;
 +        AVCodec *codec;
 +        AVCodecContext *avctx;
 +
 +        codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
 +        ost   = new_output_stream(o, s, codec->type, -1);
 +        st    = ost->st;
 +        avctx = st->codec;
 +        ost->enc = codec;
 +
 +        // FIXME: a more elegant solution is needed
 +        memcpy(st, ic->streams[i], sizeof(AVStream));
 +        st->cur_dts = 0;
 +        st->info = av_malloc(sizeof(*st->info));
 +        memcpy(st->info, ic->streams[i]->info, sizeof(*st->info));
 +        st->codec= avctx;
 +        avcodec_copy_context(st->codec, ic->streams[i]->codec);
 +
 +        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && !ost->stream_copy)
 +            choose_sample_fmt(st, codec);
 +        else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && !ost->stream_copy)
 +            choose_pixel_fmt(st, codec, st->codec->pix_fmt);
 +    }
 +
 +    avformat_close_input(&ic);
 +    return 0;
 +}
 +
  static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
                                 AVFormatContext *oc)
  {
  
      switch (avfilter_pad_get_type(ofilter->out_tmp->filter_ctx->output_pads,
                                    ofilter->out_tmp->pad_idx)) {
 -    case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc); break;
 -    case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc); break;
 +    case AVMEDIA_TYPE_VIDEO: ost = new_video_stream(o, oc, -1); break;
 +    case AVMEDIA_TYPE_AUDIO: ost = new_audio_stream(o, oc, -1); break;
      default:
          av_log(NULL, AV_LOG_FATAL, "Only video and audio filters are supported "
                 "currently.\n");
@@@ -4945,13 -4158,30 +4945,13 @@@ static void opt_output_file(void *optct
      if (!strcmp(filename, "-"))
          filename = "pipe:";
  
 -    oc = avformat_alloc_context();
 +    err = avformat_alloc_output_context2(&oc, NULL, o->format, filename);
      if (!oc) {
 -        print_error(filename, AVERROR(ENOMEM));
 +        print_error(filename, err);
          exit_program(1);
      }
 -
 -    if (o->format) {
 -        file_oformat = av_guess_format(o->format, NULL, NULL);
 -        if (!file_oformat) {
 -            av_log(NULL, AV_LOG_FATAL, "Requested output format '%s' is not a suitable output format\n", o->format);
 -            exit_program(1);
 -        }
 -    } else {
 -        file_oformat = av_guess_format(NULL, filename, NULL);
 -        if (!file_oformat) {
 -            av_log(NULL, AV_LOG_FATAL, "Unable to find a suitable output format for '%s'\n",
 -                   filename);
 -            exit_program(1);
 -        }
 -    }
 -
 -    oc->oformat = file_oformat;
 +    file_oformat= oc->oformat;
      oc->interrupt_callback = int_cb;
 -    av_strlcpy(oc->filename, filename, sizeof(oc->filename));
  
      /* create streams for all unlabeled output pads */
      for (i = 0; i < nb_filtergraphs; i++) {
          }
      }
  
 -    if (!o->nb_stream_maps) {
 -        /* pick the "best" stream of each type */
 -#define NEW_STREAM(type, index)\
 -        if (index >= 0) {\
 -            ost = new_ ## type ## _stream(o, oc);\
 -            ost->source_index = index;\
 -            ost->sync_ist     = input_streams[index];\
 -            input_streams[index]->discard = 0;\
 -            input_streams[index]->st->discard = AVDISCARD_NONE;\
 +    if (!strcmp(file_oformat->name, "ffm") &&
 +        av_strstart(filename, "http:", NULL)) {
 +        int j;
 +        /* special case for files sent to ffserver: we get the stream
 +           parameters from ffserver */
 +        int err = read_ffserver_streams(o, oc, filename);
 +        if (err < 0) {
 +            print_error(filename, err);
 +            exit_program(1);
          }
 +        for(j = nb_output_streams - oc->nb_streams; j < nb_output_streams; j++) {
 +            ost = output_streams[j];
 +            for (i = 0; i < nb_input_streams; i++) {
 +                ist = input_streams[i];
 +                if(ist->st->codec->codec_type == ost->st->codec->codec_type){
 +                    ost->sync_ist= ist;
 +                    ost->source_index= i;
 +                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) ost->avfilter = av_strdup("anull");
 +                    if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) ost->avfilter = av_strdup("null");
 +                    ist->discard = 0;
 +                    ist->st->discard = AVDISCARD_NONE;
 +                    break;
 +                }
 +            }
 +            if(!ost->sync_ist){
 +                av_log(NULL, AV_LOG_FATAL, "Missing %s stream which is required by this ffm\n", av_get_media_type_string(ost->st->codec->codec_type));
 +                exit_program(1);
 +            }
 +        }
 +    } else if (!o->nb_stream_maps) {
 +        /* pick the "best" stream of each type */
  
          /* video: highest resolution */
          if (!o->video_disable && oc->oformat->video_codec != CODEC_ID_NONE) {
                      idx = i;
                  }
              }
 -            NEW_STREAM(video, idx);
 +            if (idx >= 0)
 +                new_video_stream(o, oc, idx);
          }
  
          /* audio: most channels */
                      idx = i;
                  }
              }
 -            NEW_STREAM(audio, idx);
 +            if (idx >= 0)
 +                new_audio_stream(o, oc, idx);
          }
  
          /* subtitles: pick first */
 -        if (!o->subtitle_disable && oc->oformat->subtitle_codec != CODEC_ID_NONE) {
 +        if (!o->subtitle_disable && (oc->oformat->subtitle_codec != CODEC_ID_NONE || subtitle_codec_name)) {
              for (i = 0; i < nb_input_streams; i++)
                  if (input_streams[i]->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
 -                    NEW_STREAM(subtitle, i);
 +                    new_subtitle_stream(o, oc, i);
                      break;
                  }
          }
      } else {
          for (i = 0; i < o->nb_stream_maps; i++) {
              StreamMap *map = &o->stream_maps[i];
 +            int src_idx = input_files[map->file_index]->ist_index + map->stream_index;
  
              if (map->disabled)
                  continue;
@@@ -5075,42 -4281,27 +5075,42 @@@ loop_end
                  init_output_filter(ofilter, o, oc);
              } else {
                  ist = input_streams[input_files[map->file_index]->ist_index + map->stream_index];
 +                if(o->subtitle_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE)
 +                    continue;
 +                if(o->   audio_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
 +                    continue;
 +                if(o->   video_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
 +                    continue;
 +                if(o->    data_disable && ist->st->codec->codec_type == AVMEDIA_TYPE_DATA)
 +                    continue;
 +
                  switch (ist->st->codec->codec_type) {
 -                case AVMEDIA_TYPE_VIDEO:    ost = new_video_stream(o, oc);    break;
 -                case AVMEDIA_TYPE_AUDIO:    ost = new_audio_stream(o, oc);    break;
 -                case AVMEDIA_TYPE_SUBTITLE: ost = new_subtitle_stream(o, oc); break;
 -                case AVMEDIA_TYPE_DATA:     ost = new_data_stream(o, oc);     break;
 -                case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc); break;
 +                case AVMEDIA_TYPE_VIDEO:      ost = new_video_stream     (o, oc, src_idx); break;
 +                case AVMEDIA_TYPE_AUDIO:      ost = new_audio_stream     (o, oc, src_idx); break;
 +                case AVMEDIA_TYPE_SUBTITLE:   ost = new_subtitle_stream  (o, oc, src_idx); break;
 +                case AVMEDIA_TYPE_DATA:       ost = new_data_stream      (o, oc, src_idx); break;
 +                case AVMEDIA_TYPE_ATTACHMENT: ost = new_attachment_stream(o, oc, src_idx); break;
                  default:
                      av_log(NULL, AV_LOG_FATAL, "Cannot map stream #%d:%d - unsupported type.\n",
                             map->file_index, map->stream_index);
                      exit_program(1);
                  }
 -
 -                ost->source_index = input_files[map->file_index]->ist_index + map->stream_index;
 -                ost->sync_ist     = input_streams[input_files[map->sync_file_index]->ist_index +
 -                                               map->sync_stream_index];
 -                ist->discard = 0;
 -                ist->st->discard = AVDISCARD_NONE;
              }
          }
      }
  
 +
 +    for (i = nb_output_streams - oc->nb_streams; i < nb_output_streams; i++) { //for all streams of this output file
 +        AVDictionaryEntry *e;
 +        ost = output_streams[i];
 +
 +        if (   ost->stream_copy
 +            && (e = av_dict_get(codec_opts, "flags", NULL, AV_DICT_IGNORE_SUFFIX))
 +            && (!e->key[5] || check_stream_specifier(oc, ost->st, e->key+6)))
 +            if (av_opt_set(ost->st->codec, "flags", e->value, 0) < 0)
 +                exit_program(1);
 +    }
 +
      /* handle attached files */
      for (i = 0; i < o->nb_attachments; i++) {
          AVIOContext *pb;
          }
          avio_read(pb, attachment, len);
  
 -        ost = new_attachment_stream(o, oc);
 +        ost = new_attachment_stream(o, oc, -1);
          ost->stream_copy               = 0;
 -        ost->source_index              = -1;
          ost->attachment_filename       = o->attachments[i];
          ost->st->codec->extradata      = attachment;
          ost->st->codec->extradata_size = len;
          av_dict_set(&output_files[nb_output_files - 1]->opts, "preload", buf, 0);
      }
      oc->max_delay = (int)(o->mux_max_delay * AV_TIME_BASE);
 -    oc->flags |= AVFMT_FLAG_NONBLOCK;
  
      /* copy metadata */
      for (i = 0; i < o->nb_metadata_map; i++) {
          char *p;
          int in_file_index = strtol(o->metadata_map[i].u.str, &p, 0);
  
 -        if (in_file_index < 0)
 -            continue;
          if (in_file_index >= nb_input_files) {
              av_log(NULL, AV_LOG_FATAL, "Invalid input file index %d while processing metadata maps\n", in_file_index);
              exit_program(1);
          }
 -        copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, input_files[in_file_index]->ctx, o);
 +        copy_metadata(o->metadata_map[i].specifier, *p ? p + 1 : p, oc, in_file_index >= 0 ? input_files[in_file_index]->ctx : NULL, o);
      }
  
      /* copy chapters */
                        !o->metadata_chapters_manual);
  
      /* copy global metadata by default */
 -    if (!o->metadata_global_manual && nb_input_files)
 +    if (!o->metadata_global_manual && nb_input_files){
          av_dict_copy(&oc->metadata, input_files[0]->ctx->metadata,
                       AV_DICT_DONT_OVERWRITE);
 +        if(o->recording_time != INT64_MAX)
 +            av_dict_set(&oc->metadata, "duration", NULL, 0);
 +    }
      if (!o->metadata_streams_manual)
          for (i = output_files[nb_output_files - 1]->ost_index; i < nb_output_streams; i++) {
              InputStream *ist;
          AVDictionary **m;
          char type, *val;
          const char *stream_spec;
 -        int index = 0, j, ret;
 +        int index = 0, j, ret = 0;
  
          val = strchr(o->metadata[i].u.str, '=');
          if (!val) {
          }
      }
  
 -    reset_options(o);
 +    reset_options(o, 0);
  }
  
  /* same option as mencoder */
  static int opt_pass(const char *opt, const char *arg)
  {
 -    do_pass = parse_number_or_die(opt, arg, OPT_INT, 1, 2);
 +    do_pass = parse_number_or_die(opt, arg, OPT_INT, 1, 3);
      return 0;
  }
  
 -static int64_t getutime(void)
 -{
 -#if HAVE_GETRUSAGE
 -    struct rusage rusage;
 -
 -    getrusage(RUSAGE_SELF, &rusage);
 -    return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
 -#elif HAVE_GETPROCESSTIMES
 -    HANDLE proc;
 -    FILETIME c, e, k, u;
 -    proc = GetCurrentProcess();
 -    GetProcessTimes(proc, &c, &e, &k, &u);
 -    return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
 -#else
 -    return av_gettime();
 -#endif
 -}
 -
  static int64_t getmaxrss(void)
  {
  #if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
@@@ -5315,12 -4525,12 +5315,12 @@@ static int opt_audio_qscale(OptionsCont
  
  static void show_usage(void)
  {
 -    printf("Hyper fast Audio and Video encoder\n");
 -    printf("usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
 -    printf("\n");
 +    av_log(NULL, AV_LOG_INFO, "Hyper fast Audio and Video encoder\n");
 +    av_log(NULL, AV_LOG_INFO, "usage: %s [options] [[infile options] -i infile]... {[outfile options] outfile}...\n", program_name);
 +    av_log(NULL, AV_LOG_INFO, "\n");
  }
  
 -static void show_help(void)
 +static int opt_help(const char *opt, const char *arg)
  {
      int flags = AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM;
      av_log_set_callback(log_callback_help);
      show_help_children(avcodec_get_class(), flags);
      show_help_children(avformat_get_class(), flags);
      show_help_children(sws_get_class(), flags);
 +
 +    return 0;
  }
  
  static int opt_target(OptionsContext *o, const char *opt, const char *arg)
          parse_option(o, "r", frame_rates[norm], options);
          opt_default("g", norm == PAL ? "15" : "18");
  
 -        opt_default("b", "1150000");
 +        opt_default("b:v", "1150000");
          opt_default("maxrate", "1150000");
          opt_default("minrate", "1150000");
          opt_default("bufsize", "327680"); // 40*1024*8;
  
          parse_option(o, "s", norm == PAL ? "480x576" : "480x480", options);
          parse_option(o, "r", frame_rates[norm], options);
 +        parse_option(o, "pix_fmt", "yuv420p", options);
          opt_default("g", norm == PAL ? "15" : "18");
  
 -        opt_default("b", "2040000");
 +        opt_default("b:v", "2040000");
          opt_default("maxrate", "2516000");
          opt_default("minrate", "0"); // 1145000;
          opt_default("bufsize", "1835008"); // 224*1024*8;
 -        opt_default("flags", "+scan_offset");
 +        opt_default("scan_offset", "1");
  
  
          opt_default("b:a", "224000");
  
          parse_option(o, "s", norm == PAL ? "720x576" : "720x480", options);
          parse_option(o, "r", frame_rates[norm], options);
 +        parse_option(o, "pix_fmt", "yuv420p", options);
          opt_default("g", norm == PAL ? "15" : "18");
  
 -        opt_default("b", "6000000");
 +        opt_default("b:v", "6000000");
          opt_default("maxrate", "9000000");
          opt_default("minrate", "0"); // 1500000;
          opt_default("bufsize", "1835008"); // 224*1024*8;
@@@ -5527,103 -4733,19 +5527,103 @@@ static int opt_data_frames(OptionsConte
      return parse_option(o, "frames:d", arg, options);
  }
  
 -static int opt_video_tag(OptionsContext *o, const char *opt, const char *arg)
 +static int opt_preset(OptionsContext *o, const char *opt, const char *arg)
 +{
 +    FILE *f=NULL;
 +    char filename[1000], line[1000], tmp_line[1000];
 +    const char *codec_name = *opt == 'v' ? video_codec_name :
 +                             *opt == 'a' ? audio_codec_name :
 +                                           subtitle_codec_name;
 +
 +    if (!(f = get_preset_file(filename, sizeof(filename), arg, *opt == 'f', codec_name))) {
 +        if(!strncmp(arg, "libx264-lossless", strlen("libx264-lossless"))){
 +            av_log(NULL, AV_LOG_FATAL, "Please use -preset <speed> -qp 0\n");
 +        }else
 +            av_log(NULL, AV_LOG_FATAL, "File for preset '%s' not found\n", arg);
 +        exit_program(1);
 +    }
 +
 +    while (fgets(line, sizeof(line), f)) {
 +        char *key = tmp_line, *value, *endptr;
 +
 +        if (strcspn(line, "#\n\r") == 0)
 +            continue;
 +        strcpy(tmp_line, line);
 +        if (!av_strtok(key,   "=",    &value) ||
 +            !av_strtok(value, "\r\n", &endptr)) {
 +            av_log(NULL, AV_LOG_FATAL, "%s: Invalid syntax: '%s'\n", filename, line);
 +            exit_program(1);
 +        }
 +        av_log(NULL, AV_LOG_DEBUG, "ffpreset[%s]: set '%s' = '%s'\n", filename, key, value);
 +
 +        if      (!strcmp(key, "acodec")) opt_audio_codec   (o, key, value);
 +        else if (!strcmp(key, "vcodec")) opt_video_codec   (o, key, value);
 +        else if (!strcmp(key, "scodec")) opt_subtitle_codec(o, key, value);
 +        else if (!strcmp(key, "dcodec")) opt_data_codec    (o, key, value);
 +        else if (opt_default(key, value) < 0) {
 +            av_log(NULL, AV_LOG_FATAL, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n",
 +                   filename, line, key, value);
 +            exit_program(1);
 +        }
 +    }
 +
 +    fclose(f);
 +
 +    return 0;
 +}
 +
 +static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
 +{
 +}
 +
 +static int opt_passlogfile(const char *opt, const char *arg)
 +{
 +    pass_logfilename_prefix = arg;
 +#if CONFIG_LIBX264_ENCODER
 +    return opt_default(opt, arg);
 +#else
 +    return 0;
 +#endif
 +}
 +
 +static int opt_old2new(OptionsContext *o, const char *opt, const char *arg)
 +{
 +    char *s = av_asprintf("%s:%c", opt + 1, *opt);
 +    int ret = parse_option(o, s, arg, options);
 +    av_free(s);
 +    return ret;
 +}
 +
 +static int opt_bitrate(OptionsContext *o, const char *opt, const char *arg)
  {
 -    return parse_option(o, "tag:v", arg, options);
 +    if(!strcmp(opt, "b")){
 +        av_log(NULL, AV_LOG_WARNING, "Please use -b:a or -b:v, -b is ambiguous\n");
 +        return parse_option(o, "b:v", arg, options);
 +    }
 +    return opt_default(opt, arg);
  }
  
 -static int opt_audio_tag(OptionsContext *o, const char *opt, const char *arg)
 +static int opt_qscale(OptionsContext *o, const char *opt, const char *arg)
  {
 -    return parse_option(o, "tag:a", arg, options);
 +    char *s;
 +    int ret;
 +    if(!strcmp(opt, "qscale")){
 +        av_log(NULL, AV_LOG_WARNING, "Please use -q:a or -q:v, -qscale is ambiguous\n");
 +        return parse_option(o, "q:v", arg, options);
 +    }
 +    s = av_asprintf("q%s", opt + 6);
 +    ret = parse_option(o, s, arg, options);
 +    av_free(s);
 +    return ret;
  }
  
 -static int opt_subtitle_tag(OptionsContext *o, const char *opt, const char *arg)
 +static int opt_profile(OptionsContext *o, const char *opt, const char *arg)
  {
 -    return parse_option(o, "tag:s", arg, options);
 +    if(!strcmp(opt, "profile")){
 +        av_log(NULL, AV_LOG_WARNING, "Please use -profile:a or -profile:v, -profile is ambiguous\n");
 +        return parse_option(o, "profile:v", arg, options);
 +    }
 +    return opt_default(opt, arg);
  }
  
  static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg)
@@@ -5641,7 -4763,6 +5641,7 @@@ static int opt_vsync(const char *opt, c
      if      (!av_strcasecmp(arg, "cfr"))         video_sync_method = VSYNC_CFR;
      else if (!av_strcasecmp(arg, "vfr"))         video_sync_method = VSYNC_VFR;
      else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH;
 +    else if (!av_strcasecmp(arg, "drop"))        video_sync_method = VSYNC_DROP;
  
      if (video_sync_method == VSYNC_AUTO)
          video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR);
@@@ -5655,14 -4776,15 +5655,14 @@@ static int opt_deinterlace(const char *
      return 0;
  }
  
 -static int opt_cpuflags(const char *opt, const char *arg)
 +static int opt_timecode(OptionsContext *o, const char *opt, const char *arg)
  {
 -    int flags = av_parse_cpu_flags(arg);
 -
 -    if (flags < 0)
 -        return flags;
 -
 -    av_set_cpu_flags_mask(flags);
 -    return 0;
 +    char *tcr = av_asprintf("timecode=%s", arg);
 +    int ret = parse_option(o, "metadata:g", tcr, options);
 +    if (ret >= 0)
 +        ret = opt_default("gop_timecode", arg);
 +    av_free(tcr);
 +    return ret;
  }
  
  static void parse_cpuflags(int argc, char **argv, const OptionDef *options)
@@@ -5725,12 -4847,10 +5725,12 @@@ static const OptionDef options[] = 
      { "f", HAS_ARG | OPT_STRING | OPT_OFFSET, {.off = OFFSET(format)}, "force format", "fmt" },
      { "i", HAS_ARG | OPT_FUNC2, {(void*)opt_input_file}, "input file name", "filename" },
      { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
 +    { "n", OPT_BOOL, {(void*)&no_file_overwrite}, "do not overwrite output files" },
      { "c", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
      { "codec", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(codec_names)}, "codec name", "codec" },
      { "pre", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(presets)}, "preset name", "preset" },
      { "map", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map}, "set input stream mapping", "[-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]]" },
 +    { "map_channel", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_map_channel}, "map an audio channel from one stream to another", "file.stream.channel[:syncfile.syncstream]" },
      { "map_metadata", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(metadata_map)}, "set metadata information of outfile from infile",
        "outfile[,metadata]:infile[,metadata]" },
      { "map_chapters",  OPT_INT | HAS_ARG | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(chapters_input_file)},  "set chapters mapping", "input_file_index" },
      { "ss", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(start_time)}, "set the start time offset", "time_off" },
      { "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET, {.off = OFFSET(input_ts_offset)}, "set the input ts offset", "time_off" },
      { "itsscale", HAS_ARG | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(ts_scale)}, "set the input ts scale", "scale" },
 +    { "timestamp", HAS_ARG | OPT_FUNC2, {(void*)opt_recording_timestamp}, "set the recording timestamp ('now' to set the current time)", "time" },
      { "metadata", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(metadata)}, "add metadata", "string=string" },
      { "dframes", HAS_ARG | OPT_FUNC2, {(void*)opt_data_frames}, "set the number of data frames to record", "number" },
      { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark},
        "add timings for benchmarking" },
 +    { "benchmark_all", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark_all},
 +      "add timings for each task" },
      { "timelimit", HAS_ARG, {(void*)opt_timelimit}, "set max runtime in seconds", "limit" },
      { "dump", OPT_BOOL | OPT_EXPERT, {(void*)&do_pkt_dump},
        "dump each input packet" },
      { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
      { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" },
      { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" },
 -    { "copytb", OPT_BOOL | OPT_EXPERT, {(void*)&copy_tb}, "copy input stream time base when stream copying" },
 +    { "copytb", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&copy_tb}, "copy input stream time base when stream copying", "mode" },
      { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
      { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" },
 +    { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_error_threshold}, "timestamp error delta threshold", "threshold" },
      { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" },
      { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC, {.off = OFFSET(copy_initial_nonkeyframes)}, "copy initial non-keyframes" },
      { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, {.off = OFFSET(max_frames)}, "set the number of frames to record", "number" },
      { "tag",   OPT_STRING | HAS_ARG | OPT_SPEC, {.off = OFFSET(codec_tags)}, "force codec tag/fourcc", "fourcc/tag" },
      { "q", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" },
 -    { "qscale", HAS_ARG | OPT_EXPERT | OPT_DOUBLE | OPT_SPEC, {.off = OFFSET(qscale)}, "use fixed quality scale (VBR)", "q" },
 +    { "qscale", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_qscale}, "use fixed quality scale (VBR)", "q" },
 +    { "profile", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_profile}, "set profile", "profile" },
      { "filter", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(filters)}, "set stream filterchain", "filter_list" },
      { "filter_complex", HAS_ARG | OPT_EXPERT, {(void*)opt_filter_complex}, "create a complex filtergraph", "graph_description" },
      { "stats", OPT_BOOL, {&print_stats}, "print progress report during encoding", },
      { "attach", HAS_ARG | OPT_FUNC2, {(void*)opt_attach}, "add an attachment to the output file", "filename" },
      { "dump_attachment", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(dump_attachment)}, "extract an attachment into a file", "filename" },
 -    { "cpuflags", HAS_ARG | OPT_EXPERT, {(void*)opt_cpuflags}, "set CPU flags mask", "mask" },
 +    { "debug_ts", OPT_BOOL | OPT_EXPERT, {&debug_ts}, "print timestamp debugging info" },
  
      /* video options */
      { "vframes", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_frames}, "set the number of video frames to record", "number" },
      { "s", HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(frame_sizes)}, "set frame size (WxH or abbreviation)", "size" },
      { "aspect", HAS_ARG | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(frame_aspect_ratios)}, "set aspect ratio (4:3, 16:9 or 1.3333, 1.7777)", "aspect" },
      { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(frame_pix_fmts)}, "set pixel format", "format" },
 +    { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_VIDEO, {(void*)&frame_bits_per_raw_sample}, "set the number of bits per raw sample", "number" },
 +    { "croptop",  HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
 +    { "cropbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
 +    { "cropleft", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
 +    { "cropright", HAS_ARG | OPT_VIDEO, {(void*)opt_frame_crop}, "Removed, use the crop filter instead", "size" },
 +    { "padtop", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
 +    { "padbottom", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
 +    { "padleft", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
 +    { "padright", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "size" },
 +    { "padcolor", HAS_ARG | OPT_VIDEO, {(void*)opt_pad}, "Removed, use the pad filter instead", "color" },
 +    { "intra", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_only}, "deprecated use -g 1"},
      { "vn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, {.off = OFFSET(video_disable)}, "disable video" },
      { "vdt", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&video_discard}, "discard threshold", "n" },
      { "rc_override", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(rc_overrides)}, "rate control override for specific intervals", "override" },
      { "vcodec", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_codec}, "force video codec ('copy' to copy stream)", "codec" },
 +    { "sameq", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant}, "use same quantizer as source (implies VBR)" },
      { "same_quant", OPT_BOOL | OPT_VIDEO, {(void*)&same_quant},
        "use same quantizer as source (implies VBR)" },
 +    { "timecode", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_timecode}, "set initial TimeCode value.", "hh:mm:ss[:;.]ff" },
      { "pass", HAS_ARG | OPT_VIDEO, {(void*)opt_pass}, "select the pass number (1 or 2)", "n" },
 -    { "passlogfile", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void*)&pass_logfilename_prefix}, "select two pass log file name prefix", "prefix" },
 +    { "passlogfile", HAS_ARG | OPT_VIDEO, {(void*)&opt_passlogfile}, "select two pass log file name prefix", "prefix" },
      { "deinterlace", OPT_EXPERT | OPT_VIDEO, {(void*)opt_deinterlace},
        "this option is deprecated, use the yadif filter instead" },
 +    { "psnr", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
      { "vstats", OPT_EXPERT | OPT_VIDEO, {(void*)&opt_vstats}, "dump video coding statistics to file" },
      { "vstats_file", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_vstats_file}, "dump video coding statistics to file", "file" },
      { "vf", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_filters}, "video filters", "filter list" },
      { "inter_matrix", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_STRING | OPT_SPEC, {.off = OFFSET(inter_matrices)}, "specify inter matrix coeffs", "matrix" },
      { "top", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_INT| OPT_SPEC, {.off = OFFSET(top_field_first)}, "top=1/bottom=0/auto=-1 field first", "" },
      { "dc", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&intra_dc_precision}, "intra_dc_precision", "precision" },
 -    { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_FUNC2, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
 +    { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_FUNC2, {(void*)opt_old2new}, "force video tag/fourcc", "fourcc/tag" },
      { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
      { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO | OPT_SPEC, {.off = OFFSET(force_fps)}, "force the selected framerate, disable the best supported framerate selection" },
      { "streamid", HAS_ARG | OPT_EXPERT | OPT_FUNC2, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" },
      { "force_key_frames", OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_SPEC, {.off = OFFSET(forced_key_frames)}, "force key frames at specified timestamps", "timestamps" },
 +    { "b", HAS_ARG | OPT_VIDEO | OPT_FUNC2, {(void*)opt_bitrate}, "video bitrate (please use -b:v)", "bitrate" },
  
      /* audio options */
      { "aframes", HAS_ARG | OPT_AUDIO | OPT_FUNC2, {(void*)opt_audio_frames}, "set the number of audio frames to record", "number" },
      { "ac", HAS_ARG | OPT_AUDIO | OPT_INT | OPT_SPEC, {.off = OFFSET(audio_channels)}, "set number of audio channels", "channels" },
      { "an", OPT_BOOL | OPT_AUDIO | OPT_OFFSET, {.off = OFFSET(audio_disable)}, "disable audio" },
      { "acodec", HAS_ARG | OPT_AUDIO | OPT_FUNC2, {(void*)opt_audio_codec}, "force audio codec ('copy' to copy stream)", "codec" },
 -    { "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_FUNC2, {(void*)opt_audio_tag}, "force audio tag/fourcc", "fourcc/tag" },
 +    { "atag", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_FUNC2, {(void*)opt_old2new}, "force audio tag/fourcc", "fourcc/tag" },
      { "vol", OPT_INT | HAS_ARG | OPT_AUDIO, {(void*)&audio_volume}, "change audio volume (256=normal)" , "volume" }, //
      { "sample_fmt", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_SPEC | OPT_STRING, {.off = OFFSET(sample_fmts)}, "set sample format", "format" },
      { "channel_layout", HAS_ARG | OPT_EXPERT | OPT_AUDIO | OPT_FUNC2, {(void*)opt_channel_layout}, "set channel layout", "layout" },
      /* subtitle options */
      { "sn", OPT_BOOL | OPT_SUBTITLE | OPT_OFFSET, {.off = OFFSET(subtitle_disable)}, "disable subtitle" },
      { "scodec", HAS_ARG | OPT_SUBTITLE | OPT_FUNC2, {(void*)opt_subtitle_codec}, "force subtitle codec ('copy' to copy stream)", "codec" },
 -    { "stag", HAS_ARG | OPT_EXPERT | OPT_SUBTITLE | OPT_FUNC2, {(void*)opt_subtitle_tag}, "force subtitle tag/fourcc", "fourcc/tag" },
 +    { "stag", HAS_ARG | OPT_EXPERT | OPT_SUBTITLE | OPT_FUNC2, {(void*)opt_old2new}, "force subtitle tag/fourcc", "fourcc/tag" },
  
      /* grab options */
 +    { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_channel}, "deprecated, use -channel", "channel" },
 +    { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO | OPT_GRAB, {(void*)opt_video_standard}, "deprecated, use -standard", "standard" },
      { "isync", OPT_BOOL | OPT_EXPERT | OPT_GRAB, {(void*)&input_sync}, "sync read on input", "" },
  
      /* muxer options */
      { "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(mux_preload)},   "set the initial demux-decode delay", "seconds" },
  
      { "bsf", HAS_ARG | OPT_STRING | OPT_SPEC, {.off = OFFSET(bitstream_filters)}, "A comma-separated list of bitstream filters", "bitstream_filters" },
 +    { "absf", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_FUNC2, {(void*)opt_old2new}, "deprecated", "audio bitstream_filters" },
 +    { "vbsf", HAS_ARG | OPT_VIDEO | OPT_EXPERT| OPT_FUNC2, {(void*)opt_old2new}, "deprecated", "video bitstream_filters" },
  
 +    { "apre", HAS_ARG | OPT_AUDIO | OPT_EXPERT| OPT_FUNC2, {(void*)opt_preset}, "set the audio options to the indicated preset", "preset" },
 +    { "vpre", HAS_ARG | OPT_VIDEO | OPT_EXPERT| OPT_FUNC2, {(void*)opt_preset}, "set the video options to the indicated preset", "preset" },
 +    { "spre", HAS_ARG | OPT_SUBTITLE | OPT_EXPERT| OPT_FUNC2, {(void*)opt_preset}, "set the subtitle options to the indicated preset", "preset" },
 +    { "fpre", HAS_ARG | OPT_EXPERT| OPT_FUNC2, {(void*)opt_preset}, "set options from indicated preset file", "filename" },
      /* data codec support */
      { "dcodec", HAS_ARG | OPT_DATA | OPT_FUNC2, {(void*)opt_data_codec}, "force data codec ('copy' to copy stream)", "codec" },
 +    { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, {.off = OFFSET(data_disable)}, "disable data" },
  
      { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
      { NULL, },
@@@ -5867,18 -4958,11 +5867,18 @@@ int main(int argc, char **argv
      OptionsContext o = { 0 };
      int64_t ti;
  
 -    reset_options(&o);
 +    reset_options(&o, 0);
  
      av_log_set_flags(AV_LOG_SKIP_REPEATED);
      parse_loglevel(argc, argv, options);
  
 +    if(argc>1 && !strcmp(argv[1], "-d")){
 +        run_as_daemon=1;
 +        av_log_set_callback(log_callback_null);
 +        argc--;
 +        argv++;
 +    }
 +
      avcodec_register_all();
  #if CONFIG_AVDEVICE
      avdevice_register_all();
      av_register_all();
      avformat_network_init();
  
 -    show_banner();
 +    show_banner(argc, argv, options);
 +
 +    term_init();
  
      parse_cpuflags(argc, argv, options);
  
  
      /* file converter / grab */
      if (nb_output_files <= 0) {
 -        fprintf(stderr, "At least one output file must be specified\n");
 +        av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
          exit_program(1);
      }
  
          exit_program(1);
      }
  
 -    ti = getutime();
 +    current_time = ti = getutime();
      if (transcode() < 0)
          exit_program(1);
      ti = getutime() - ti;
diff --combined ffplay.c
+++ b/ffplay.c
@@@ -1,33 -1,28 +1,33 @@@
  /*
 - * avplay : Simple Media Player based on the Libav libraries
   * Copyright (c) 2003 Fabrice Bellard
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 +/**
 + * @file
 + * simple media player based on the FFmpeg libraries
 + */
 +
  #include "config.h"
  #include <inttypes.h>
  #include <math.h>
  #include <limits.h>
 +#include <signal.h>
  #include "libavutil/avstring.h"
  #include "libavutil/colorspace.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/dict.h"
  #include "libavutil/parseutils.h"
  #include "libavutil/samplefmt.h"
 +#include "libavutil/avassert.h"
  #include "libavformat/avformat.h"
  #include "libavdevice/avdevice.h"
  #include "libswscale/swscale.h"
 -#include "libavresample/avresample.h"
  #include "libavutil/opt.h"
  #include "libavcodec/avfft.h"
 +#include "libswresample/swresample.h"
  
  #if CONFIG_AVFILTER
 +# include "libavfilter/avcodec.h"
  # include "libavfilter/avfilter.h"
  # include "libavfilter/avfiltergraph.h"
  # include "libavfilter/buffersink.h"
  # include "libavfilter/buffersrc.h"
  #endif
  
 -#include "cmdutils.h"
 -
  #include <SDL.h>
  #include <SDL_thread.h>
  
 -#ifdef __MINGW32__
 -#undef main /* We don't want SDL to override our main() */
 -#endif
 +#include "cmdutils.h"
  
  #include <unistd.h>
  #include <assert.h>
  
 -const char program_name[] = "avplay";
 +const char program_name[] = "ffplay";
  const int program_birth_year = 2003;
  
  #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
 -#define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
  #define MIN_FRAMES 5
  
  /* SDL audio buffer size, in samples. Should be small to have precise
@@@ -75,6 -73,8 +75,6 @@@
  /* no AV correction is done if too big error */
  #define AV_NOSYNC_THRESHOLD 10.0
  
 -#define FRAME_SKIP_FACTOR 0.05
 -
  /* maximum audio speed change to get correct sync */
  #define SAMPLE_CORRECTION_PERCENT_MAX 10
  
@@@ -100,13 -100,13 +100,13 @@@ typedef struct PacketQueue 
  
  typedef struct VideoPicture {
      double pts;                                  ///< presentation time stamp for this picture
 -    double target_clock;                         ///< av_gettime() time at which this should be displayed ideally
      int64_t pos;                                 ///< byte position in file
 +    int skip;
      SDL_Overlay *bmp;
      int width, height; /* source height & width */
 +    AVRational sample_aspect_ratio;
      int allocated;
      int reallocate;
 -    enum PixelFormat pix_fmt;
  
  #if CONFIG_AVFILTER
      AVFilterBufferRef *picref;
@@@ -118,13 -118,6 +118,13 @@@ typedef struct SubPicture 
      AVSubtitle sub;
  } SubPicture;
  
 +typedef struct AudioParams {
 +    int freq;
 +    int channels;
 +    int channel_layout;
 +    enum AVSampleFormat fmt;
 +} AudioParams;
 +
  enum {
      AV_SYNC_AUDIO_MASTER, /* default choice */
      AV_SYNC_VIDEO_MASTER,
  };
  
  typedef struct VideoState {
 -    SDL_Thread *parse_tid;
 +    SDL_Thread *read_tid;
      SDL_Thread *video_tid;
      SDL_Thread *refresh_tid;
      AVInputFormat *iformat;
      int no_background;
      int abort_request;
 +    int force_refresh;
      int paused;
      int last_paused;
      int seek_req;
      AVStream *audio_st;
      PacketQueue audioq;
      int audio_hw_buf_size;
 +    DECLARE_ALIGNED(16,uint8_t,audio_buf2)[AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];
      uint8_t silence_buf[SDL_AUDIO_BUFFER_SIZE];
      uint8_t *audio_buf;
      uint8_t *audio_buf1;
      unsigned int audio_buf_size; /* in bytes */
      int audio_buf_index; /* in bytes */
 +    int audio_write_buf_size;
      AVPacket audio_pkt_temp;
      AVPacket audio_pkt;
 -    enum AVSampleFormat sdl_sample_fmt;
 -    uint64_t sdl_channel_layout;
 -    int sdl_channels;
 -    enum AVSampleFormat resample_sample_fmt;
 -    uint64_t resample_channel_layout;
 -    AVAudioResampleContext *avr;
 +    struct AudioParams audio_src;
 +    struct AudioParams audio_tgt;
 +    struct SwrContext *swr_ctx;
 +    double audio_current_pts;
 +    double audio_current_pts_drift;
 +    int frame_drops_early;
 +    int frame_drops_late;
      AVFrame *frame;
  
 -    int show_audio; /* if true, display audio samples */
 +    enum ShowMode {
 +        SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
 +    } show_mode;
      int16_t sample_array[SAMPLE_ARRAY_SIZE];
      int sample_array_index;
      int last_i_start;
  
      double frame_timer;
      double frame_last_pts;
 -    double frame_last_delay;
 +    double frame_last_duration;
 +    double frame_last_dropped_pts;
 +    double frame_last_returned_time;
 +    double frame_last_filter_delay;
 +    int64_t frame_last_dropped_pos;
      double video_clock;                          ///< pts of last decoded frame / predicted pts of next decoded frame
      int video_stream;
      AVStream *video_st;
      struct SwsContext *img_convert_ctx;
  #endif
  
 -    //    QETimer *video_timer;
      char filename[1024];
      int width, height, xleft, ytop;
 -
 -    PtsCorrectionContext pts_ctx;
 +    int step;
  
  #if CONFIG_AVFILTER
      AVFilterContext *in_video_filter;           ///< the first filter in the video chain
      FrameBuffer *buffer_pool;
  #endif
  
 -    float skip_frames;
 -    float skip_frames_index;
      int refresh;
 +    int last_video_stream, last_audio_stream, last_subtitle_stream;
  } VideoState;
  
 -static void show_help(void);
 +typedef struct AllocEventProps {
 +    VideoState *is;
 +    AVFrame *frame;
 +} AllocEventProps;
 +
 +static int opt_help(const char *opt, const char *arg);
  
  /* options specified by the user */
  static AVInputFormat *file_iformat;
@@@ -266,10 -247,12 +266,10 @@@ static int show_status = 1
  static int av_sync_type = AV_SYNC_AUDIO_MASTER;
  static int64_t start_time = AV_NOPTS_VALUE;
  static int64_t duration = AV_NOPTS_VALUE;
 -static int debug = 0;
 -static int debug_mv = 0;
 -static int step = 0;
  static int workaround_bugs = 1;
  static int fast = 0;
  static int genpts = 0;
 +static int lowres = 0;
  static int idct = FF_IDCT_AUTO;
  static enum AVDiscard skip_frame       = AVDISCARD_DEFAULT;
  static enum AVDiscard skip_idct        = AVDISCARD_DEFAULT;
@@@ -280,11 -263,8 +280,11 @@@ static int autoexit
  static int exit_on_keydown;
  static int exit_on_mousedown;
  static int loop = 1;
 -static int framedrop = 1;
 -
 +static int framedrop = -1;
 +static enum ShowMode show_mode = SHOW_MODE_NONE;
 +static const char *audio_codec_name;
 +static const char *subtitle_codec_name;
 +static const char *video_codec_name;
  static int rdftspeed = 20;
  #if CONFIG_AVFILTER
  static char *vfilters = NULL;
  
  /* current context */
  static int is_full_screen;
 -static VideoState *cur_stream;
  static int64_t audio_callback_time;
  
  static AVPacket flush_pkt;
  
  static SDL_Surface *screen;
  
 -void exit_program(int ret)
 +void av_noreturn exit_program(int ret)
  {
      exit(ret);
  }
  
 -static int packet_queue_put(PacketQueue *q, AVPacket *pkt);
 +static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
 +{
 +    AVPacketList *pkt1;
 +
 +    if (q->abort_request)
 +       return -1;
 +
 +    pkt1 = av_malloc(sizeof(AVPacketList));
 +    if (!pkt1)
 +        return -1;
 +    pkt1->pkt = *pkt;
 +    pkt1->next = NULL;
 +
 +    if (!q->last_pkt)
 +        q->first_pkt = pkt1;
 +    else
 +        q->last_pkt->next = pkt1;
 +    q->last_pkt = pkt1;
 +    q->nb_packets++;
 +    q->size += pkt1->pkt.size + sizeof(*pkt1);
 +    /* XXX: should duplicate packet data in DV case */
 +    SDL_CondSignal(q->cond);
 +    return 0;
 +}
 +
 +static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
 +{
 +    int ret;
 +
 +    /* duplicate the packet */
 +    if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
 +        return -1;
 +
 +    SDL_LockMutex(q->mutex);
 +    ret = packet_queue_put_private(q, pkt);
 +    SDL_UnlockMutex(q->mutex);
 +
 +    if (pkt != &flush_pkt && ret < 0)
 +        av_free_packet(pkt);
 +
 +    return ret;
 +}
  
  /* packet queue handling */
  static void packet_queue_init(PacketQueue *q)
      memset(q, 0, sizeof(PacketQueue));
      q->mutex = SDL_CreateMutex();
      q->cond = SDL_CreateCond();
 -    packet_queue_put(q, &flush_pkt);
 +    q->abort_request = 1;
  }
  
  static void packet_queue_flush(PacketQueue *q)
      SDL_UnlockMutex(q->mutex);
  }
  
 -static void packet_queue_end(PacketQueue *q)
 +static void packet_queue_destroy(PacketQueue *q)
  {
      packet_queue_flush(q);
      SDL_DestroyMutex(q->mutex);
      SDL_DestroyCond(q->cond);
  }
  
 -static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
 +static void packet_queue_abort(PacketQueue *q)
  {
 -    AVPacketList *pkt1;
 -
 -    /* duplicate the packet */
 -    if (pkt != &flush_pkt && av_dup_packet(pkt) < 0)
 -        return -1;
 -
 -    pkt1 = av_malloc(sizeof(AVPacketList));
 -    if (!pkt1)
 -        return -1;
 -    pkt1->pkt = *pkt;
 -    pkt1->next = NULL;
 -
 -
      SDL_LockMutex(q->mutex);
  
 -    if (!q->last_pkt)
 +    q->abort_request = 1;
  
 -        q->first_pkt = pkt1;
 -    else
 -        q->last_pkt->next = pkt1;
 -    q->last_pkt = pkt1;
 -    q->nb_packets++;
 -    q->size += pkt1->pkt.size + sizeof(*pkt1);
 -    /* XXX: should duplicate packet data in DV case */
      SDL_CondSignal(q->cond);
  
      SDL_UnlockMutex(q->mutex);
 -    return 0;
  }
  
 -static void packet_queue_abort(PacketQueue *q)
 +static void packet_queue_start(PacketQueue *q)
  {
      SDL_LockMutex(q->mutex);
 -
 -    q->abort_request = 1;
 -
 -    SDL_CondSignal(q->cond);
 -
 +    q->abort_request = 0;
 +    packet_queue_put_private(q, &flush_pkt);
      SDL_UnlockMutex(q->mutex);
  }
  
@@@ -695,20 -659,33 +695,20 @@@ static void video_image_display(VideoSt
  
      vp = &is->pictq[is->pictq_rindex];
      if (vp->bmp) {
 -#if CONFIG_AVFILTER
 -         if (vp->picref->video->pixel_aspect.num == 0)
 -             aspect_ratio = 0;
 -         else
 -             aspect_ratio = av_q2d(vp->picref->video->pixel_aspect);
 -#else
 -
 -        /* XXX: use variable in the frame */
 -        if (is->video_st->sample_aspect_ratio.num)
 -            aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
 -        else if (is->video_st->codec->sample_aspect_ratio.num)
 -            aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
 -        else
 +        if (vp->sample_aspect_ratio.num == 0)
              aspect_ratio = 0;
 -#endif
 +        else
 +            aspect_ratio = av_q2d(vp->sample_aspect_ratio);
 +
          if (aspect_ratio <= 0.0)
              aspect_ratio = 1.0;
          aspect_ratio *= (float)vp->width / (float)vp->height;
  
 -        if (is->subtitle_st)
 -        {
 -            if (is->subpq_size > 0)
 -            {
 +        if (is->subtitle_st) {
 +            if (is->subpq_size > 0) {
                  sp = &is->subpq[is->subpq_rindex];
  
 -                if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000))
 -                {
 +                if (vp->pts >= sp->pts + ((float) sp->sub.start_display_time / 1000)) {
                      SDL_LockYUVOverlay (vp->bmp);
  
                      pict.data[0] = vp->bmp->pixels[0];
          is->no_background = 0;
          rect.x = is->xleft + x;
          rect.y = is->ytop  + y;
 -        rect.w = width;
 -        rect.h = height;
 +        rect.w = FFMAX(width,  1);
 +        rect.h = FFMAX(height, 1);
          SDL_DisplayYUVOverlay(vp->bmp, &rect);
      }
  }
  
 -/* get the current audio output buffer size, in samples. With SDL, we
 -   cannot have a precise information */
 -static int audio_write_get_buf_size(VideoState *is)
 -{
 -    return is->audio_buf_size - is->audio_buf_index;
 -}
 -
  static inline int compute_mod(int a, int b)
  {
 -    a = a % b;
 -    if (a >= 0)
 -        return a;
 -    else
 -        return a + b;
 +    return a < 0 ? a%b + b : a%b;
  }
  
  static void video_audio_display(VideoState *s)
      nb_freq = 1 << (rdft_bits - 1);
  
      /* compute display index : center on currently output samples */
 -    channels = s->sdl_channels;
 +    channels = s->audio_tgt.channels;
      nb_display_channels = channels;
      if (!s->paused) {
 -        int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq);
 +        int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq);
          n = 2 * channels;
 -        delay = audio_write_get_buf_size(s);
 +        delay = s->audio_write_buf_size;
          delay /= n;
  
          /* to be more precise, we take into account the time spent since
             the last buffer computation */
          if (audio_callback_time) {
              time_diff = av_gettime() - audio_callback_time;
 -            delay -= (time_diff * s->audio_st->codec->sample_rate) / 1000000;
 +            delay -= (time_diff * s->audio_tgt.freq) / 1000000;
          }
  
          delay += 2 * data_used;
              delay = data_used;
  
          i_start= x = compute_mod(s->sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE);
 -        if (s->show_audio == 1) {
 +        if (s->show_mode == SHOW_MODE_WAVES) {
              h = INT_MIN;
              for (i = 0; i < 1000; i += channels) {
                  int idx = (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE;
      }
  
      bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
 -    if (s->show_audio == 1) {
 +    if (s->show_mode == SHOW_MODE_WAVES) {
          fill_rectangle(screen,
                         s->xleft, s->ytop, s->width, s->height,
                         bgcolor);
              }
          }
          SDL_UpdateRect(screen, s->xpos, s->ytop, 1, s->height);
 -        s->xpos++;
 +        if (!s->paused)
 +            s->xpos++;
          if (s->xpos >= s->width)
              s->xpos= s->xleft;
      }
  }
  
 -static int video_open(VideoState *is)
 +static void stream_close(VideoState *is)
 +{
 +    VideoPicture *vp;
 +    int i;
 +    /* XXX: use a special url_shutdown call to abort parse cleanly */
 +    is->abort_request = 1;
 +    SDL_WaitThread(is->read_tid, NULL);
 +    SDL_WaitThread(is->refresh_tid, NULL);
 +    packet_queue_destroy(&is->videoq);
 +    packet_queue_destroy(&is->audioq);
 +    packet_queue_destroy(&is->subtitleq);
 +
 +    /* free all pictures */
 +    for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
 +        vp = &is->pictq[i];
 +#if CONFIG_AVFILTER
 +        if (vp->picref) {
 +            avfilter_unref_buffer(vp->picref);
 +            vp->picref = NULL;
 +        }
 +#endif
 +        if (vp->bmp) {
 +            SDL_FreeYUVOverlay(vp->bmp);
 +            vp->bmp = NULL;
 +        }
 +    }
 +    SDL_DestroyMutex(is->pictq_mutex);
 +    SDL_DestroyCond(is->pictq_cond);
 +    SDL_DestroyMutex(is->subpq_mutex);
 +    SDL_DestroyCond(is->subpq_cond);
 +#if !CONFIG_AVFILTER
 +    if (is->img_convert_ctx)
 +        sws_freeContext(is->img_convert_ctx);
 +#endif
 +    av_free(is);
 +}
 +
 +static void do_exit(VideoState *is)
 +{
 +    if (is) {
 +        stream_close(is);
 +    }
 +    av_lockmgr_register(NULL);
 +    uninit_opts();
 +#if CONFIG_AVFILTER
 +    avfilter_uninit();
 +#endif
 +    avformat_network_deinit();
 +    if (show_status)
 +        printf("\n");
 +    SDL_Quit();
 +    av_log(NULL, AV_LOG_QUIET, "%s", "");
 +    exit(0);
 +}
 +
 +static void sigterm_handler(int sig)
 +{
 +    exit(123);
 +}
 +
 +static int video_open(VideoState *is, int force_set_video_mode)
  {
      int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
      int w,h;
 +    VideoPicture *vp = &is->pictq[is->pictq_rindex];
  
      if (is_full_screen) flags |= SDL_FULLSCREEN;
      else                flags |= SDL_RESIZABLE;
      } else if (!is_full_screen && screen_width) {
          w = screen_width;
          h = screen_height;
 -#if CONFIG_AVFILTER
 -    } else if (is->out_video_filter && is->out_video_filter->inputs[0]) {
 -        w = is->out_video_filter->inputs[0]->w;
 -        h = is->out_video_filter->inputs[0]->h;
 -#else
 -    } else if (is->video_st && is->video_st->codec->width) {
 -        w = is->video_st->codec->width;
 -        h = is->video_st->codec->height;
 -#endif
 +    } else if (vp->width) {
 +        w = vp->width;
 +        h = vp->height;
      } else {
          w = 640;
          h = 480;
      }
      if (screen && is->width == screen->w && screen->w == w
 -       && is->height== screen->h && screen->h == h)
 +       && is->height== screen->h && screen->h == h && !force_set_video_mode)
          return 0;
 -
 -#if defined(__APPLE__) && !SDL_VERSION_ATLEAST(1, 2, 14)
 -    /* setting bits_per_pixel = 0 or 32 causes blank video on OS X and older SDL */
 -    screen = SDL_SetVideoMode(w, h, 24, flags);
 -#else
      screen = SDL_SetVideoMode(w, h, 0, flags);
 -#endif
      if (!screen) {
          fprintf(stderr, "SDL: could not set video mode - exiting\n");
 -        return -1;
 +        do_exit(is);
      }
      if (!window_title)
          window_title = input_filename;
  static void video_display(VideoState *is)
  {
      if (!screen)
 -        video_open(cur_stream);
 -    if (is->audio_st && is->show_audio)
 +        video_open(is, 0);
 +    if (is->audio_st && is->show_mode != SHOW_MODE_VIDEO)
          video_audio_display(is);
      else if (is->video_st)
          video_image_display(is);
@@@ -1010,12 -948,11 +1010,12 @@@ static int refresh_thread(void *opaque
          SDL_Event event;
          event.type = FF_REFRESH_EVENT;
          event.user.data1 = opaque;
 -        if (!is->refresh) {
 +        if (!is->refresh && (!is->paused || is->force_refresh)) {
              is->refresh = 1;
              SDL_PushEvent(&event);
          }
 -        usleep(is->audio_st && is->show_audio ? rdftspeed * 1000 : 5000); // FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
 +        //FIXME ideally we should wait the correct time but SDLs event passing is so slow it would be silly
 +        usleep(is->audio_st && is->show_mode != SHOW_MODE_VIDEO ? rdftspeed*1000 : 5000);
      }
      return 0;
  }
  /* get the current audio clock value */
  static double get_audio_clock(VideoState *is)
  {
 -    double pts;
 -    int hw_buf_size, bytes_per_sec;
 -    pts = is->audio_clock;
 -    hw_buf_size = audio_write_get_buf_size(is);
 -    bytes_per_sec = 0;
 -    if (is->audio_st) {
 -        bytes_per_sec = is->audio_st->codec->sample_rate * is->sdl_channels *
 -                        av_get_bytes_per_sample(is->sdl_sample_fmt);
 +    if (is->paused) {
 +        return is->audio_current_pts;
 +    } else {
 +        return is->audio_current_pts_drift + av_gettime() / 1000000.0;
      }
 -    if (bytes_per_sec)
 -        pts -= (double)hw_buf_size / bytes_per_sec;
 -    return pts;
  }
  
  /* get the current video clock value */
@@@ -1083,7 -1027,7 +1083,7 @@@ static void stream_seek(VideoState *is
  }
  
  /* pause or resume the video */
 -static void stream_pause(VideoState *is)
 +static void stream_toggle_pause(VideoState *is)
  {
      if (is->paused) {
          is->frame_timer += av_gettime() / 1000000.0 + is->video_current_pts_drift - is->video_current_pts;
      is->paused = !is->paused;
  }
  
 -static double compute_target_time(double frame_current_pts, VideoState *is)
 +static double compute_target_delay(double delay, VideoState *is)
  {
 -    double delay, sync_threshold, diff;
 -
 -    /* compute nominal delay */
 -    delay = frame_current_pts - is->frame_last_pts;
 -    if (delay <= 0 || delay >= 10.0) {
 -        /* if incorrect delay, use previous one */
 -        delay = is->frame_last_delay;
 -    } else {
 -        is->frame_last_delay = delay;
 -    }
 -    is->frame_last_pts = frame_current_pts;
 +    double sync_threshold, diff;
  
      /* update delay to follow master synchronisation source */
      if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) ||
                  delay = 2 * delay;
          }
      }
 -    is->frame_timer += delay;
  
 -    av_dlog(NULL, "video: delay=%0.3f pts=%0.3f A-V=%f\n",
 -            delay, frame_current_pts, -diff);
 +    av_dlog(NULL, "video: delay=%0.3f A-V=%f\n",
 +            delay, -diff);
  
 -    return is->frame_timer;
 +    return delay;
 +}
 +
 +static void pictq_next_picture(VideoState *is) {
 +    /* update queue size and signal for next picture */
 +    if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
 +        is->pictq_rindex = 0;
 +
 +    SDL_LockMutex(is->pictq_mutex);
 +    is->pictq_size--;
 +    SDL_CondSignal(is->pictq_cond);
 +    SDL_UnlockMutex(is->pictq_mutex);
 +}
 +
 +static void update_video_pts(VideoState *is, double pts, int64_t pos) {
 +    double time = av_gettime() / 1000000.0;
 +    /* update current video pts */
 +    is->video_current_pts = pts;
 +    is->video_current_pts_drift = is->video_current_pts - time;
 +    is->video_current_pos = pos;
 +    is->frame_last_pts = pts;
  }
  
  /* called to display each frame */
 -static void video_refresh_timer(void *opaque)
 +static void video_refresh(void *opaque)
  {
      VideoState *is = opaque;
      VideoPicture *vp;
 +    double time;
  
      SubPicture *sp, *sp2;
  
      if (is->video_st) {
  retry:
          if (is->pictq_size == 0) {
 +            SDL_LockMutex(is->pictq_mutex);
 +            if (is->frame_last_dropped_pts != AV_NOPTS_VALUE && is->frame_last_dropped_pts > is->frame_last_pts) {
 +                update_video_pts(is, is->frame_last_dropped_pts, is->frame_last_dropped_pos);
 +                is->frame_last_dropped_pts = AV_NOPTS_VALUE;
 +            }
 +            SDL_UnlockMutex(is->pictq_mutex);
              // nothing to do, no picture to display in the que
          } else {
 -            double time = av_gettime() / 1000000.0;
 -            double next_target;
 +            double last_duration, duration, delay;
              /* dequeue the picture */
              vp = &is->pictq[is->pictq_rindex];
  
 -            if (time < vp->target_clock)
 +            if (vp->skip) {
 +                pictq_next_picture(is);
 +                goto retry;
 +            }
 +
 +            if (is->paused)
 +                goto display;
 +
 +            /* compute nominal last_duration */
 +            last_duration = vp->pts - is->frame_last_pts;
 +            if (last_duration > 0 && last_duration < 10.0) {
 +                /* if duration of the last frame was sane, update last_duration in video state */
 +                is->frame_last_duration = last_duration;
 +            }
 +            delay = compute_target_delay(is->frame_last_duration, is);
 +
 +            time= av_gettime()/1000000.0;
 +            if (time < is->frame_timer + delay)
                  return;
 -            /* update current video pts */
 -            is->video_current_pts = vp->pts;
 -            is->video_current_pts_drift = is->video_current_pts - time;
 -            is->video_current_pos = vp->pos;
 +
 +            if (delay > 0)
 +                is->frame_timer += delay * FFMAX(1, floor((time-is->frame_timer) / delay));
 +
 +            SDL_LockMutex(is->pictq_mutex);
 +            update_video_pts(is, vp->pts, vp->pos);
 +            SDL_UnlockMutex(is->pictq_mutex);
 +
              if (is->pictq_size > 1) {
                  VideoPicture *nextvp = &is->pictq[(is->pictq_rindex + 1) % VIDEO_PICTURE_QUEUE_SIZE];
 -                assert(nextvp->target_clock >= vp->target_clock);
 -                next_target= nextvp->target_clock;
 -            } else {
 -                next_target = vp->target_clock + is->video_clock - vp->pts; // FIXME pass durations cleanly
 -            }
 -            if (framedrop && time > next_target) {
 -                is->skip_frames *= 1.0 + FRAME_SKIP_FACTOR;
 -                if (is->pictq_size > 1 || time > next_target + 0.5) {
 -                    /* update queue size and signal for next picture */
 -                    if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
 -                        is->pictq_rindex = 0;
 -
 -                    SDL_LockMutex(is->pictq_mutex);
 -                    is->pictq_size--;
 -                    SDL_CondSignal(is->pictq_cond);
 -                    SDL_UnlockMutex(is->pictq_mutex);
 +                duration = nextvp->pts - vp->pts;
 +                if((framedrop>0 || (framedrop && is->audio_st)) && time > is->frame_timer + duration){
 +                    is->frame_drops_late++;
 +                    pictq_next_picture(is);
                      goto retry;
                  }
              }
                  }
              }
  
 +display:
              /* display picture */
              if (!display_disable)
                  video_display(is);
  
 -            /* update queue size and signal for next picture */
 -            if (++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)
 -                is->pictq_rindex = 0;
 -
 -            SDL_LockMutex(is->pictq_mutex);
 -            is->pictq_size--;
 -            SDL_CondSignal(is->pictq_cond);
 -            SDL_UnlockMutex(is->pictq_mutex);
 +            if (!is->paused)
 +                pictq_next_picture(is);
          }
      } else if (is->audio_st) {
          /* draw the next audio frame */
          if (!display_disable)
              video_display(is);
      }
 +    is->force_refresh = 0;
      if (show_status) {
          static int64_t last_time;
          int64_t cur_time;
              av_diff = 0;
              if (is->audio_st && is->video_st)
                  av_diff = get_audio_clock(is) - get_video_clock(is);
 -            printf("%7.2f A-V:%7.3f s:%3.1f aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64"   \r",
 -                   get_master_clock(is), av_diff, FFMAX(is->skip_frames - 1, 0), aqsize / 1024,
 -                   vqsize / 1024, sqsize, is->pts_ctx.num_faulty_dts, is->pts_ctx.num_faulty_pts);
 +            printf("%7.2f A-V:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64"   \r",
 +                   get_master_clock(is),
 +                   av_diff,
 +                   is->frame_drops_early + is->frame_drops_late,
 +                   aqsize / 1024,
 +                   vqsize / 1024,
 +                   sqsize,
 +                   is->video_st ? is->video_st->codec->pts_correction_num_faulty_dts : 0,
 +                   is->video_st ? is->video_st->codec->pts_correction_num_faulty_pts : 0);
              fflush(stdout);
              last_time = cur_time;
          }
      }
  }
  
 -static void stream_close(VideoState *is)
 -{
 -    VideoPicture *vp;
 -    int i;
 -    /* XXX: use a special url_shutdown call to abort parse cleanly */
 -    is->abort_request = 1;
 -    SDL_WaitThread(is->parse_tid, NULL);
 -    SDL_WaitThread(is->refresh_tid, NULL);
 -
 -    /* free all pictures */
 -    for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
 -        vp = &is->pictq[i];
 -#if CONFIG_AVFILTER
 -        if (vp->picref) {
 -            avfilter_unref_buffer(vp->picref);
 -            vp->picref = NULL;
 -        }
 -#endif
 -        if (vp->bmp) {
 -            SDL_FreeYUVOverlay(vp->bmp);
 -            vp->bmp = NULL;
 -        }
 -    }
 -    SDL_DestroyMutex(is->pictq_mutex);
 -    SDL_DestroyCond(is->pictq_cond);
 -    SDL_DestroyMutex(is->subpq_mutex);
 -    SDL_DestroyCond(is->subpq_cond);
 -#if !CONFIG_AVFILTER
 -    if (is->img_convert_ctx)
 -        sws_freeContext(is->img_convert_ctx);
 -#endif
 -    av_free(is);
 -}
 -
 -static void do_exit(void)
 -{
 -    if (cur_stream) {
 -        stream_close(cur_stream);
 -        cur_stream = NULL;
 -    }
 -    uninit_opts();
 -#if CONFIG_AVFILTER
 -    avfilter_uninit();
 -#endif
 -    avformat_network_deinit();
 -    if (show_status)
 -        printf("\n");
 -    SDL_Quit();
 -    av_log(NULL, AV_LOG_QUIET, "");
 -    exit(0);
 -}
 -
  /* allocate a picture (needs to do that in main thread to avoid
     potential locking problems */
 -static void alloc_picture(void *opaque)
 +static void alloc_picture(AllocEventProps *event_props)
  {
 -    VideoState *is = opaque;
 +    VideoState *is = event_props->is;
 +    AVFrame *frame = event_props->frame;
      VideoPicture *vp;
  
      vp = &is->pictq[is->pictq_windex];
      if (vp->picref)
          avfilter_unref_buffer(vp->picref);
      vp->picref = NULL;
 -
 -    vp->width   = is->out_video_filter->inputs[0]->w;
 -    vp->height  = is->out_video_filter->inputs[0]->h;
 -    vp->pix_fmt = is->out_video_filter->inputs[0]->format;
 -#else
 -    vp->width   = is->video_st->codec->width;
 -    vp->height  = is->video_st->codec->height;
 -    vp->pix_fmt = is->video_st->codec->pix_fmt;
  #endif
  
 +    vp->width   = frame->width;
 +    vp->height  = frame->height;
 +
 +    video_open(event_props->is, 0);
 +
      vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
                                     SDL_YV12_OVERLAY,
                                     screen);
          /* SDL allocates a buffer smaller than requested if the video
           * overlay hardware is unable to support the requested size. */
          fprintf(stderr, "Error: the video system does not support an image\n"
 -                        "size of %dx%d pixels. Try using -vf \"scale=w:h\"\n"
 +                        "size of %dx%d pixels. Try using -lowres or -vf \"scale=w:h\"\n"
                          "to reduce the image size.\n", vp->width, vp->height );
 -        do_exit();
 +        do_exit(is);
      }
  
      SDL_LockMutex(is->pictq_mutex);
      SDL_UnlockMutex(is->pictq_mutex);
  }
  
 -/**
 - *
 - * @param pts the dts of the pkt / pts of the frame and guessed if not known
 - */
 -static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, int64_t pos)
 +static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
  {
      VideoPicture *vp;
 -#if CONFIG_AVFILTER
 -    AVPicture pict_src;
 -#else
 -    int dst_pix_fmt = PIX_FMT_YUV420P;
 +    double frame_delay, pts = pts1;
 +
 +    /* compute the exact PTS for the picture if it is omitted in the stream
 +     * pts1 is the dts of the pkt / pts of the frame */
 +    if (pts != 0) {
 +        /* update video clock with pts, if present */
 +        is->video_clock = pts;
 +    } else {
 +        pts = is->video_clock;
 +    }
 +    /* update video clock for next frame */
 +    frame_delay = av_q2d(is->video_st->codec->time_base);
 +    /* for MPEG2, the frame can be repeated, so we update the
 +       clock accordingly */
 +    frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
 +    is->video_clock += frame_delay;
 +
 +#if defined(DEBUG_SYNC) && 0
 +    printf("frame_type=%c clock=%0.3f pts=%0.3f\n",
 +           av_get_picture_type_char(src_frame->pict_type), pts, pts1);
  #endif
 +
      /* wait until we have space to put a new picture */
      SDL_LockMutex(is->pictq_mutex);
  
 -    if (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !is->refresh)
 -        is->skip_frames = FFMAX(1.0 - FRAME_SKIP_FACTOR, is->skip_frames * (1.0 - FRAME_SKIP_FACTOR));
 -
      while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
             !is->videoq.abort_request) {
          SDL_CondWait(is->pictq_cond, is->pictq_mutex);
  
      /* alloc or resize hardware picture buffer */
      if (!vp->bmp || vp->reallocate ||
 -#if CONFIG_AVFILTER
 -        vp->width  != is->out_video_filter->inputs[0]->w ||
 -        vp->height != is->out_video_filter->inputs[0]->h) {
 -#else
 -        vp->width != is->video_st->codec->width ||
 -        vp->height != is->video_st->codec->height) {
 -#endif
 +        vp->width  != src_frame->width ||
 +        vp->height != src_frame->height) {
          SDL_Event event;
 +        AllocEventProps event_props;
 +
 +        event_props.frame = src_frame;
 +        event_props.is = is;
  
          vp->allocated  = 0;
          vp->reallocate = 0;
  
          /* the allocation must be done in the main thread to avoid
 -           locking problems */
 +           locking problems. We wait in this block for the event to complete,
 +           so we can pass a pointer to event_props to it. */
          event.type = FF_ALLOC_EVENT;
 -        event.user.data1 = is;
 +        event.user.data1 = &event_props;
          SDL_PushEvent(&event);
  
          /* wait until the picture is allocated */
          while (!vp->allocated && !is->videoq.abort_request) {
              SDL_CondWait(is->pictq_cond, is->pictq_mutex);
          }
 +        /* if the queue is aborted, we have to pop the pending ALLOC event or wait for the allocation to complete */
 +        if (is->videoq.abort_request && SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_EVENTMASK(FF_ALLOC_EVENT)) != 1) {
 +            while (!vp->allocated) {
 +                SDL_CondWait(is->pictq_cond, is->pictq_mutex);
 +            }
 +        }
          SDL_UnlockMutex(is->pictq_mutex);
  
          if (is->videoq.abort_request)
          pict.linesize[2] = vp->bmp->pitches[1];
  
  #if CONFIG_AVFILTER
 -        pict_src.data[0] = src_frame->data[0];
 -        pict_src.data[1] = src_frame->data[1];
 -        pict_src.data[2] = src_frame->data[2];
 -
 -        pict_src.linesize[0] = src_frame->linesize[0];
 -        pict_src.linesize[1] = src_frame->linesize[1];
 -        pict_src.linesize[2] = src_frame->linesize[2];
 -
          // FIXME use direct rendering
 -        av_picture_copy(&pict, &pict_src,
 -                        vp->pix_fmt, vp->width, vp->height);
 +        av_picture_copy(&pict, (AVPicture *)src_frame,
 +                        src_frame->format, vp->width, vp->height);
 +        vp->sample_aspect_ratio = vp->picref->video->sample_aspect_ratio;
  #else
          sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
          is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
 -            vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,
 -            dst_pix_fmt, sws_flags, NULL, NULL, NULL);
 +            vp->width, vp->height, src_frame->format, vp->width, vp->height,
 +            PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
          if (is->img_convert_ctx == NULL) {
              fprintf(stderr, "Cannot initialize the conversion context\n");
              exit(1);
          }
          sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
                    0, vp->height, pict.data, pict.linesize);
 +        vp->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, src_frame);
  #endif
          /* update the bitmap content */
          SDL_UnlockYUVOverlay(vp->bmp);
  
          vp->pts = pts;
          vp->pos = pos;
 +        vp->skip = 0;
  
          /* now we can update the picture count */
          if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)
              is->pictq_windex = 0;
          SDL_LockMutex(is->pictq_mutex);
 -        vp->target_clock = compute_target_time(vp->pts, is);
 -
          is->pictq_size++;
          SDL_UnlockMutex(is->pictq_mutex);
      }
      return 0;
  }
  
 -/**
 - * compute the exact PTS for the picture if it is omitted in the stream
 - * @param pts1 the dts of the pkt / pts of the frame
 - */
 -static int output_picture2(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos)
 -{
 -    double frame_delay, pts;
 -
 -    pts = pts1;
 -
 -    if (pts != 0) {
 -        /* update video clock with pts, if present */
 -        is->video_clock = pts;
 -    } else {
 -        pts = is->video_clock;
 -    }
 -    /* update video clock for next frame */
 -    frame_delay = av_q2d(is->video_st->codec->time_base);
 -    /* for MPEG2, the frame can be repeated, so we update the
 -       clock accordingly */
 -    frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);
 -    is->video_clock += frame_delay;
 -
 -    return queue_picture(is, src_frame, pts, pos);
 -}
 -
  static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt)
  {
      int got_picture, i;
          SDL_LockMutex(is->pictq_mutex);
          // Make sure there are no long delay timers (ideally we should just flush the que but thats harder)
          for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
 -            is->pictq[i].target_clock= 0;
 +            is->pictq[i].skip = 1;
          }
          while (is->pictq_size && !is->videoq.abort_request) {
              SDL_CondWait(is->pictq_cond, is->pictq_mutex);
          }
          is->video_current_pos = -1;
 -        SDL_UnlockMutex(is->pictq_mutex);
 -
 -        init_pts_correction(&is->pts_ctx);
          is->frame_last_pts = AV_NOPTS_VALUE;
 -        is->frame_last_delay = 0;
 +        is->frame_last_duration = 0;
          is->frame_timer = (double)av_gettime() / 1000000.0;
 -        is->skip_frames = 1;
 -        is->skip_frames_index = 0;
 +        is->frame_last_dropped_pts = AV_NOPTS_VALUE;
 +        SDL_UnlockMutex(is->pictq_mutex);
 +
          return 0;
      }
  
 -    avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt);
 +    if(avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt) < 0)
 +        return 0;
  
      if (got_picture) {
 +        int ret = 1;
 +
          if (decoder_reorder_pts == -1) {
 -            *pts = guess_correct_pts(&is->pts_ctx, frame->pkt_pts, frame->pkt_dts);
 +            *pts = av_frame_get_best_effort_timestamp(frame);
          } else if (decoder_reorder_pts) {
              *pts = frame->pkt_pts;
          } else {
              *pts = 0;
          }
  
 -        is->skip_frames_index += 1;
 -        if (is->skip_frames_index >= is->skip_frames) {
 -            is->skip_frames_index -= FFMAX(is->skip_frames, 1.0);
 -            return 1;
 +        if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) || is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK) &&
 +             (framedrop>0 || (framedrop && is->audio_st))) {
 +            SDL_LockMutex(is->pictq_mutex);
 +            if (is->frame_last_pts != AV_NOPTS_VALUE && *pts) {
 +                double clockdiff = get_video_clock(is) - get_master_clock(is);
 +                double dpts = av_q2d(is->video_st->time_base) * *pts;
 +                double ptsdiff = dpts - is->frame_last_pts;
 +                if (fabs(clockdiff) < AV_NOSYNC_THRESHOLD &&
 +                     ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD &&
 +                     clockdiff + ptsdiff - is->frame_last_filter_delay < 0) {
 +                    is->frame_last_dropped_pos = pkt->pos;
 +                    is->frame_last_dropped_pts = dpts;
 +                    is->frame_drops_early++;
 +                    ret = 0;
 +                }
 +            }
 +            SDL_UnlockMutex(is->pictq_mutex);
          }
  
 +        return ret;
      }
      return 0;
  }
  #if CONFIG_AVFILTER
  static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const char *vfilters)
  {
 +    static const enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
      char sws_flags_str[128];
      char buffersrc_args[256];
      int ret;
 +    AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
      AVFilterContext *filt_src = NULL, *filt_out = NULL, *filt_format;
      AVCodecContext *codec = is->video_st->codec;
  
                                              "src", buffersrc_args, NULL,
                                              graph)) < 0)
          return ret;
 -    if ((ret = avfilter_graph_create_filter(&filt_out,
 -                                            avfilter_get_by_name("buffersink"),
 -                                            "out", NULL, NULL, graph)) < 0)
 +
 +#if FF_API_OLD_VSINK_API
 +    ret = avfilter_graph_create_filter(&filt_out,
 +                                       avfilter_get_by_name("buffersink"),
 +                                       "out", NULL, pix_fmts, graph);
 +#else
 +    buffersink_params->pixel_fmts = pix_fmts;
 +    ret = avfilter_graph_create_filter(&filt_out,
 +                                       avfilter_get_by_name("buffersink"),
 +                                       "out", NULL, buffersink_params, graph);
 +#endif
 +    av_freep(&buffersink_params);
 +    if (ret < 0)
          return ret;
  
      if ((ret = avfilter_graph_create_filter(&filt_format,
          inputs->pad_idx = 0;
          inputs->next    = NULL;
  
 -        if ((ret = avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL)) < 0)
 +        if ((ret = avfilter_graph_parse(graph, vfilters, &inputs, &outputs, NULL)) < 0)
              return ret;
      } else {
          if ((ret = avfilter_link(filt_src, 0, filt_format, 0)) < 0)
@@@ -1637,24 -1599,19 +1637,24 @@@ static int video_thread(void *arg
  {
      VideoState *is = arg;
      AVFrame *frame = avcodec_alloc_frame();
 -    int64_t pts_int;
 +    int64_t pts_int = AV_NOPTS_VALUE, pos = -1;
      double pts;
      int ret;
  
  #if CONFIG_AVFILTER
      AVFilterGraph *graph = avfilter_graph_alloc();
      AVFilterContext *filt_out = NULL, *filt_in = NULL;
 -    int64_t pos;
      int last_w = is->video_st->codec->width;
      int last_h = is->video_st->codec->height;
 +    enum PixelFormat last_format = is->video_st->codec->pix_fmt;
  
 -    if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
 +    if ((ret = configure_video_filters(graph, is, vfilters)) < 0) {
 +        SDL_Event event;
 +        event.type = FF_QUIT_EVENT;
 +        event.user.data1 = is;
 +        SDL_PushEvent(&event);
          goto the_end;
 +    }
      filt_in  = is->in_video_filter;
      filt_out = is->out_video_filter;
  #endif
          AVPacket pkt;
  #if CONFIG_AVFILTER
          AVFilterBufferRef *picref;
 -        AVRational tb;
 +        AVRational tb = filt_out->inputs[0]->time_base;
  #endif
          while (is->paused && !is->videoq.abort_request)
              SDL_Delay(10);
  
 +        avcodec_get_frame_defaults(frame);
          ret = get_video_frame(is, frame, &pts_int, &pkt);
          if (ret < 0)
              goto the_end;
 -        av_free_packet(&pkt);
  
 -        if (!ret)
 +        if (!ret) {
 +            av_free_packet(&pkt);
              continue;
 +        }
  
  #if CONFIG_AVFILTER
          if (   last_w != is->video_st->codec->width
 -            || last_h != is->video_st->codec->height) {
 -            av_dlog(NULL, "Changing size %dx%d -> %dx%d\n", last_w, last_h,
 -                    is->video_st->codec->width, is->video_st->codec->height);
 +            || last_h != is->video_st->codec->height
 +            || last_format != is->video_st->codec->pix_fmt) {
 +            av_log(NULL, AV_LOG_INFO, "Frame changed from size:%dx%d to size:%dx%d\n",
 +                   last_w, last_h, is->video_st->codec->width, is->video_st->codec->height);
              avfilter_graph_free(&graph);
              graph = avfilter_graph_alloc();
 -            if ((ret = configure_video_filters(graph, is, vfilters)) < 0)
 +            if ((ret = configure_video_filters(graph, is, vfilters)) < 0) {
 +                av_free_packet(&pkt);
                  goto the_end;
 +            }
 +            filt_in  = is->in_video_filter;
              filt_out = is->out_video_filter;
              last_w = is->video_st->codec->width;
              last_h = is->video_st->codec->height;
 +            last_format = is->video_st->codec->pix_fmt;
          }
  
          frame->pts = pts_int;
 +        frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
          if (is->use_dr1) {
              FrameBuffer      *buf = frame->opaque;
              AVFilterBufferRef *fb = avfilter_get_video_buffer_ref_from_arrays(
          } else
              av_buffersrc_write_frame(filt_in, frame);
  
 +        av_free_packet(&pkt);
 +
          while (ret >= 0) {
 -            ret = av_buffersink_read(filt_out, &picref);
 +            is->frame_last_returned_time = av_gettime() / 1000000.0;
 +
 +            ret = av_buffersink_get_buffer_ref(filt_out, &picref, 0);
              if (ret < 0) {
                  ret = 0;
                  break;
              }
  
 -            avfilter_copy_buf_props(frame, picref);
 +            is->frame_last_filter_delay = av_gettime() / 1000000.0 - is->frame_last_returned_time;
 +            if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
 +                is->frame_last_filter_delay = 0;
 +
 +            avfilter_fill_frame_from_video_buffer_ref(frame, picref);
  
              pts_int = picref->pts;
              tb      = filt_out->inputs[0]->time_base;
                          is->video_st->time_base.num, is->video_st->time_base.den, pts_int);
              }
              pts = pts_int * av_q2d(is->video_st->time_base);
 -            ret = output_picture2(is, frame, pts, pos);
 +            ret = queue_picture(is, frame, pts, pos);
          }
  #else
          pts = pts_int * av_q2d(is->video_st->time_base);
 -        ret = output_picture2(is, frame, pts,  pkt.pos);
 +        ret = queue_picture(is, frame, pts, pkt.pos);
  #endif
  
          if (ret < 0)
              goto the_end;
  
 -        if (step)
 -            if (cur_stream)
 -                stream_pause(cur_stream);
 +        if (is->step)
 +            stream_toggle_pause(is);
      }
   the_end:
 +    avcodec_flush_buffers(is->video_st->codec);
  #if CONFIG_AVFILTER
      av_freep(&vfilters);
      avfilter_graph_free(&graph);
@@@ -1859,19 -1800,25 +1859,19 @@@ static void update_sample_display(Video
      }
  }
  
 -/* return the new audio buffer size (samples can be added or deleted
 -   to get better sync if video or external master clock) */
 -static int synchronize_audio(VideoState *is, short *samples,
 -                             int samples_size1, double pts)
 +/* return the wanted number of samples to get better sync if sync_type is video
 + * or external master clock */
 +static int synchronize_audio(VideoState *is, int nb_samples)
  {
 -    int n, samples_size;
 -    double ref_clock;
 -
 -    n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
 -    samples_size = samples_size1;
 +    int wanted_nb_samples = nb_samples;
  
      /* if not master, then we try to remove or add samples to correct the clock */
      if (((is->av_sync_type == AV_SYNC_VIDEO_MASTER && is->video_st) ||
           is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) {
          double diff, avg_diff;
 -        int wanted_size, min_size, max_size, nb_samples;
 +        int min_nb_samples, max_nb_samples;
  
 -        ref_clock = get_master_clock(is);
 -        diff = get_audio_clock(is) - ref_clock;
 +        diff = get_audio_clock(is) - get_master_clock(is);
  
          if (diff < AV_NOSYNC_THRESHOLD) {
              is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
                  avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);
  
                  if (fabs(avg_diff) >= is->audio_diff_threshold) {
 -                    wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);
 -                    nb_samples = samples_size / n;
 -
 -                    min_size = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
 -                    max_size = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX)) / 100) * n;
 -                    if (wanted_size < min_size)
 -                        wanted_size = min_size;
 -                    else if (wanted_size > max_size)
 -                        wanted_size = max_size;
 -
 -                    /* add or remove samples to correction the synchro */
 -                    if (wanted_size < samples_size) {
 -                        /* remove samples */
 -                        samples_size = wanted_size;
 -                    } else if (wanted_size > samples_size) {
 -                        uint8_t *samples_end, *q;
 -                        int nb;
 -
 -                        /* add samples */
 -                        nb = (samples_size - wanted_size);
 -                        samples_end = (uint8_t *)samples + samples_size - n;
 -                        q = samples_end + n;
 -                        while (nb > 0) {
 -                            memcpy(q, samples_end, n);
 -                            q += n;
 -                            nb -= n;
 -                        }
 -                        samples_size = wanted_size;
 -                    }
 +                    wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq);
 +                    min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100));
 +                    max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100));
 +                    wanted_nb_samples = FFMIN(FFMAX(wanted_nb_samples, min_nb_samples), max_nb_samples);
                  }
                  av_dlog(NULL, "diff=%f adiff=%f sample_diff=%d apts=%0.3f vpts=%0.3f %f\n",
 -                        diff, avg_diff, samples_size - samples_size1,
 +                        diff, avg_diff, wanted_nb_samples - nb_samples,
                          is->audio_clock, is->video_clock, is->audio_diff_threshold);
              }
          } else {
          }
      }
  
 -    return samples_size;
 +    return wanted_nb_samples;
  }
  
  /* decode one audio frame and returns its uncompressed size */
@@@ -1909,26 -1881,22 +1909,26 @@@ static int audio_decode_frame(VideoStat
      AVPacket *pkt_temp = &is->audio_pkt_temp;
      AVPacket *pkt = &is->audio_pkt;
      AVCodecContext *dec = is->audio_st->codec;
 -    int n, len1, data_size, got_frame;
 +    int len1, len2, data_size, resampled_data_size;
 +    int64_t dec_channel_layout;
 +    int got_frame;
      double pts;
      int new_packet = 0;
      int flush_complete = 0;
 +    int wanted_nb_samples;
  
      for (;;) {
          /* NOTE: the audio packet can contain several frames */
          while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) {
 -            int resample_changed, audio_resample;
 -
              if (!is->frame) {
                  if (!(is->frame = avcodec_alloc_frame()))
                      return AVERROR(ENOMEM);
              } else
                  avcodec_get_frame_defaults(is->frame);
  
 +            if (is->paused)
 +                return -1;
 +
              if (flush_complete)
                  break;
              new_packet = 0;
                                                     is->frame->nb_samples,
                                                     dec->sample_fmt, 1);
  
 -            audio_resample = dec->sample_fmt     != is->sdl_sample_fmt ||
 -                             dec->channel_layout != is->sdl_channel_layout;
 -
 -            resample_changed = dec->sample_fmt     != is->resample_sample_fmt ||
 -                               dec->channel_layout != is->resample_channel_layout;
 -
 -            if ((!is->avr && audio_resample) || resample_changed) {
 -                int ret;
 -                if (is->avr)
 -                    avresample_close(is->avr);
 -                else if (audio_resample) {
 -                    is->avr = avresample_alloc_context();
 -                    if (!is->avr) {
 -                        fprintf(stderr, "error allocating AVAudioResampleContext\n");
 -                        break;
 -                    }
 +            dec_channel_layout = (dec->channel_layout && dec->channels == av_get_channel_layout_nb_channels(dec->channel_layout)) ? dec->channel_layout : av_get_default_channel_layout(dec->channels);
 +            wanted_nb_samples = synchronize_audio(is, is->frame->nb_samples);
 +
 +            if (dec->sample_fmt != is->audio_src.fmt ||
 +                dec_channel_layout != is->audio_src.channel_layout ||
 +                dec->sample_rate != is->audio_src.freq ||
 +                (wanted_nb_samples != is->frame->nb_samples && !is->swr_ctx)) {
 +                if (is->swr_ctx)
 +                    swr_free(&is->swr_ctx);
 +                is->swr_ctx = swr_alloc_set_opts(NULL,
 +                                                 is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq,
 +                                                 dec_channel_layout,           dec->sample_fmt,   dec->sample_rate,
 +                                                 0, NULL);
 +                if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
 +                    fprintf(stderr, "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
 +                        dec->sample_rate,
 +                        av_get_sample_fmt_name(dec->sample_fmt),
 +                        dec->channels,
 +                        is->audio_tgt.freq,
 +                        av_get_sample_fmt_name(is->audio_tgt.fmt),
 +                        is->audio_tgt.channels);
 +                    break;
                  }
 -                if (audio_resample) {
 -                    av_opt_set_int(is->avr, "in_channel_layout",  dec->channel_layout,    0);
 -                    av_opt_set_int(is->avr, "in_sample_fmt",      dec->sample_fmt,        0);
 -                    av_opt_set_int(is->avr, "in_sample_rate",     dec->sample_rate,       0);
 -                    av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0);
 -                    av_opt_set_int(is->avr, "out_sample_fmt",     is->sdl_sample_fmt,     0);
 -                    av_opt_set_int(is->avr, "out_sample_rate",    dec->sample_rate,       0);
 -                    if (av_get_bytes_per_sample(dec->sample_fmt) <= 2)
 -                        av_opt_set_int(is->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0);
 -
 -                    if ((ret = avresample_open(is->avr)) < 0) {
 -                        fprintf(stderr, "error initializing libavresample\n");
 +                is->audio_src.channel_layout = dec_channel_layout;
 +                is->audio_src.channels = dec->channels;
 +                is->audio_src.freq = dec->sample_rate;
 +                is->audio_src.fmt = dec->sample_fmt;
 +            }
 +
 +            resampled_data_size = data_size;
 +            if (is->swr_ctx) {
 +                const uint8_t *in[] = { is->frame->data[0] };
 +                uint8_t *out[] = {is->audio_buf2};
 +                if (wanted_nb_samples != is->frame->nb_samples) {
 +                    if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - is->frame->nb_samples) * is->audio_tgt.freq / dec->sample_rate,
 +                                                wanted_nb_samples * is->audio_tgt.freq / dec->sample_rate) < 0) {
 +                        fprintf(stderr, "swr_set_compensation() failed\n");
                          break;
                      }
                  }
 -                is->resample_sample_fmt     = dec->sample_fmt;
 -                is->resample_channel_layout = dec->channel_layout;
 -            }
 -
 -            if (audio_resample) {
 -                void *tmp_out;
 -                int out_samples, out_size, out_linesize;
 -                int osize      = av_get_bytes_per_sample(is->sdl_sample_fmt);
 -                int nb_samples = is->frame->nb_samples;
 -
 -                out_size = av_samples_get_buffer_size(&out_linesize,
 -                                                      is->sdl_channels,
 -                                                      nb_samples,
 -                                                      is->sdl_sample_fmt, 0);
 -                tmp_out = av_realloc(is->audio_buf1, out_size);
 -                if (!tmp_out)
 -                    return AVERROR(ENOMEM);
 -                is->audio_buf1 = tmp_out;
 -
 -                out_samples = avresample_convert(is->avr,
 -                                                 (void **)&is->audio_buf1,
 -                                                 out_linesize, nb_samples,
 -                                                 (void **)is->frame->data,
 -                                                 is->frame->linesize[0],
 -                                                 is->frame->nb_samples);
 -                if (out_samples < 0) {
 -                    fprintf(stderr, "avresample_convert() failed\n");
 +                len2 = swr_convert(is->swr_ctx, out, sizeof(is->audio_buf2) / is->audio_tgt.channels / av_get_bytes_per_sample(is->audio_tgt.fmt),
 +                                                in, is->frame->nb_samples);
 +                if (len2 < 0) {
 +                    fprintf(stderr, "audio_resample() failed\n");
                      break;
                  }
 -                is->audio_buf = is->audio_buf1;
 -                data_size = out_samples * osize * is->sdl_channels;
 +                if (len2 == sizeof(is->audio_buf2) / is->audio_tgt.channels / av_get_bytes_per_sample(is->audio_tgt.fmt)) {
 +                    fprintf(stderr, "warning: audio buffer is probably too small\n");
 +                    swr_init(is->swr_ctx);
 +                }
 +                is->audio_buf = is->audio_buf2;
 +                resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
              } else {
                  is->audio_buf = is->frame->data[0];
              }
              /* if no pts, then compute it */
              pts = is->audio_clock;
              *pts_ptr = pts;
 -            n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt);
              is->audio_clock += (double)data_size /
 -                (double)(n * dec->sample_rate);
 +                (dec->channels * dec->sample_rate * av_get_bytes_per_sample(dec->sample_fmt));
  #ifdef DEBUG
              {
                  static double last_clock;
                  last_clock = is->audio_clock;
              }
  #endif
 -            return data_size;
 +            return resampled_data_size;
          }
  
          /* free the current packet */
@@@ -2057,8 -2037,6 +2057,8 @@@ static void sdl_audio_callback(void *op
  {
      VideoState *is = opaque;
      int audio_size, len1;
 +    int bytes_per_sec;
 +    int frame_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, 1, is->audio_tgt.fmt, 1);
      double pts;
  
      audio_callback_time = av_gettime();
             if (audio_size < 0) {
                  /* if error, just output silence */
                 is->audio_buf      = is->silence_buf;
 -               is->audio_buf_size = sizeof(is->silence_buf);
 +               is->audio_buf_size = sizeof(is->silence_buf) / frame_size * frame_size;
             } else {
 -               if (is->show_audio)
 +               if (is->show_mode != SHOW_MODE_VIDEO)
                     update_sample_display(is, (int16_t *)is->audio_buf, audio_size);
 -               audio_size = synchronize_audio(is, (int16_t *)is->audio_buf, audio_size,
 -                                              pts);
                 is->audio_buf_size = audio_size;
             }
             is->audio_buf_index = 0;
          stream += len1;
          is->audio_buf_index += len1;
      }
 +    bytes_per_sec = is->audio_tgt.freq * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
 +    is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index;
 +    /* Let's assume the audio driver that is used by SDL has two periods. */
 +    is->audio_current_pts = is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / bytes_per_sec;
 +    is->audio_current_pts_drift = is->audio_current_pts - audio_callback_time / 1000000.0;
 +}
 +
 +static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params)
 +{
 +    SDL_AudioSpec wanted_spec, spec;
 +    const char *env;
 +    const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6};
 +
 +    env = SDL_getenv("SDL_AUDIO_CHANNELS");
 +    if (env) {
 +        wanted_nb_channels = SDL_atoi(env);
 +        wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
 +    }
 +    if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) {
 +        wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels);
 +        wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX;
 +    }
 +    wanted_spec.channels = av_get_channel_layout_nb_channels(wanted_channel_layout);
 +    wanted_spec.freq = wanted_sample_rate;
 +    if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) {
 +        fprintf(stderr, "Invalid sample rate or channel count!\n");
 +        return -1;
 +    }
 +    wanted_spec.format = AUDIO_S16SYS;
 +    wanted_spec.silence = 0;
 +    wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
 +    wanted_spec.callback = sdl_audio_callback;
 +    wanted_spec.userdata = opaque;
 +    while (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
 +        fprintf(stderr, "SDL_OpenAudio (%d channels): %s\n", wanted_spec.channels, SDL_GetError());
 +        wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)];
 +        if (!wanted_spec.channels) {
 +            fprintf(stderr, "No more channel combinations to try, audio open failed\n");
 +            return -1;
 +        }
 +        wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels);
 +    }
 +    if (spec.format != AUDIO_S16SYS) {
 +        fprintf(stderr, "SDL advised audio format %d is not supported!\n", spec.format);
 +        return -1;
 +    }
 +    if (spec.channels != wanted_spec.channels) {
 +        wanted_channel_layout = av_get_default_channel_layout(spec.channels);
 +        if (!wanted_channel_layout) {
 +            fprintf(stderr, "SDL advised channel count %d is not supported!\n", spec.channels);
 +            return -1;
 +        }
 +    }
 +
 +    audio_hw_params->fmt = AV_SAMPLE_FMT_S16;
 +    audio_hw_params->freq = spec.freq;
 +    audio_hw_params->channel_layout = wanted_channel_layout;
 +    audio_hw_params->channels =  spec.channels;
 +    return spec.size;
  }
  
  /* open a given stream. Return 0 if OK */
@@@ -2152,6 -2073,7 +2152,6 @@@ static int stream_component_open(VideoS
      AVFormatContext *ic = is->ic;
      AVCodecContext *avctx;
      AVCodec *codec;
 -    SDL_AudioSpec wanted_spec, spec;
      AVDictionary *opts;
      AVDictionaryEntry *t = NULL;
  
          return -1;
      avctx = ic->streams[stream_index]->codec;
  
 -    opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index]);
 -
      codec = avcodec_find_decoder(avctx->codec_id);
 -    avctx->debug_mv          = debug_mv;
 -    avctx->debug             = debug;
 +    opts = filter_codec_opts(codec_opts, codec, ic, ic->streams[stream_index]);
 +
 +    switch(avctx->codec_type){
 +        case AVMEDIA_TYPE_AUDIO   : is->last_audio_stream    = stream_index; if(audio_codec_name   ) codec= avcodec_find_decoder_by_name(   audio_codec_name); break;
 +        case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; if(subtitle_codec_name) codec= avcodec_find_decoder_by_name(subtitle_codec_name); break;
 +        case AVMEDIA_TYPE_VIDEO   : is->last_video_stream    = stream_index; if(video_codec_name   ) codec= avcodec_find_decoder_by_name(   video_codec_name); break;
 +    }
 +    if (!codec)
 +        return -1;
 +
      avctx->workaround_bugs   = workaround_bugs;
 +    avctx->lowres            = lowres;
 +    if(avctx->lowres > codec->max_lowres){
 +        av_log(avctx, AV_LOG_WARNING, "The maximum value for lowres supported by the decoder is %d\n",
 +                codec->max_lowres);
 +        avctx->lowres= codec->max_lowres;
 +    }
      avctx->idct_algo         = idct;
      avctx->skip_frame        = skip_frame;
      avctx->skip_idct         = skip_idct;
      avctx->skip_loop_filter  = skip_loop_filter;
      avctx->error_concealment = error_concealment;
  
 +    if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
      if (fast)   avctx->flags2 |= CODEC_FLAG2_FAST;
 +    if(codec->capabilities & CODEC_CAP_DR1)
 +        avctx->flags |= CODEC_FLAG_EMU_EDGE;
  
      if (!av_dict_get(opts, "threads", NULL, 0))
          av_dict_set(&opts, "threads", "auto", 0);
  
      /* prepare audio output */
      if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
 -        wanted_spec.freq = avctx->sample_rate;
 -        wanted_spec.format = AUDIO_S16SYS;
 -
 -        if (!avctx->channel_layout)
 -            avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
 -        if (!avctx->channel_layout) {
 -            fprintf(stderr, "unable to guess channel layout\n");
 +        int audio_hw_buf_size = audio_open(is, avctx->channel_layout, avctx->channels, avctx->sample_rate, &is->audio_src);
 +        if (audio_hw_buf_size < 0)
              return -1;
 -        }
 -        if (avctx->channels == 1)
 -            is->sdl_channel_layout = AV_CH_LAYOUT_MONO;
 -        else
 -            is->sdl_channel_layout = AV_CH_LAYOUT_STEREO;
 -        is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout);
 -
 -        wanted_spec.channels = is->sdl_channels;
 -        wanted_spec.silence = 0;
 -        wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
 -        wanted_spec.callback = sdl_audio_callback;
 -        wanted_spec.userdata = is;
 -        if (SDL_OpenAudio(&wanted_spec, &spec) < 0) {
 -            fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());
 -            return -1;
 -        }
 -        is->audio_hw_buf_size = spec.size;
 -        is->sdl_sample_fmt          = AV_SAMPLE_FMT_S16;
 -        is->resample_sample_fmt     = is->sdl_sample_fmt;
 -        is->resample_channel_layout = is->sdl_channel_layout;
 +        is->audio_hw_buf_size = audio_hw_buf_size;
 +        is->audio_tgt = is->audio_src;
      }
  
      ic->streams[stream_index]->discard = AVDISCARD_DEFAULT;
          is->audio_diff_avg_count = 0;
          /* since we do not have a precise anough audio fifo fullness,
             we correct audio sync only if larger than this threshold */
 -        is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / avctx->sample_rate;
 +        is->audio_diff_threshold = 2.0 * is->audio_hw_buf_size / av_samples_get_buffer_size(NULL, is->audio_tgt.channels, is->audio_tgt.freq, is->audio_tgt.fmt, 1);
  
          memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));
 -        packet_queue_init(&is->audioq);
 +        memset(&is->audio_pkt_temp, 0, sizeof(is->audio_pkt_temp));
 +        packet_queue_start(&is->audioq);
          SDL_PauseAudio(0);
          break;
      case AVMEDIA_TYPE_VIDEO:
          is->video_stream = stream_index;
          is->video_st = ic->streams[stream_index];
  
 -        packet_queue_init(&is->videoq);
 +        packet_queue_start(&is->videoq);
          is->video_tid = SDL_CreateThread(video_thread, is);
          break;
      case AVMEDIA_TYPE_SUBTITLE:
          is->subtitle_stream = stream_index;
          is->subtitle_st = ic->streams[stream_index];
 -        packet_queue_init(&is->subtitleq);
 +        packet_queue_start(&is->subtitleq);
  
          is->subtitle_tid = SDL_CreateThread(subtitle_thread, is);
          break;
@@@ -2262,10 -2191,10 +2262,10 @@@ static void stream_component_close(Vide
  
          SDL_CloseAudio();
  
 -        packet_queue_end(&is->audioq);
 +        packet_queue_flush(&is->audioq);
          av_free_packet(&is->audio_pkt);
 -        if (is->avr)
 -            avresample_free(&is->avr);
 +        if (is->swr_ctx)
 +            swr_free(&is->swr_ctx);
          av_freep(&is->audio_buf1);
          is->audio_buf = NULL;
          av_freep(&is->frame);
  
          SDL_WaitThread(is->video_tid, NULL);
  
 -        packet_queue_end(&is->videoq);
 +        packet_queue_flush(&is->videoq);
          break;
      case AVMEDIA_TYPE_SUBTITLE:
          packet_queue_abort(&is->subtitleq);
  
          SDL_WaitThread(is->subtitle_tid, NULL);
  
 -        packet_queue_end(&is->subtitleq);
 +        packet_queue_flush(&is->subtitleq);
          break;
      default:
          break;
  
      ic->streams[stream_index]->discard = AVDISCARD_ALL;
      avcodec_close(avctx);
 +#if CONFIG_AVFILTER
      free_buffer_pool(&is->buffer_pool);
 +#endif
      switch (avctx->codec_type) {
      case AVMEDIA_TYPE_AUDIO:
          is->audio_st = NULL;
      }
  }
  
 -/* since we have only one decoding thread, we can use a global
 -   variable instead of a thread local variable */
 -static VideoState *global_video_state;
 -
  static int decode_interrupt_cb(void *ctx)
  {
 -    return global_video_state && global_video_state->abort_request;
 +    VideoState *is = ctx;
 +    return is->abort_request;
  }
  
  /* this thread gets the stream from the disk or the network */
 -static int decode_thread(void *arg)
 +static int read_thread(void *arg)
  {
      VideoState *is = arg;
      AVFormatContext *ic = NULL;
      int orig_nb_streams;
  
      memset(st_index, -1, sizeof(st_index));
 -    is->video_stream = -1;
 -    is->audio_stream = -1;
 -    is->subtitle_stream = -1;
 -
 -    global_video_state = is;
 +    is->last_video_stream = is->video_stream = -1;
 +    is->last_audio_stream = is->audio_stream = -1;
 +    is->last_subtitle_stream = is->subtitle_stream = -1;
  
      ic = avformat_alloc_context();
      ic->interrupt_callback.callback = decode_interrupt_cb;
 +    ic->interrupt_callback.opaque = is;
      err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
      if (err < 0) {
          print_error(is->filename, err);
      av_freep(&opts);
  
      if (ic->pb)
 -        ic->pb->eof_reached = 0; // FIXME hack, avplay maybe should not use url_feof() to test for the end
 +        ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use url_feof() to test for the end
  
      if (seek_by_bytes < 0)
          seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT);
          av_dump_format(ic, 0, is->filename, 0);
      }
  
 +    is->show_mode = show_mode;
 +
      /* open the streams */
      if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
          stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
          ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
      }
      is->refresh_tid = SDL_CreateThread(refresh_thread, is);
 -    if (ret < 0) {
 -        if (!display_disable)
 -            is->show_audio = 2;
 -    }
 +    if (is->show_mode == SHOW_MODE_NONE)
 +        is->show_mode = ret >= 0 ? SHOW_MODE_VIDEO : SHOW_MODE_RDFT;
  
      if (st_index[AVMEDIA_TYPE_SUBTITLE] >= 0) {
          stream_component_open(is, st_index[AVMEDIA_TYPE_SUBTITLE]);
              else
                  av_read_play(ic);
          }
 -#if CONFIG_RTSP_DEMUXER
 -        if (is->paused && !strcmp(ic->iformat->name, "rtsp")) {
 +#if CONFIG_RTSP_DEMUXER || CONFIG_MMSH_PROTOCOL
 +        if (is->paused &&
 +                (!strcmp(ic->iformat->name, "rtsp") ||
 +                 (ic->pb && !strncmp(input_filename, "mmsh:", 5)))) {
              /* wait 10 ms to avoid trying to get another packet */
              /* XXX: horrible */
              SDL_Delay(10);
  
          /* if the queue are full, no need to read more */
          if (   is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
 -            || (   (is->audioq   .size  > MIN_AUDIOQ_SIZE || is->audio_stream < 0)
 -                && (is->videoq   .nb_packets > MIN_FRAMES || is->video_stream < 0)
 -                && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0))) {
 +            || (   (is->audioq   .nb_packets > MIN_FRAMES || is->audio_stream < 0 || is->audioq.abort_request)
 +                && (is->videoq   .nb_packets > MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request)
 +                && (is->subtitleq.nb_packets > MIN_FRAMES || is->subtitle_stream < 0 || is->subtitleq.abort_request))) {
              /* wait 10 ms */
              SDL_Delay(10);
              continue;
              SDL_Delay(10);
              if (is->audioq.size + is->videoq.size + is->subtitleq.size == 0) {
                  if (loop != 1 && (!loop || --loop)) {
 -                    stream_seek(cur_stream, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
 +                    stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
                  } else if (autoexit) {
                      ret = AVERROR_EOF;
                      goto fail;
                  }
              }
 +            eof=0;
              continue;
          }
          ret = av_read_frame(ic, pkt);
          if (ret < 0) {
 -            if (ret == AVERROR_EOF || (ic->pb && ic->pb->eof_reached))
 +            if (ret == AVERROR_EOF || url_feof(ic->pb))
                  eof = 1;
              if (ic->pb && ic->pb->error)
                  break;
  
      ret = 0;
   fail:
 -    /* disable interrupting */
 -    global_video_state = NULL;
 -
      /* close each stream */
      if (is->audio_stream >= 0)
          stream_component_close(is, is->audio_stream);
@@@ -2616,13 -2547,9 +2616,13 @@@ static VideoState *stream_open(const ch
      is->subpq_mutex = SDL_CreateMutex();
      is->subpq_cond  = SDL_CreateCond();
  
 +    packet_queue_init(&is->videoq);
 +    packet_queue_init(&is->audioq);
 +    packet_queue_init(&is->subtitleq);
 +
      is->av_sync_type = av_sync_type;
 -    is->parse_tid    = SDL_CreateThread(decode_thread, is);
 -    if (!is->parse_tid) {
 +    is->read_tid     = SDL_CreateThread(read_thread, is);
 +    if (!is->read_tid) {
          av_free(is);
          return NULL;
      }
@@@ -2633,19 -2560,16 +2633,19 @@@ static void stream_cycle_channel(VideoS
  {
      AVFormatContext *ic = is->ic;
      int start_index, stream_index;
 +    int old_index;
      AVStream *st;
  
 -    if (codec_type == AVMEDIA_TYPE_VIDEO)
 -        start_index = is->video_stream;
 -    else if (codec_type == AVMEDIA_TYPE_AUDIO)
 -        start_index = is->audio_stream;
 -    else
 -        start_index = is->subtitle_stream;
 -    if (start_index < (codec_type == AVMEDIA_TYPE_SUBTITLE ? -1 : 0))
 -        return;
 +    if (codec_type == AVMEDIA_TYPE_VIDEO) {
 +        start_index = is->last_video_stream;
 +        old_index = is->video_stream;
 +    } else if (codec_type == AVMEDIA_TYPE_AUDIO) {
 +        start_index = is->last_audio_stream;
 +        old_index = is->audio_stream;
 +    } else {
 +        start_index = is->last_subtitle_stream;
 +        old_index = is->subtitle_stream;
 +    }
      stream_index = start_index;
      for (;;) {
          if (++stream_index >= is->ic->nb_streams)
              if (codec_type == AVMEDIA_TYPE_SUBTITLE)
              {
                  stream_index = -1;
 +                is->last_subtitle_stream = -1;
                  goto the_end;
 -            } else
 -                stream_index = 0;
 +            }
 +            if (start_index == -1)
 +                return;
 +            stream_index = 0;
          }
          if (stream_index == start_index)
              return;
          }
      }
   the_end:
 -    stream_component_close(is, start_index);
 +    stream_component_close(is, old_index);
      stream_component_open(is, stream_index);
  }
  
  
 -static void toggle_full_screen(void)
 +static void toggle_full_screen(VideoState *is)
  {
-     av_unused int i;
-     is_full_screen = !is_full_screen;
  #if defined(__APPLE__) && SDL_VERSION_ATLEAST(1, 2, 14)
 -    /* OS X needs to empty the picture_queue */
 +    /* OS X needs to reallocate the SDL overlays */
-     for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++) {
+     int i;
+     for (i = 0; i < VIDEO_PICTURE_QUEUE_SIZE; i++)
 -        cur_stream->pictq[i].reallocate = 1;
 +        is->pictq[i].reallocate = 1;
-     }
  #endif
 -    video_open(cur_stream);
+     is_full_screen = !is_full_screen;
 +    video_open(is, 1);
  }
  
 -static void toggle_pause(void)
 +static void toggle_pause(VideoState *is)
  {
 -    if (cur_stream)
 -        stream_pause(cur_stream);
 -    step = 0;
 +    stream_toggle_pause(is);
 +    is->step = 0;
  }
  
 -static void step_to_next_frame(void)
 +static void step_to_next_frame(VideoState *is)
  {
 -    if (cur_stream) {
 -        /* if the stream is paused unpause it, then step */
 -        if (cur_stream->paused)
 -            stream_pause(cur_stream);
 -    }
 -    step = 1;
 +    /* if the stream is paused unpause it, then step */
 +    if (is->paused)
 +        stream_toggle_pause(is);
 +    is->step = 1;
  }
  
 -static void toggle_audio_display(void)
 +static void toggle_audio_display(VideoState *is)
  {
 -    if (cur_stream) {
 -        int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
 -        cur_stream->show_audio = (cur_stream->show_audio + 1) % 3;
 -        fill_rectangle(screen,
 -                       cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height,
 -                       bgcolor);
 -        SDL_UpdateRect(screen, cur_stream->xleft, cur_stream->ytop, cur_stream->width, cur_stream->height);
 -    }
 +    int bgcolor = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
 +    is->show_mode = (is->show_mode + 1) % SHOW_MODE_NB;
 +    fill_rectangle(screen,
 +                is->xleft, is->ytop, is->width, is->height,
 +                bgcolor);
 +    SDL_UpdateRect(screen, is->xleft, is->ytop, is->width, is->height);
  }
  
  /* handle an event sent by the GUI */
 -static void event_loop(void)
 +static void event_loop(VideoState *cur_stream)
  {
      SDL_Event event;
      double incr, pos, frac;
          switch (event.type) {
          case SDL_KEYDOWN:
              if (exit_on_keydown) {
 -                do_exit();
 +                do_exit(cur_stream);
                  break;
              }
              switch (event.key.keysym.sym) {
              case SDLK_ESCAPE:
              case SDLK_q:
 -                do_exit();
 +                do_exit(cur_stream);
                  break;
              case SDLK_f:
 -                toggle_full_screen();
 +                toggle_full_screen(cur_stream);
 +                cur_stream->force_refresh = 1;
                  break;
              case SDLK_p:
              case SDLK_SPACE:
 -                toggle_pause();
 +                toggle_pause(cur_stream);
                  break;
              case SDLK_s: // S: Step to next frame
 -                step_to_next_frame();
 +                step_to_next_frame(cur_stream);
                  break;
              case SDLK_a:
 -                if (cur_stream)
 -                    stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
 +                stream_cycle_channel(cur_stream, AVMEDIA_TYPE_AUDIO);
                  break;
              case SDLK_v:
 -                if (cur_stream)
 -                    stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
 +                stream_cycle_channel(cur_stream, AVMEDIA_TYPE_VIDEO);
                  break;
              case SDLK_t:
 -                if (cur_stream)
 -                    stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
 +                stream_cycle_channel(cur_stream, AVMEDIA_TYPE_SUBTITLE);
                  break;
              case SDLK_w:
 -                toggle_audio_display();
 +                toggle_audio_display(cur_stream);
 +                cur_stream->force_refresh = 1;
                  break;
 +            case SDLK_PAGEUP:
 +                incr = 600.0;
 +                goto do_seek;
 +            case SDLK_PAGEDOWN:
 +                incr = -600.0;
 +                goto do_seek;
              case SDLK_LEFT:
                  incr = -10.0;
                  goto do_seek;
              case SDLK_DOWN:
                  incr = -60.0;
              do_seek:
 -                if (cur_stream) {
                      if (seek_by_bytes) {
                          if (cur_stream->video_stream >= 0 && cur_stream->video_current_pos >= 0) {
                              pos = cur_stream->video_current_pos;
                          pos += incr;
                          stream_seek(cur_stream, (int64_t)(pos * AV_TIME_BASE), (int64_t)(incr * AV_TIME_BASE), 0);
                      }
 -                }
                  break;
              default:
                  break;
              }
              break;
 +        case SDL_VIDEOEXPOSE:
 +            cur_stream->force_refresh = 1;
 +            break;
          case SDL_MOUSEBUTTONDOWN:
              if (exit_on_mousedown) {
 -                do_exit();
 +                do_exit(cur_stream);
                  break;
              }
          case SDL_MOUSEMOTION:
                      break;
                  x = event.motion.x;
              }
 -            if (cur_stream) {
                  if (seek_by_bytes || cur_stream->ic->duration <= 0) {
                      uint64_t size =  avio_size(cur_stream->ic->pb);
                      stream_seek(cur_stream, size*x/cur_stream->width, 0, 1);
                          ts += cur_stream->ic->start_time;
                      stream_seek(cur_stream, ts, 0, 0);
                  }
 -            }
              break;
          case SDL_VIDEORESIZE:
 -            if (cur_stream) {
                  screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0,
                                            SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL);
                  screen_width  = cur_stream->width  = event.resize.w;
                  screen_height = cur_stream->height = event.resize.h;
 -            }
 +                cur_stream->force_refresh = 1;
              break;
          case SDL_QUIT:
          case FF_QUIT_EVENT:
 -            do_exit();
 +            do_exit(cur_stream);
              break;
          case FF_ALLOC_EVENT:
 -            video_open(event.user.data1);
              alloc_picture(event.user.data1);
              break;
          case FF_REFRESH_EVENT:
 -            video_refresh_timer(event.user.data1);
 +            video_refresh(event.user.data1);
              cur_stream->refresh = 0;
              break;
          default:
  
  static int opt_frame_size(const char *opt, const char *arg)
  {
 -    av_log(NULL, AV_LOG_ERROR,
 -           "Option '%s' has been removed, use private format options instead\n", opt);
 -    return AVERROR(EINVAL);
 +    av_log(NULL, AV_LOG_WARNING, "Option -s is deprecated, use -video_size.\n");
 +    return opt_default("video_size", arg);
  }
  
  static int opt_width(const char *opt, const char *arg)
@@@ -2901,8 -2825,9 +2900,8 @@@ static int opt_format(const char *opt, 
  
  static int opt_frame_pix_fmt(const char *opt, const char *arg)
  {
 -    av_log(NULL, AV_LOG_ERROR,
 -           "Option '%s' has been removed, use private format options instead\n", opt);
 -    return AVERROR(EINVAL);
 +    av_log(NULL, AV_LOG_WARNING, "Option -pix_fmt is deprecated, use -pixel_format.\n");
 +    return opt_default("pixel_format", arg);
  }
  
  static int opt_sync(const char *opt, const char *arg)
@@@ -2932,39 -2857,19 +2931,39 @@@ static int opt_duration(const char *opt
      return 0;
  }
  
 -static int opt_debug(const char *opt, const char *arg)
 +static int opt_show_mode(const char *opt, const char *arg)
  {
 -    av_log_set_level(99);
 -    debug = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX);
 +    show_mode = !strcmp(arg, "video") ? SHOW_MODE_VIDEO :
 +                !strcmp(arg, "waves") ? SHOW_MODE_WAVES :
 +                !strcmp(arg, "rdft" ) ? SHOW_MODE_RDFT  :
 +                parse_number_or_die(opt, arg, OPT_INT, 0, SHOW_MODE_NB-1);
      return 0;
  }
  
 -static int opt_vismv(const char *opt, const char *arg)
 +static void opt_input_file(void *optctx, const char *filename)
  {
 -    debug_mv = parse_number_or_die(opt, arg, OPT_INT64, INT_MIN, INT_MAX);
 +    if (input_filename) {
 +        fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
 +                filename, input_filename);
 +        exit_program(1);
 +    }
 +    if (!strcmp(filename, "-"))
 +        filename = "pipe:";
 +    input_filename = filename;
 +}
 +
 +static int opt_codec(void *o, const char *opt, const char *arg)
 +{
 +    switch(opt[strlen(opt)-1]){
 +    case 'a' :    audio_codec_name = arg; break;
 +    case 's' : subtitle_codec_name = arg; break;
 +    case 'v' :    video_codec_name = arg; break;
 +    }
      return 0;
  }
  
 +static int dummy;
 +
  static const OptionDef options[] = {
  #include "cmdutils_common_opts.h"
      { "x", HAS_ARG, { (void*)opt_width }, "force displayed width", "width" },
      { "f", HAS_ARG, { (void*)opt_format }, "force format", "fmt" },
      { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { (void*)opt_frame_pix_fmt }, "set pixel format", "format" },
      { "stats", OPT_BOOL | OPT_EXPERT, { (void*)&show_status }, "show status", "" },
 -    { "debug", HAS_ARG | OPT_EXPERT, { (void*)opt_debug }, "print specific debug info", "" },
      { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&workaround_bugs }, "workaround bugs", "" },
 -    { "vismv", HAS_ARG | OPT_EXPERT, { (void*)opt_vismv }, "visualize motion vectors", "" },
      { "fast", OPT_BOOL | OPT_EXPERT, { (void*)&fast }, "non spec compliant optimizations", "" },
      { "genpts", OPT_BOOL | OPT_EXPERT, { (void*)&genpts }, "generate pts", "" },
      { "drp", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&decoder_reorder_pts }, "let decoder reorder pts 0=off 1=on -1=auto", ""},
 +    { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&lowres }, "", "" },
      { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_loop_filter }, "", "" },
      { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_frame }, "", "" },
      { "skipidct", OPT_INT | HAS_ARG | OPT_EXPERT, { (void*)&skip_idct }, "", "" },
      { "vf", OPT_STRING | HAS_ARG, { (void*)&vfilters }, "video filters", "filter list" },
  #endif
      { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { (void*)&rdftspeed }, "rdft speed", "msecs" },
 +    { "showmode", HAS_ARG, {(void*)opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" },
      { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { (void*)opt_default }, "generic catch all option", "" },
 -    { "i", 0, { NULL }, "avconv compatibility dummy option", ""},
 +    { "i", OPT_BOOL, {(void *)&dummy}, "read specified file", "input_file"},
 +    { "codec", HAS_ARG | OPT_FUNC2, {(void*)opt_codec}, "force decoder", "decoder" },
      { NULL, },
  };
  
  static void show_usage(void)
  {
 -    printf("Simple media player\n");
 -    printf("usage: %s [options] input_file\n", program_name);
 -    printf("\n");
 +    av_log(NULL, AV_LOG_INFO, "Simple media player\n");
 +    av_log(NULL, AV_LOG_INFO, "usage: %s [options] input_file\n", program_name);
 +    av_log(NULL, AV_LOG_INFO, "\n");
  }
  
 -static void show_help(void)
 +static int opt_help(const char *opt, const char *arg)
  {
      av_log_set_callback(log_callback_help);
      show_usage();
             "s                   activate frame-step mode\n"
             "left/right          seek backward/forward 10 seconds\n"
             "down/up             seek backward/forward 1 minute\n"
 +           "page down/page up   seek backward/forward 10 minutes\n"
             "mouse click         seek to percentage in file corresponding to fraction of width\n"
             );
 +    return 0;
  }
  
 -static void opt_input_file(void *optctx, const char *filename)
 +static int lockmgr(void **mtx, enum AVLockOp op)
  {
 -    if (input_filename) {
 -        fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
 -                filename, input_filename);
 -        exit(1);
 -    }
 -    if (!strcmp(filename, "-"))
 -        filename = "pipe:";
 -    input_filename = filename;
 +   switch(op) {
 +      case AV_LOCK_CREATE:
 +          *mtx = SDL_CreateMutex();
 +          if(!*mtx)
 +              return 1;
 +          return 0;
 +      case AV_LOCK_OBTAIN:
 +          return !!SDL_LockMutex(*mtx);
 +      case AV_LOCK_RELEASE:
 +          return !!SDL_UnlockMutex(*mtx);
 +      case AV_LOCK_DESTROY:
 +          SDL_DestroyMutex(*mtx);
 +          return 0;
 +   }
 +   return 1;
  }
  
  /* Called from the main */
  int main(int argc, char **argv)
  {
      int flags;
 +    VideoState *is;
 +    char dummy_videodriver[] = "SDL_VIDEODRIVER=dummy";
  
      av_log_set_flags(AV_LOG_SKIP_REPEATED);
      parse_loglevel(argc, argv, options);
  
      init_opts();
  
 -    show_banner();
 +    signal(SIGINT , sigterm_handler); /* Interrupt (ANSI).    */
 +    signal(SIGTERM, sigterm_handler); /* Termination (ANSI).  */
 +
 +    show_banner(argc, argv, options);
  
      parse_options(NULL, argc, argv, options, opt_input_file);
  
          video_disable = 1;
      }
      flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
 +    if (audio_disable)
 +        flags &= ~SDL_INIT_AUDIO;
 +    if (display_disable)
 +        SDL_putenv(dummy_videodriver); /* For the event queue, we always need a video driver. */
  #if !defined(__MINGW32__) && !defined(__APPLE__)
      flags |= SDL_INIT_EVENTTHREAD; /* Not supported on Windows or Mac OS X */
  #endif
      if (SDL_Init (flags)) {
          fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
 +        fprintf(stderr, "(Did you set the DISPLAY variable?)\n");
          exit(1);
      }
  
      SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);
      SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
  
 +    if (av_lockmgr_register(lockmgr)) {
 +        fprintf(stderr, "Could not initialize lock manager!\n");
 +        do_exit(NULL);
 +    }
 +
      av_init_packet(&flush_pkt);
 -    flush_pkt.data = "FLUSH";
 +    flush_pkt.data = (char *)(intptr_t)"FLUSH";
  
 -    cur_stream = stream_open(input_filename, file_iformat);
 +    is = stream_open(input_filename, file_iformat);
 +    if (!is) {
 +        fprintf(stderr, "Failed to initialize VideoState!\n");
 +        do_exit(NULL);
 +    }
  
 -    event_loop();
 +    event_loop(is);
  
      /* never returns */
  
diff --combined libavcodec/pthread.c
@@@ -6,20 -6,20 +6,20 @@@
   * to Michael Niedermayer <michaelni@gmx.at> for writing initial
   * implementation.
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -43,7 -43,6 +43,7 @@@
  #include <sys/param.h>
  #endif
  #include <sys/types.h>
 +#include <sys/param.h>
  #include <sys/sysctl.h>
  #endif
  #if HAVE_SYSCONF
@@@ -58,8 -57,6 +58,8 @@@
  #include <pthread.h>
  #elif HAVE_W32THREADS
  #include "w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
  #endif
  
  typedef int (action_func)(AVCodecContext *c, void *arg);
@@@ -190,10 -187,6 +190,10 @@@ static int get_logical_cpus(AVCodecCont
      nb_cpus = sysconf(_SC_NPROCESSORS_ONLN);
  #endif
      av_log(avctx, AV_LOG_DEBUG, "detected %d logical cores\n", nb_cpus);
 +
 +    if  (avctx->height)
 +        nb_cpus = FFMIN(nb_cpus, (avctx->height+15)/16);
 +
      return nb_cpus;
  }
  
@@@ -365,36 -358,34 +365,36 @@@ static attribute_align_arg void *frame_
      AVCodecContext *avctx = p->avctx;
      AVCodec *codec = avctx->codec;
  
 +    pthread_mutex_lock(&p->mutex);
      while (1) {
 -        if (p->state == STATE_INPUT_READY && !fctx->die) {
 -            pthread_mutex_lock(&p->mutex);
 +        int i;
              while (p->state == STATE_INPUT_READY && !fctx->die)
                  pthread_cond_wait(&p->input_cond, &p->mutex);
 -            pthread_mutex_unlock(&p->mutex);
 -        }
  
          if (fctx->die) break;
  
 -        if (!codec->update_thread_context && avctx->thread_safe_callbacks)
 +        if (!codec->update_thread_context && (avctx->thread_safe_callbacks || avctx->get_buffer == avcodec_default_get_buffer))
              ff_thread_finish_setup(avctx);
  
 -        pthread_mutex_lock(&p->mutex);
          avcodec_get_frame_defaults(&p->frame);
          p->got_frame = 0;
          p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt);
  
          if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx);
  
 +        pthread_mutex_lock(&p->progress_mutex);
 +        for (i = 0; i < MAX_BUFFERS; i++)
 +            if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != CODEC_ID_H264)) {
 +                p->progress[i][0] = INT_MAX;
 +                p->progress[i][1] = INT_MAX;
 +            }
          p->state = STATE_INPUT_READY;
  
 -        pthread_mutex_lock(&p->progress_mutex);
 +        pthread_cond_broadcast(&p->progress_cond);
          pthread_cond_signal(&p->output_cond);
          pthread_mutex_unlock(&p->progress_mutex);
 -
 -        pthread_mutex_unlock(&p->mutex);
      }
 +    pthread_mutex_unlock(&p->mutex);
  
      return NULL;
  }
@@@ -440,7 -431,6 +440,7 @@@ static int update_context_from_thread(A
      }
  
      if (for_user) {
 +        dst->delay       = src->thread_count - 1;
          dst->coded_frame = src->coded_frame;
      } else {
          if (dst->codec->update_thread_context)
@@@ -477,7 -467,6 +477,7 @@@ static int update_context_from_user(AVC
  
      dst->frame_number     = src->frame_number;
      dst->reordered_opaque = src->reordered_opaque;
 +    dst->thread_safe_callbacks = src->thread_safe_callbacks;
  
      if (src->slice_count && src->slice_offset) {
          if (dst->slice_count < src->slice_count) {
@@@ -704,10 -693,6 +704,10 @@@ void ff_thread_finish_setup(AVCodecCont
  
      if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return;
  
 +    if(p->state == STATE_SETUP_FINISHED){
 +        av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n");
 +    }
 +
      pthread_mutex_lock(&p->progress_mutex);
      p->state = STATE_SETUP_FINISHED;
      pthread_cond_broadcast(&p->progress_cond);
@@@ -728,7 -713,6 +728,7 @@@ static void park_frame_worker_threads(F
                  pthread_cond_wait(&p->output_cond, &p->progress_mutex);
              pthread_mutex_unlock(&p->progress_mutex);
          }
 +        p->got_frame = 0;
      }
  }
  
@@@ -754,7 -738,6 +754,7 @@@ static void frame_thread_free(AVCodecCo
  
          if (p->thread_init)
              pthread_join(p->thread, NULL);
 +        p->thread_init=0;
  
          if (codec->close)
              codec->close(p->avctx);
@@@ -800,8 -783,6 +800,8 @@@ static int frame_thread_init(AVCodecCon
  
      if (!thread_count) {
          int nb_cpus = get_logical_cpus(avctx);
 +        if ((avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) || avctx->debug_mv)
 +            nb_cpus = 1;
          // use number of cores + 1 as thread count if there is more than one
          if (nb_cpus > 1)
              thread_count = avctx->thread_count = FFMIN(nb_cpus + 1, MAX_AUTO_THREADS);
  
          if (err) goto error;
  
 -        if (!pthread_create(&p->thread, NULL, frame_worker_thread, p))
 -            p->thread_init = 1;
 +        err = AVERROR(pthread_create(&p->thread, NULL, frame_worker_thread, p));
 +        p->thread_init= !err;
 +        if(!p->thread_init)
 +            goto error;
      }
  
      return 0;
@@@ -886,8 -865,8 +886,8 @@@ error
  
  void ff_thread_flush(AVCodecContext *avctx)
  {
-     FrameThreadContext *fctx = avctx->thread_opaque;
      int i;
+     FrameThreadContext *fctx = avctx->thread_opaque;
  
      if (!avctx->thread_opaque) return;
  
@@@ -928,17 -907,6 +928,17 @@@ static int *allocate_progress(PerThread
      return p->progress[i];
  }
  
 +int ff_thread_can_start_frame(AVCodecContext *avctx)
 +{
 +    PerThreadContext *p = avctx->thread_opaque;
 +    if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP &&
 +        (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks &&
 +                avctx->get_buffer != avcodec_default_get_buffer))) {
 +        return 0;
 +    }
 +    return 1;
 +}
 +
  int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
  {
      PerThreadContext *p = avctx->thread_opaque;
  
      f->owner = avctx;
  
 +    ff_init_buffer_info(avctx, f);
 +
      if (!(avctx->active_thread_type&FF_THREAD_FRAME)) {
          f->thread_opaque = NULL;
          return avctx->get_buffer(avctx, f);
      }
  
      if (p->state != STATE_SETTING_UP &&
 -        (avctx->codec->update_thread_context || !avctx->thread_safe_callbacks)) {
 +        (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks &&
 +                avctx->get_buffer != avcodec_default_get_buffer))) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n");
          return -1;
      }
          p->requested_frame = f;
          p->state = STATE_GET_BUFFER;
          pthread_mutex_lock(&p->progress_mutex);
 -        pthread_cond_signal(&p->progress_cond);
 +        pthread_cond_broadcast(&p->progress_cond);
  
          while (p->state != STATE_SETTING_UP)
              pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
diff --combined libavdevice/dv1394.h
@@@ -8,20 -8,20 +8,20 @@@
   *   Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
   *                          Peter Schlaile <udbz@rz.uni-karlsruhe.de>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
                reset_dv1394();
           } else {
                int i;
-               for(i = 0; i < status.n_clear_frames; i++) {
+               for (i = 0; i < status.n_clear_frames; i++) {
                    copy_DV_frame();
                }
           }
diff --combined libavformat/rtmppkt.c
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP input format
   * Copyright (c) 2009 Kostya Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -74,15 -74,25 +74,25 @@@ void ff_amf_write_object_end(uint8_t **
  int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
                          int chunk_size, RTMPPacket *prev_pkt)
  {
-     uint8_t hdr, t, buf[16];
+     uint8_t hdr;
+     if (ffurl_read(h, &hdr, 1) != 1)
+         return AVERROR(EIO);
+     return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt, hdr);
+ }
+ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
+                                  RTMPPacket *prev_pkt, uint8_t hdr)
+ {
+     uint8_t t, buf[16];
      int channel_id, timestamp, data_size, offset = 0;
      uint32_t extra = 0;
      enum RTMPPacketType type;
      int size = 0;
      int ret;
  
-     if (ffurl_read(h, &hdr, 1) != 1)
-         return AVERROR(EIO);
      size++;
      channel_id = hdr & 0x3F;
  
diff --combined libavformat/rtmppkt.h
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP packet utilities
   * Copyright (c) 2009 Kostya Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -115,6 -115,19 +115,19 @@@ void ff_rtmp_packet_destroy(RTMPPacket 
   */
  int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
                          int chunk_size, RTMPPacket *prev_pkt);
+ /**
+  * Read internal RTMP packet sent by the server.
+  *
+  * @param h          reader context
+  * @param p          packet
+  * @param chunk_size current chunk size
+  * @param prev_pkt   previously read packet headers for all channels
+  *                   (may be needed for restoring incomplete packet header)
+  * @param c          the first byte already read
+  * @return number of bytes read on success, negative value otherwise
+  */
+ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
+                                  RTMPPacket *prev_pkt, uint8_t c);
  
  /**
   * Send RTMP packet to the server.
diff --combined libavformat/rtmpproto.c
@@@ -2,20 -2,20 +2,20 @@@
   * RTMP network protocol
   * Copyright (c) 2009 Kostya Shishkov
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -998,7 -998,7 +998,7 @@@ static int get_packet(URLContext *s, in
              }
          }
          rt->bytes_read += ret;
 -        if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
 +        if (rt->bytes_read - rt->last_bytes_read > rt->client_report_size) {
              av_log(s, AV_LOG_DEBUG, "Sending bytes read report\n");
              if ((ret = gen_bytes_read(s, rt, rpkt.timestamp + 1)) < 0)
                  return ret;
@@@ -1287,6 -1287,7 +1287,7 @@@ static int rtmp_write(URLContext *s, co
      int pktsize, pkttype;
      uint32_t ts;
      const uint8_t *buf_temp = buf;
+     uint8_t c;
      int ret;
  
      do {
              rt->flv_header_bytes = 0;
          }
      } while (buf_temp - buf < size);
+     /* set stream into nonblocking mode */
+     rt->stream->flags |= AVIO_FLAG_NONBLOCK;
+     /* try to read one byte from the stream */
+     ret = ffurl_read(rt->stream, &c, 1);
+     /* switch the stream back into blocking mode */
+     rt->stream->flags &= ~AVIO_FLAG_NONBLOCK;
+     if (ret == AVERROR(EAGAIN)) {
+         /* no incoming data to handle */
+         return size;
+     } else if (ret < 0) {
+         return ret;
+     } else if (ret == 1) {
+         RTMPPacket rpkt = { 0 };
+         if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
+                                                 rt->chunk_size,
+                                                 rt->prev_pkt[0], c)) <= 0)
+              return ret;
+         if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
+             return ret;
+         ff_rtmp_packet_destroy(&rpkt);
+     }
      return size;
  }