Merge ffmpeg for M41.

Taken from commit 24e7e0237b6eb95a649dc62bd70817a12c6c6ea6

Conflicts:
	doc/t2h.pm
	libavcodec/h264_cabac.c
	libavcodec/utils.c

Change-Id: Ib8bad7f1ffba3c49922a8eacff158c7ae5121847
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..a900528
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.pnm -diff -text
diff --git a/Changelog b/Changelog
index ec6abba..7172d0c 100644
--- a/Changelog
+++ b/Changelog
@@ -9,6 +9,15 @@
 - STL subtitle demuxer and decoder
 - libutvideo YUV 4:2:2 10bit support
 - XCB-based screen-grabber
+- UDP-Lite support (RFC 3828)
+- xBR scaling filter
+- AVFoundation screen capturing support
+- ffserver supports codec private options
+- creating DASH compatible fragmented MP4, MPEG-DASH segmenting muxer
+- WebP muxer with animated WebP support
+- zygoaudio decoding support
+- APNG demuxer
+
 
 version 2.4:
 - Icecast protocol
diff --git a/LICENSE.md b/LICENSE.md
index e0a431b..cf9955f 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -64,6 +64,7 @@
   documentation accompanying your program if you only distribute executables.
   You must also indicate any changes including additions and deletions to
   those three files in the documentation.
+  tests/reference.pnm is under the expat license
 
 
 external libraries
diff --git a/MAINTAINERS b/MAINTAINERS
index 90a4013..15b976f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -386,6 +386,7 @@
   aiffdec.c                             Baptiste Coudurier, Matthieu Bouron
   aiffenc.c                             Baptiste Coudurier, Matthieu Bouron
   ape.c                                 Kostya Shishkov
+  apngdec.c                             Benoit Fouet
   ass*                                  Aurelien Jacobs
   astdec.c                              Paul B Mahol
   astenc.c                              James Almer
@@ -497,6 +498,7 @@
   libssh.c                              Lukasz Marek
   mms*.c                                Ronald S. Bultje
   udp.c                                 Luca Abeni
+  icecast.c                             Marvin Scholz
 
 
 libswresample
diff --git a/README.chromium b/README.chromium
index 4e6f4d2..f91093e 100644
--- a/README.chromium
+++ b/README.chromium
@@ -3,7 +3,7 @@
 License: LGPL 2.1
 License File: LICENSE.md
 Upstream Git: git://source.ffmpeg.org/ffmpeg.git
-Last Upstream Merge: f05855414ed4cce97c06ba2a31f4987af47e6d4e, Oct 29 2014
+Last Upstream Merge: 24e7e0237b6eb95a649dc62bd70817a12c6c6ea6, Dec 1 2014
 
 This file documents the layout of the Chromium copy of FFmpeg git, some common
 tasks, how to produce the FFmpeg include directory, and how to create the
diff --git a/README.md b/README.md
index 182d726..04089e4 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@
 
 ### Examples
 
-Conding examples are available in the **doc/example** directory.
+Coding examples are available in the **doc/examples** directory.
 
 ## License
 
diff --git a/cmdutils.c b/cmdutils.c
index b777396..b68dae9 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -1997,7 +1997,7 @@
             switch (check_stream_specifier(s, st, p + 1)) {
             case  1: *p = 0; break;
             case  0:         continue;
-            default:         return NULL;
+            default:         exit_program(1);
             }
 
         if (av_opt_find(&cc, t->key, NULL, flags, AV_OPT_SEARCH_FAKE_OBJ) ||
diff --git a/configure b/configure
index fae9ca1..d4a86c0 100755
--- a/configure
+++ b/configure
@@ -254,6 +254,7 @@
   --enable-libxcb          enable X11 grabbing using XCB [auto]
   --enable-libxcb-shm      enable X11 grabbing shm communication [auto]
   --enable-libxcb-xfixes   enable X11 grabbing mouse rendering [auto]
+  --enable-libxcb-shape    enable X11 grabbing shape rendering [auto]
   --enable-libxvid         enable Xvid encoding via xvidcore,
                            native MPEG-4/Xvid encoder exists [no]
   --enable-libzmq          enable message passing via libzmq [no]
@@ -1386,6 +1387,7 @@
     libxavs
     libxcb
     libxcb_shm
+    libxcb_shape
     libxcb_xfixes
     libxvid
     libzmq
@@ -1659,6 +1661,7 @@
     sys_un_h
     sys_videoio_h
     termios_h
+    udplite_h
     unistd_h
     windows_h
     winsock2_h
@@ -1677,7 +1680,6 @@
     exp2
     exp2f
     expf
-    fminf
     isinf
     isnan
     ldexpf
@@ -1730,6 +1732,7 @@
     lzo1x_999_compress
     mach_absolute_time
     MapViewOfFile
+    MoveFileExA
     memalign
     mkstemp
     mmap
@@ -2068,6 +2071,7 @@
 amv_decoder_select="sp5x_decoder exif"
 amv_encoder_select="aandcttables mpegvideoenc"
 ape_decoder_select="bswapdsp llauddsp"
+apng_decoder_select="zlib"
 asv1_decoder_select="blockdsp bswapdsp idctdsp"
 asv1_encoder_select="bswapdsp fdctdsp pixblockdsp"
 asv2_decoder_select="blockdsp bswapdsp idctdsp"
@@ -2397,6 +2401,7 @@
 avisynth_demuxer_deps="avisynth"
 avisynth_demuxer_select="riffdec"
 caf_demuxer_select="riffdec"
+dash_muxer_select="mp4_muxer"
 dirac_demuxer_select="dirac_parser"
 dts_demuxer_select="dca_parser"
 dtshd_demuxer_select="dca_parser"
@@ -2542,6 +2547,7 @@
 tls_protocol_deps_any="openssl gnutls"
 tls_protocol_select="tcp_protocol"
 udp_protocol_select="network"
+udplite_protocol_select="network"
 unix_protocol_deps="sys_un_h"
 unix_protocol_select="network"
 
@@ -2564,19 +2570,16 @@
 ebur128_filter_deps="gpl"
 flite_filter_deps="libflite"
 frei0r_filter_deps="frei0r dlopen"
-frei0r_filter_extralibs='$ldl'
 frei0r_src_filter_deps="frei0r dlopen"
-frei0r_src_filter_extralibs='$ldl'
 geq_filter_deps="gpl"
 histeq_filter_deps="gpl"
 hqdn3d_filter_deps="gpl"
 interlace_filter_deps="gpl"
 kerndeint_filter_deps="gpl"
 ladspa_filter_deps="ladspa dlopen"
-ladspa_filter_extralibs='$ldl'
 mcdeint_filter_deps="avcodec gpl"
 movie_filter_deps="avcodec avformat"
-mp_filter_deps="gpl avcodec swscale inline_asm"
+mp_filter_deps="gpl avcodec swscale"
 mpdecimate_filter_deps="gpl"
 mpdecimate_filter_select="pixelutils"
 mptestsrc_filter_deps="gpl"
@@ -3442,29 +3445,6 @@
         # 4509: "This form of conditional instruction is deprecated"
         _flags="-nologo -ignore 4509"
         _flags_filter=armasm_flags
-    elif $_cc 2>&1 | grep -q Microsoft; then
-        _type=msvc
-        _ident=$($cc 2>&1 | head -n1)
-        _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)'
-        _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs'
-        _cflags_speed="-O2"
-        _cflags_size="-O1"
-        if $_cc 2>&1 | grep -q Linker; then
-            _ld_o='-out:$@'
-        else
-            _ld_o='-Fe$@'
-        fi
-        _cc_o='-Fo$@'
-        _cc_e='-P -Fi$@'
-        _flags_filter=msvc_flags
-        _ld_lib='lib%.a'
-        _ld_path='-libpath:'
-        _flags='-nologo'
-        _cflags='-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -Dinline=__inline -FIstdlib.h -Dstrtoll=_strtoi64'
-        if [ $pfx = hostcc ]; then
-            append _cflags -Dsnprintf=_snprintf
-        fi
-        disable stripping
     elif $_cc 2>&1 | grep -q Intel; then
         _type=icl
         _ident=$($cc 2>&1 | head -n1)
@@ -3491,6 +3471,30 @@
         if [ $pfx = hostcc ]; then
             append _cflags -Dsnprintf=_snprintf
         fi
+        disable stripping
+    elif $_cc 2>&1 | grep -q Microsoft; then
+        _type=msvc
+        _ident=$($cc 2>&1 | head -n1)
+        _DEPCMD='$(DEP$(1)) $(DEP$(1)FLAGS) $($(1)DEP_FLAGS) $< 2>&1 | awk '\''/including/ { sub(/^.*file: */, ""); gsub(/\\/, "/"); if (!match($$0, / /)) print "$@:", $$0 }'\'' > $(@:.o=.d)'
+        _DEPFLAGS='$(CPPFLAGS) $(CFLAGS) -showIncludes -Zs'
+        _cflags_speed="-O2"
+        _cflags_size="-O1"
+        if $_cc 2>&1 | grep -q Linker; then
+            _ld_o='-out:$@'
+        else
+            _ld_o='-Fe$@'
+        fi
+        _cc_o='-Fo$@'
+        _cc_e='-P -Fi$@'
+        _flags_filter=msvc_flags
+        _ld_lib='lib%.a'
+        _ld_path='-libpath:'
+        _flags='-nologo'
+        _cflags='-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS -Dinline=__inline -FIstdlib.h -Dstrtoll=_strtoi64'
+        if [ $pfx = hostcc ]; then
+            append _cflags -Dsnprintf=_snprintf
+        fi
+        disable stripping
     elif $_cc --version 2>/dev/null | grep -q ^cparser; then
         _type=cparser
         _ident=$($_cc --version | head -n1)
@@ -3948,6 +3952,9 @@
     ;;
     x86)
         check_64bit x86_32 x86_64 'sizeof(void *) > 4'
+        # Treat x32 as x64 for now. Note it also needs spic=$shared
+        test "$subarch" = "x86_32" && check_cpp_condition stddef.h 'defined(__x86_64__)' &&
+            subarch=x86_64
         if test "$subarch" = "x86_64"; then
             spic=$shared
         fi
@@ -4525,7 +4532,7 @@
 
     if enabled gcc; then
         case $($cc -dumpversion) in
-            4.[3-8].*) check_cflags -fno-optimize-sibling-calls ;;
+            4.[3-9].*) check_cflags -fno-optimize-sibling-calls ;;
         esac
     fi
 
@@ -4641,6 +4648,10 @@
     ldl=-ldl
 fi
 
+frei0r_filter_extralibs='$ldl'
+frei0r_src_filter_extralibs='$ldl'
+ladspa_filter_extralibs='$ldl'
+
 if ! disabled network; then
     check_func getaddrinfo $network_extralibs
     check_func getservbyport $network_extralibs
@@ -4727,6 +4738,7 @@
 check_func_headers windows.h GetProcessTimes
 check_func_headers windows.h GetSystemTimeAsFileTime
 check_func_headers windows.h MapViewOfFile
+check_func_headers windows.h MoveFileExA
 check_func_headers windows.h PeekNamedPipe
 check_func_headers windows.h SetConsoleTextAttribute
 check_func_headers windows.h Sleep
@@ -4745,6 +4757,7 @@
 check_header libcrystalhd/libcrystalhd_if.h
 check_header mach/mach_time.h
 check_header malloc.h
+check_header net/udplite.h
 check_header poll.h
 check_header sys/mman.h
 check_header sys/param.h
@@ -4810,7 +4823,6 @@
 atan2f_args=2
 ldexpf_args=2
 powf_args=2
-fminf_args=2
 
 for func in $MATH_FUNCS; do
     eval check_mathfunc $func \${${func}_args:-1}
@@ -5030,18 +5042,23 @@
     } && disable x11grab && enable libxcb
 
 if enabled libxcb; then
-    disabled libxcb_shm ||
+    disabled libxcb_shm || {
         check_pkg_config xcb-shm xcb/shm.h xcb_shm_attach || {
             enabled libxcb_shm && die "ERROR: libxcb_shm not found";
-        } && check_header sys/shm.h && enable libxcb_shm
+        } && check_header sys/shm.h && enable libxcb_shm; }
 
-    disabled libxcb_xfixes ||
+    disabled libxcb_xfixes || {
         check_pkg_config xcb-xfixes xcb/xfixes.h xcb_xfixes_get_cursor_image || {
             enabled libxcb_xfixes && die "ERROR: libxcb_xfixes not found";
-        } && enable libxcb_xfixes
+        } && enable libxcb_xfixes; }
 
-    add_cflags "$xcb_event_cflags $xcb_shm_cflags $xcb_xfixes_cflags"
-    add_extralibs "$xcb_event_libs $xcb_shm_libs $xcb_xfixes_libs"
+    disabled libxcb_shape || {
+        check_pkg_config xcb-shape xcb/shape.h xcb_shape_get_rectangles || {
+            enabled libxcb_shape && die "ERROR: libxcb_shape not found";
+        } && enable libxcb_shape; }
+
+    add_cflags $xcb_cflags $xcb_shm_cflags $xcb_xfixes_cflags $xcb_shape_cflags
+    add_extralibs $xcb_libs $xcb_shm_libs $xcb_xfixes_libs $xcb_shape_libs
 fi
 fi
 
diff --git a/doc/APIchanges b/doc/APIchanges
index ec9fe06..5915ad3 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,6 +15,24 @@
 
 API changes, most recent first:
 
+2014-11-21 - xxxxxxx - lavu 54.15.100 - dict.h
+   Add av_dict_get_string().
+
+2014-11-18 - xxxxxxx - lavu 54.14.100 - float_dsp.h
+  Add avpriv_float_dsp_alloc().
+
+2014-11-16 - xxxxxxx - lavf 56.13.100 - avformat.h
+  Add AVStream.recommended_encoder_configuration with accessors.
+
+2014-11-16 - xxxxxxx - lavu 54.13.100 - opt.h
+  Add av_opt_serialize().
+
+2014-11-16 - xxxxxxx - lavu 54.12.100 - opt.h
+  Add av_opt_is_set_to_default().
+
+2014-11-xx - xxxxxxx - lavc 56.6.0 - vorbis_parser.h
+  Add a public API for parsing vorbis packets.
+
 2014-10-xx - xxxxxxx - lavc 56.5.0 - avcodec.h
   Replace AVCodecContext.time_base used for decoding
   with AVCodecContext.framerate.
@@ -248,10 +266,10 @@
 2014-05-11 - 14aef38 / 66e6c8a - lavu 52.83.100 / 53.14.0 - pixfmt.h
   Add AV_PIX_FMT_VDA for new-style VDA acceleration.
 
-2014-05-xx - xxxxxxx - lavu 52.82.0 - fifo.h
+2014-05-xx - xxxxxxx - lavu 52.82.100 - fifo.h
   Add av_fifo_freep() function.
 
-2014-05-02 - ba52fb11 - lavu 52.81.0 - opt.h
+2014-05-02 - ba52fb11 - lavu 52.81.100 - opt.h
   Add av_opt_set_dict2() function.
 
 2014-05-01 - e77b985 / a2941c8 - lavc 55.60.103 / 55.50.3 - avcodec.h
@@ -896,6 +914,9 @@
   avresample_read() are now uint8_t** instead of void**.
   Libavresample is now stable.
 
+2012-09-26 - 3ba0dab7 / 1384df64 - lavf 54.29.101 / 56.06.3 - avformat.h
+  Add AVFormatContext.avoid_negative_ts.
+
 2012-09-24 - 46a3595 / a42aada - lavc 54.59.100 / 54.28.0 - avcodec.h
   Add avcodec_free_frame(). This function must now
   be used for freeing an AVFrame.
diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index 58ebddd..6431ce8 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -13,7 +13,16 @@
 The option @code{-bsfs} of the ff* tools will display the list of
 all the supported bitstream filters included in your build.
 
-Below is a description of the currently available bitstream filters.
+The ff* tools have a -bsf option applied per stream, taking a
+comma-separated list of filters, whose parameters follow the filter
+name after a '='.
+
+@example
+ffmpeg -i INPUT -c:v copy -bsf:v filter1[=opt1=str1/opt2=str2][,filter2] OUTPUT
+@end example
+
+Below is a description of the currently available bitstream filters,
+with their parameters, if any.
 
 @section aac_adtstoasc
 
@@ -135,9 +144,16 @@
 Damages the contents of packets without damaging the container. Can be
 used for fuzzing or testing error resilience/concealment.
 
+Parameters:
+A numeral string, whose value is related to how often output bytes will
+be modified. Therefore, values below or equal to 0 are forbidden, and
+the lower the more frequent bytes will be modified, with 1 meaning
+every byte is modified.
+
 @example
-ffmpeg -i INPUT -c copy -bsf noise output.mkv
+ffmpeg -i INPUT -c copy -bsf noise[=1] output.mkv
 @end example
+applies the modification to every byte.
 
 @section remove_extra
 
diff --git a/doc/codecs.texi b/doc/codecs.texi
index 5a1abb8..f1f5c00 100644
--- a/doc/codecs.texi
+++ b/doc/codecs.texi
@@ -71,7 +71,9 @@
 @item global_header
 Place global headers in extradata instead of every keyframe.
 @item bitexact
-Use only bitexact stuff (except (I)DCT).
+Only write platform-, build- and time-independent data. (except (I)DCT).
+This ensures that file and data checksums are reproducible and match between
+platforms. Its primary use is for regression testing.
 @item aic
 Apply H263 advanced intra coding / mpeg4 ac prediction.
 @item cbp
@@ -1114,6 +1116,19 @@
 Set to 1 to disable processing alpha (transparency). This works like the
 @samp{gray} flag in the @option{flags} option which skips chroma information
 instead of alpha. Default is 0.
+
+@item codec_whitelist @var{list} (@emph{input})
+"," separated List of allowed decoders. By default all are allowed.
+
+@item dump_separator @var{string} (@emph{input})
+Separator used to separate the fields printed on the command line about the
+Stream parameters.
+For example to separate the fields with newlines and indention:
+@example
+ffprobe -dump_separator "
+                          "  -i ~/videos/matrixbench_mpeg2.mpg
+@end example
+
 @end table
 
 @c man end CODEC OPTIONS
diff --git a/doc/decoders.texi b/doc/decoders.texi
index ae20cea..01fca9fc 100644
--- a/doc/decoders.texi
+++ b/doc/decoders.texi
@@ -191,6 +191,10 @@
 ee450d, 101010, eaeaea, 0ce60b, ec14ed, ebff0b, 0d617a, 7b7b7b, d1d1d1,
 7b2a0e, 0d950c, 0f007b, cf0dec, cfa80c, 7c127b}.
 
+@item ifo_palette
+Specify the IFO file from which the global palette is obtained.
+(experimental)
+
 @item forced_subs_only
 Only decode subtitle entries marked as forced. Some titles have forced
 and non-forced subtitles in the same track. Setting this flag to @code{1}
diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index e582322..11dfe1b 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -29,6 +29,26 @@
 The total bitrate of the variant that the stream belongs to is
 available in a metadata key named "variant_bitrate".
 
+@section apng
+
+Animated Portable Network Graphics demuxer.
+
+This demuxer is used to demux APNG files.
+All headers, but the PNG signature, up to (but not including) the first
+fcTL chunk are transmitted as extradata.
+Frames are then split as being all the chunks between two fcTL ones, or
+between the last fcTL and IEND chunks.
+
+@table @option
+@item -ignore_loop @var{bool}
+Ignore the loop variable in the file if set.
+@item -max_fps @var{int}
+Maximum framerate in frames per second (0 for no limit).
+@item -default_fps @var{int}
+Default framerate in frames per second when none is specified in the file
+(0 meaning as fast as possible).
+@end table
+
 @section asf
 
 Advanced Systems Format demuxer.
diff --git a/doc/examples/decoding_encoding.c b/doc/examples/decoding_encoding.c
index 556fe98..80da664 100644
--- a/doc/examples/decoding_encoding.c
+++ b/doc/examples/decoding_encoding.c
@@ -288,6 +288,7 @@
     avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
 
     while (avpkt.size > 0) {
+        int i, ch;
         int got_frame = 0;
 
         if (!decoded_frame) {
@@ -304,15 +305,15 @@
         }
         if (got_frame) {
             /* if a frame has been decoded, output it */
-            int data_size = av_samples_get_buffer_size(NULL, c->channels,
-                                                       decoded_frame->nb_samples,
-                                                       c->sample_fmt, 1);
+            int data_size = av_get_bytes_per_sample(c->sample_fmt);
             if (data_size < 0) {
                 /* This should not occur, checking just for paranoia */
                 fprintf(stderr, "Failed to calculate data size\n");
                 exit(1);
             }
-            fwrite(decoded_frame->data[0], 1, data_size, outfile);
+            for (i=0; i<decoded_frame->nb_samples; i++)
+                for (ch=0; ch<c->channels; ch++)
+                    fwrite(decoded_frame->data[ch] + data_size*i, 1, data_size, outfile);
         }
         avpkt.size -= len;
         avpkt.data += len;
@@ -650,7 +651,7 @@
         video_encode_example("test.h264", AV_CODEC_ID_H264);
     } else if (!strcmp(output_type, "mp2")) {
         audio_encode_example("test.mp2");
-        audio_decode_example("test.sw", "test.mp2");
+        audio_decode_example("test.pcm", "test.mp2");
     } else if (!strcmp(output_type, "mpg")) {
         video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO);
         video_decode_example("test%02d.pgm", "test.mpg");
diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c
index cee447f..e98c217 100644
--- a/doc/examples/transcode_aac.c
+++ b/doc/examples/transcode_aac.c
@@ -306,7 +306,7 @@
 
     /** Read one audio frame from the input file into a temporary packet. */
     if ((error = av_read_frame(input_format_context, &input_packet)) < 0) {
-        /** If we are the the end of the file, flush the decoder below. */
+        /** If we are at the end of the file, flush the decoder below. */
         if (error == AVERROR_EOF)
             *finished = 1;
         else {
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 38dca86..d774aba 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -360,7 +360,7 @@
 @end example
 
 @item -dframes @var{number} (@emph{output})
-Set the number of data frames to record. This is an alias for @code{-frames:d}.
+Set the number of data frames to output. This is an alias for @code{-frames:d}.
 
 @item -frames[:@var{stream_specifier}] @var{framecount} (@emph{output,per-stream})
 Stop writing to the stream after @var{framecount} frames.
@@ -467,7 +467,7 @@
 
 @table @option
 @item -vframes @var{number} (@emph{output})
-Set the number of video frames to record. This is an alias for @code{-frames:v}.
+Set the number of video frames to output. This is an alias for @code{-frames:v}.
 @item -r[:@var{stream_specifier}] @var{fps} (@emph{input/output,per-stream})
 Set frame rate (Hz value, fraction or abbreviation).
 
@@ -692,7 +692,7 @@
 
 @table @option
 @item -aframes @var{number} (@emph{output})
-Set the number of audio frames to record. This is an alias for @code{-frames:a}.
+Set the number of audio frames to output. This is an alias for @code{-frames:a}.
 @item -ar[:@var{stream_specifier}] @var{freq} (@emph{input/output,per-stream})
 Set the audio sampling frequency. For output streams it is set by
 default to the frequency of the corresponding input stream. For input
diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
index f4d679e..c2cab37 100644
--- a/doc/ffprobe.xsd
+++ b/doc/ffprobe.xsd
@@ -13,6 +13,7 @@
             <xsd:element name="pixel_formats"    type="ffprobe:pixelFormatsType"    minOccurs="0" maxOccurs="1" />
             <xsd:element name="packets"  type="ffprobe:packetsType" minOccurs="0" maxOccurs="1" />
             <xsd:element name="frames"   type="ffprobe:framesType"  minOccurs="0" maxOccurs="1" />
+            <xsd:element name="packets_and_frames" type="ffprobe:packetsAndFramesType" minOccurs="0" maxOccurs="1" />
             <xsd:element name="programs" type="ffprobe:programsType" minOccurs="0" maxOccurs="1" />
             <xsd:element name="streams"  type="ffprobe:streamsType" minOccurs="0" maxOccurs="1" />
             <xsd:element name="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" />
@@ -36,6 +37,16 @@
         </xsd:sequence>
     </xsd:complexType>
 
+    <xsd:complexType name="packetsAndFramesType">
+        <xsd:sequence>
+            <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                <xsd:element name="packet" type="ffprobe:packetType" minOccurs="0" maxOccurs="unbounded"/>
+                <xsd:element name="frame" type="ffprobe:frameType" minOccurs="0" maxOccurs="unbounded"/>
+                <xsd:element name="subtitle" type="ffprobe:subtitleType" minOccurs="0" maxOccurs="unbounded"/>
+            </xsd:choice>
+        </xsd:sequence>
+    </xsd:complexType>
+
     <xsd:complexType name="packetType">
       <xsd:attribute name="codec_type"    type="xsd:string" use="required" />
       <xsd:attribute name="stream_index"  type="xsd:int" use="required" />
diff --git a/doc/ffserver.texi b/doc/ffserver.texi
index 77273d2..83b6520 100644
--- a/doc/ffserver.texi
+++ b/doc/ffserver.texi
@@ -408,6 +408,12 @@
 Set no-daemon mode. This option is currently ignored since now
 @command{ffserver} will always work in no-daemon mode, and is
 deprecated.
+
+@item UseDefaults
+@item NoDefaults
+Control whether default codec options are used for the all streams or not.
+Each stream may overwrite this setting for its own. Default is @var{UseDefaults}.
+The lastest occurrence overrides previous if multiple definitions.
 @end table
 
 @section Feed section
@@ -571,6 +577,11 @@
 @item Metadata @var{key} @var{value}
 Set metadata value on the output stream.
 
+@item UseDefaults
+@item NoDefaults
+Control whether default codec options are used for the stream or not.
+Default is @var{UseDefaults} unless disabled globally.
+
 @item NoAudio
 @item NoVideo
 Suppress audio/video.
@@ -589,8 +600,9 @@
 lower this frequency to 22050 or 11025. The supported frequencies
 depend on the selected audio codec.
 
-@item AVOptionAudio @var{option} @var{value} (@emph{encoding,audio})
-Set generic option for audio stream.
+@item AVOptionAudio [@var{codec}:]@var{option} @var{value} (@emph{encoding,audio})
+Set generic or private option for audio stream.
+Private option must be prefixed with codec name or codec must be defined before.
 
 @item AVPresetAudio @var{preset} (@emph{encoding,audio})
 Set preset for audio stream.
@@ -667,8 +679,9 @@
 @item DarkMask @var{float} (@emph{encoding,video})
 Set @option{lumi_mask}/@option{dark_mask} encoding options.
 
-@item AVOptionVideo @var{option} @var{value} (@emph{encoding,video})
-Set generic option for video stream.
+@item AVOptionVideo [@var{codec}:]@var{option} @var{value} (@emph{encoding,video})
+Set generic or private option for video stream.
+Private option must be prefixed with codec name or codec must be defined before.
 
 @item AVPresetVideo @var{preset} (@emph{encoding,video})
 Set preset for video stream.
diff --git a/doc/filters.texi b/doc/filters.texi
index 7be29de..8c16c7a 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1710,11 +1710,11 @@
 Mix channels with specific gain levels. The filter accepts the output
 channel layout followed by a set of channels definitions.
 
-This filter is also designed to remap efficiently the channels of an audio
+This filter is also designed to efficiently remap the channels of an audio
 stream.
 
 The filter accepts parameters of the form:
-"@var{l}:@var{outdef}:@var{outdef}:..."
+"@var{l}|@var{outdef}|@var{outdef}|..."
 
 @table @option
 @item l
@@ -1745,13 +1745,13 @@
 For example, if you want to down-mix from stereo to mono, but with a bigger
 factor for the left channel:
 @example
-pan=1:c0=0.9*c0+0.1*c1
+pan=1c|c0=0.9*c0+0.1*c1
 @end example
 
 A customized down-mix to stereo that works automatically for 3-, 4-, 5- and
 7-channels surround:
 @example
-pan=stereo: FL < FL + 0.5*FC + 0.6*BL + 0.6*SL : FR < FR + 0.5*FC + 0.6*BR + 0.6*SR
+pan=stereo| FL < FL + 0.5*FC + 0.6*BL + 0.6*SL | FR < FR + 0.5*FC + 0.6*BR + 0.6*SR
 @end example
 
 Note that @command{ffmpeg} integrates a default down-mix (and up-mix) system
@@ -1774,25 +1774,25 @@
 For example, if you have a 5.1 source and want a stereo audio stream by
 dropping the extra channels:
 @example
-pan="stereo: c0=FL : c1=FR"
+pan="stereo| c0=FL | c1=FR"
 @end example
 
 Given the same source, you can also switch front left and front right channels
 and keep the input channel layout:
 @example
-pan="5.1: c0=c1 : c1=c0 : c2=c2 : c3=c3 : c4=c4 : c5=c5"
+pan="5.1| c0=c1 | c1=c0 | c2=c2 | c3=c3 | c4=c4 | c5=c5"
 @end example
 
 If the input is a stereo audio stream, you can mute the front left channel (and
 still keep the stereo channel layout) with:
 @example
-pan="stereo:c1=c1"
+pan="stereo|c1=c1"
 @end example
 
 Still with a stereo audio stream input, you can copy the right channel in both
 front left and right:
 @example
-pan="stereo: c0=FR : c1=FR"
+pan="stereo| c0=FR | c1=FR"
 @end example
 
 @section replaygain
@@ -5574,12 +5574,21 @@
 
 Detect video interlacing type.
 
-This filter tries to detect if the input is interlaced or progressive,
-top or bottom field first.
+This filter tries to detect if the input frames as interlaced, progressive,
+top or bottom field first. It will also try and detect fields that are
+repeated between adjacent frames (a sign of telecine).
+
+Single frame detection considers only immediately adjacent frames when classifying each frame.
+Multiple frame detection incorporates the classification history of previous frames.
 
 The filter will log these metadata values:
 
 @table @option
+@item single.current_frame
+Detected type of current frame using single-frame detection. One of:
+``tff'' (top field first), ``bff'' (bottom field first),
+``progressive'', or ``undetermined''
+
 @item single.tff
 Cumulative number of frames detected as top field first using single-frame detection.
 
@@ -5589,6 +5598,11 @@
 @item single.bff
 Cumulative number of frames detected as bottom field first using single-frame detection.
 
+@item multiple.current_frame
+Detected type of current frame using multiple-frame detection. One of:
+``tff'' (top field first), ``bff'' (bottom field first),
+``progressive'', or ``undetermined''
+
 @item multiple.bff
 Cumulative number of frames detected as bottom field first using multiple-frame detection.
 
@@ -5603,6 +5617,18 @@
 
 @item multiple.undetermined
 Cumulative number of frames that could not be classified using multiple-frame detection.
+
+@item repeated.current_frame
+Which field in the current frame is repeated from the last. One of ``neither'', ``top'', or ``bottom''.
+
+@item repeated.neither
+Cumulative number of frames with no repeated field.
+
+@item repeated.top
+Cumulative number of frames with the top field repeated from the previous frame's top field.
+
+@item repeated.bottom
+Cumulative number of frames with the bottom field repeated from the previous frame's bottom field.
 @end table
 
 The filter accepts the following options:
@@ -5612,6 +5638,13 @@
 Set interlacing threshold.
 @item prog_thres
 Set progressive threshold.
+@item repeat_thres
+Threshold for repeated field detection.
+@item half_life
+Number of frames after which a given frame's contribution to the
+statistics is halved (i.e., it contributes only 0.5 to it's
+classification). The default of 0 means that all frames seen are given
+full weight of 1.0 forever.
 @end table
 
 @section il
@@ -9163,6 +9196,20 @@
 Default value is @samp{all}.
 @end table
 
+@section xbr
+Apply the xBR high-quality magnification filter which is designed for pixel
+art. It follows a set of edge-detection rules, see
+@url{http://www.libretro.com/forums/viewtopic.php?f=6&t=134}.
+
+It accepts the following option:
+
+@table @option
+@item n
+Set the scaling dimension: @code{2} for @code{2xBR}, @code{3} for
+@code{3xBR} and @code{4} for @code{4xBR}.
+Default is @code{3}.
+@end table
+
 @anchor{yadif}
 @section yadif
 
diff --git a/doc/formats.texi b/doc/formats.texi
index 027510e..4138709 100644
--- a/doc/formats.texi
+++ b/doc/formats.texi
@@ -55,6 +55,10 @@
 Enable RTP MP4A-LATM payload.
 @item nobuffer
 Reduce the latency introduced by optional buffering
+@item bitexact
+Only write platform-, build- and time-independent data.
+This ensures that file and data checksums are reproducible and match between
+platforms. Its primary use is for regression testing.
 @end table
 
 @item seek2any @var{integer} (@emph{input})
@@ -168,6 +172,18 @@
 Specifying a positive offset means that the corresponding streams are
 delayed bt the time duration specified in @var{offset}. Default value
 is @code{0} (meaning that no offset is applied).
+
+@item format_whitelist @var{list} (@emph{input})
+"," separated List of allowed demuxers. By default all are allowed.
+
+@item dump_separator @var{string} (@emph{input})
+Separator used to separate the fields printed on the command line about the
+Stream parameters.
+For example to separate the fields with newlines and indention:
+@example
+ffprobe -dump_separator "
+                          "  -i ~/videos/matrixbench_mpeg2.mpg
+@end example
 @end table
 
 @c man end FORMAT OPTIONS
diff --git a/doc/indevs.texi b/doc/indevs.texi
index 99e1112..ad823ab 100644
--- a/doc/indevs.texi
+++ b/doc/indevs.texi
@@ -58,34 +58,94 @@
 AVFoundation is the currently recommended framework by Apple for streamgrabbing on OSX >= 10.7 as well as on iOS.
 The older QTKit framework has been marked deprecated since OSX version 10.7.
 
-The filename passed as input is parsed to contain either a device name or index.
-The device index can also be given by using -video_device_index.
-A given device index will override any given device name.
-If the desired device consists of numbers only, use -video_device_index to identify it.
-The default device will be chosen if an empty string  or the device name "default" is given.
-The available devices can be enumerated by using -list_devices.
-The pixel format can be set using -pixel_format.
-Available formats:
- monob, rgb555be, rgb555le, rgb565be, rgb565le, rgb24, bgr24, 0rgb, bgr0, 0bgr, rgb0,
+The input filename has to be given in the following syntax:
+@example
+-i "[[VIDEO]:[AUDIO]]"
+@end example
+The first entry selects the video input while the latter selects the audio input.
+The stream has to be specified by the device name or the device index as shown by the device list.
+Alternatively, the video and/or audio input device can be chosen by index using the
+@option{
+    -video_device_index <INDEX>
+}
+and/or
+@option{
+    -audio_device_index <INDEX>
+}
+, overriding any
+device name or index given in the input filename.
+
+All available devices can be enumerated by using @option{-list_devices true}, listing
+all device names and corresponding indices.
+
+There are two device name aliases:
+@table @code
+
+@item default
+Select the AVFoundation default device of the corresponding type.
+
+@item none
+Do not record the corresponding media type.
+This is equivalent to specifying an empty device name or index.
+
+@end table
+
+@subsection Options
+
+AVFoundation supports the following options:
+
+@table @option
+
+@item -list_devices <TRUE|FALSE>
+If set to true, a list of all available input devices is given showing all
+device names and indices.
+
+@item -video_device_index <INDEX>
+Specify the video device by its index. Overrides anything given in the input filename.
+
+@item -audio_device_index <INDEX>
+Specify the audio device by its index. Overrides anything given in the input filename.
+
+@item -pixel_format <FORMAT>
+Request the video device to use a specific pixel format.
+If the specified format is not supported, a list of available formats is given
+und the first one in this list is used instead. Available pixel formats are:
+@code{monob, rgb555be, rgb555le, rgb565be, rgb565le, rgb24, bgr24, 0rgb, bgr0, 0bgr, rgb0,
  bgr48be, uyvy422, yuva444p, yuva444p16le, yuv444p, yuv422p16, yuv422p10, yuv444p10,
- yuv420p, nv12, yuyv422, gray
+ yuv420p, nv12, yuyv422, gray}
 
+@end table
+
+@subsection Examples
+
+@itemize
+
+@item
+Print the list of AVFoundation supported devices and exit:
 @example
-ffmpeg -f avfoundation -i "0" out.mpg
+$ ffmpeg -f avfoundation -list_devices true -i ""
 @end example
 
+@item
+Record video from video device 0 and audio from audio device 0 into out.avi:
 @example
-ffmpeg -f avfoundation -video_device_index 0 -i "" out.mpg
+$ ffmpeg -f avfoundation -i "0:0" out.avi
 @end example
 
+@item
+Record video from video device 2 and audio from audio device 1 into out.avi:
 @example
-ffmpeg -f avfoundation -pixel_format bgr0 -i "default" out.mpg
+$ ffmpeg -f avfoundation -video_device_index 2 -i ":1" out.avi
 @end example
 
+@item
+Record video from the system default video device using the pixel format bgr0 and do not record any audio into out.avi:
 @example
-ffmpeg -f avfoundation -list_devices true -i ""
+$ ffmpeg -f avfoundation -pixel_format bgr0 -i "default:none" out.avi
 @end example
 
+@end itemize
+
 @section bktr
 
 BSD video input device.
diff --git a/doc/muxers.texi b/doc/muxers.texi
index cacc46c..c6ba604 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -559,7 +559,6 @@
 mdat atom, and the moov atom only describes the tracks but has
 a zero duration.
 
-Files written with this option set do not work in QuickTime.
 This option is implicitly set when writing ismv (Smooth Streaming) files.
 @item -movflags separate_moof
 Write a separate moof (movie fragment) atom for each track. Normally,
@@ -580,6 +579,16 @@
 set, only the QuickTime chapter track will be written. Nero chapters can
 cause failures when the file is reprocessed with certain tagging programs, like
 mp3Tag 2.61a and iTunes 11.3, most likely other versions are affected as well.
+@item -movflags omit_tfhd_offset
+Do not write any absolute base_data_offset in tfhd atoms. This avoids
+tying fragments to absolute byte positions in the file/streams.
+@item -movflags default_base_moof
+Similarly to the omit_tfhd_offset, this flag avoids writing the
+absolute base_data_offset field in tfhd atoms, but does so by using
+the new default-base-is-moof flag instead. This flag is new from
+14496-12:2012. This may make the fragments easier to parse in certain
+circumstances (avoiding basing track fragment location calculations
+on the implicit end of the previous track fragment).
 @end table
 
 @subsection Example
diff --git a/doc/print_options.c b/doc/print_options.c
index ec8d839..9fd66ca 100644
--- a/doc/print_options.c
+++ b/doc/print_options.c
@@ -26,6 +26,10 @@
 #include <string.h>
 #include <float.h>
 
+// print_options is build for the host, os_support.h isn't needed and is setup
+// for the target. without this build breaks on mingw
+#define AVFORMAT_OS_SUPPORT_H
+
 #include "libavformat/avformat.h"
 #include "libavformat/options_table.h"
 #include "libavcodec/avcodec.h"
diff --git a/doc/protocols.texi b/doc/protocols.texi
index dc2fdb1..d165bda 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -750,7 +750,7 @@
 
 @item
 If @option{localrtcpport} (the local RTCP port) is not set it will be
-set to the the local RTP port value plus 1.
+set to the local RTP port value plus 1.
 @end enumerate
 
 @section rtsp
diff --git a/doc/writing_filters.txt b/doc/writing_filters.txt
index c7923e8..eb16d42 100644
--- a/doc/writing_filters.txt
+++ b/doc/writing_filters.txt
@@ -16,16 +16,15 @@
 similar filter.  We'll pick edgedetect, but any other should do. You can look
 for others using the `./ffmpeg -v 0 -filters|grep ' V->V '` command.
 
- - cp libavfilter/vf_{edgedetect,foobar}.c
- - sed -i s/edgedetect/foobar/g -i libavfilter/vf_foobar.c
- - sed -i s/EdgeDetect/Foobar/g -i libavfilter/vf_foobar.c
+ - sed 's/edgedetect/foobar/g;s/EdgeDetect/Foobar/g' libavfilter/vf_edgedetect.c > libavfilter/vf_foobar.c
  - edit libavfilter/Makefile, and add an entry for "foobar" following the
    pattern of the other filters.
  - edit libavfilter/allfilters.c, and add an entry for "foobar" following the
    pattern of the other filters.
  - ./configure ...
  - make -j<whatever> ffmpeg
- - ./ffmpeg -i tests/lena.pnm -vf foobar foobar.png
+ - ./ffmpeg -i http://samples.ffmpeg.org/image-samples/lena.pnm -vf foobar foobar.png
+   Note here: you can obviously use a random local image instead of a remote URL.
 
 If everything went right, you should get a foobar.png with Lena edge-detected.
 
diff --git a/ffmpeg.c b/ffmpeg.c
index 1fd0ece..b44401f 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -475,6 +475,7 @@
         }
         ost->bitstream_filters = NULL;
         av_frame_free(&ost->filtered_frame);
+        av_frame_free(&ost->last_frame);
 
         av_parser_close(ost->parser);
 
@@ -622,7 +623,11 @@
 
     while (bsfc) {
         AVPacket new_pkt = *pkt;
-        int a = av_bitstream_filter_filter(bsfc, avctx, NULL,
+        AVDictionaryEntry *bsf_arg = av_dict_get(ost->bsf_args,
+                                                 bsfc->filter->name,
+                                                 NULL, 0);
+        int a = av_bitstream_filter_filter(bsfc, avctx,
+                                           bsf_arg ? bsf_arg->value : NULL,
                                            &new_pkt.data, &new_pkt.size,
                                            pkt->data, pkt->size,
                                            pkt->flags & AV_PKT_FLAG_KEY);
@@ -874,14 +879,14 @@
 
 static void do_video_out(AVFormatContext *s,
                          OutputStream *ost,
-                         AVFrame *in_picture)
+                         AVFrame *next_picture)
 {
     int ret, format_video_sync;
     AVPacket pkt;
     AVCodecContext *enc = ost->enc_ctx;
     AVCodecContext *mux_enc = ost->st->codec;
-    int nb_frames, i;
-    double sync_ipts, delta;
+    int nb_frames, nb0_frames, i;
+    double sync_ipts, delta, delta0;
     double duration = 0;
     int frame_size = 0;
     InputStream *ist = NULL;
@@ -892,10 +897,20 @@
     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));
 
-    sync_ipts = in_picture->pts;
-    delta = sync_ipts - ost->sync_opts + duration;
+    if (!ost->filters_script &&
+        !ost->filters &&
+        next_picture &&
+        ist &&
+        lrintf(av_frame_get_pkt_duration(next_picture) * av_q2d(ist->st->time_base) / av_q2d(enc->time_base)) > 0) {
+        duration = lrintf(av_frame_get_pkt_duration(next_picture) * av_q2d(ist->st->time_base) / av_q2d(enc->time_base));
+    }
+
+    sync_ipts = next_picture->pts;
+    delta0 = sync_ipts - ost->sync_opts;
+    delta  = delta0 + duration;
 
     /* by default, we output a single frame */
+    nb0_frames = 0;
     nb_frames = 1;
 
     format_video_sync = video_sync_method;
@@ -915,19 +930,34 @@
         }
     }
 
+    if (delta0 < 0 &&
+        delta > 0 &&
+        format_video_sync != VSYNC_PASSTHROUGH &&
+        format_video_sync != VSYNC_DROP) {
+        double cor = FFMIN(-delta0, duration);
+        av_log(NULL, AV_LOG_WARNING, "Past duration %f too large\n", -delta0);
+        sync_ipts += cor;
+        duration -= cor;
+        delta0 += cor;
+    }
+
     switch (format_video_sync) {
     case VSYNC_VSCFR:
         if (ost->frame_number == 0 && delta - duration >= 0.5) {
             av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta - duration));
             delta = duration;
+            delta0 = 0;
             ost->sync_opts = lrint(sync_ipts);
         }
     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)
+        else if (delta > 1.1) {
             nb_frames = lrintf(delta);
+            if (delta0 > 1.1)
+                nb0_frames = lrintf(delta0 - 0.6);
+        }
         break;
     case VSYNC_VFR:
         if (delta <= -0.6)
@@ -944,28 +974,36 @@
     }
 
     nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
-    if (nb_frames == 0) {
+    nb0_frames = FFMIN(nb0_frames, nb_frames);
+    if (nb0_frames == 0 && ost->last_droped) {
         nb_frames_drop++;
         av_log(NULL, AV_LOG_VERBOSE,
                "*** dropping frame %d from stream %d at ts %"PRId64"\n",
-               ost->frame_number, ost->st->index, in_picture->pts);
-        return;
-    } else if (nb_frames > 1) {
+               ost->frame_number, ost->st->index, ost->last_frame->pts);
+    }
+    if (nb_frames > (nb0_frames && ost->last_droped) + (nb_frames > nb0_frames)) {
         if (nb_frames > dts_error_threshold * 30) {
             av_log(NULL, AV_LOG_ERROR, "%d frame duplication too large, skipping\n", nb_frames - 1);
             nb_frames_drop++;
             return;
         }
-        nb_frames_dup += nb_frames - 1;
+        nb_frames_dup += nb_frames - (nb0_frames && ost->last_droped) - (nb_frames > nb0_frames);
         av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
     }
+    ost->last_droped = nb_frames == nb0_frames;
 
   /* duplicates frame if needed */
   for (i = 0; i < nb_frames; i++) {
+    AVFrame *in_picture;
     av_init_packet(&pkt);
     pkt.data = NULL;
     pkt.size = 0;
 
+    if (i < nb0_frames && ost->last_frame) {
+        in_picture = ost->last_frame;
+    } else
+        in_picture = next_picture;
+
     in_picture->pts = ost->sync_opts;
 
 #if 1
@@ -1103,6 +1141,11 @@
     if (vstats_filename && frame_size)
         do_video_stats(ost, frame_size);
   }
+
+    if (!ost->last_frame)
+        ost->last_frame = av_frame_alloc();
+    av_frame_unref(ost->last_frame);
+    av_frame_ref(ost->last_frame, next_picture);
 }
 
 static double psnr(double d)
@@ -1271,7 +1314,6 @@
     if (data_size && total_size>0 && total_size >= data_size)
         percent = 100.0 * (total_size - data_size) / data_size;
 
-    av_log(NULL, AV_LOG_INFO, "\n");
     av_log(NULL, AV_LOG_INFO, "video:%1.0fkB audio:%1.0fkB subtitle:%1.0fkB other streams:%1.0fkB global headers:%1.0fkB muxing overhead: ",
            video_size / 1024.0,
            audio_size / 1024.0,
@@ -1462,6 +1504,8 @@
         if (av_stream_get_end_pts(ost->st) != AV_NOPTS_VALUE)
             pts = FFMAX(pts, av_rescale_q(av_stream_get_end_pts(ost->st),
                                           ost->st->time_base, AV_TIME_BASE_Q));
+        if (is_last_report)
+            nb_frames_drop += ost->last_droped;
     }
 
     secs = pts / AV_TIME_BASE;
@@ -1497,10 +1541,11 @@
     av_bprintf(&buf_script, "drop_frames=%d\n", nb_frames_drop);
 
     if (print_stats || is_last_report) {
+        const char end = is_last_report ? '\n' : '\r';
         if (print_stats==1 && AV_LOG_INFO > av_log_get_level()) {
-            fprintf(stderr, "%s    \r", buf);
+            fprintf(stderr, "%s    %c", buf, end);
         } else
-            av_log(NULL, AV_LOG_INFO, "%s    \r", buf);
+            av_log(NULL, AV_LOG_INFO, "%s    %c", buf, end);
 
     fflush(stderr);
     }
@@ -1907,6 +1952,20 @@
     if (*got_output || ret<0 || pkt->size)
         decode_error_stat[ret<0] ++;
 
+    if (*got_output && ret >= 0) {
+        if (ist->dec_ctx->width  != decoded_frame->width ||
+            ist->dec_ctx->height != decoded_frame->height ||
+            ist->dec_ctx->pix_fmt != decoded_frame->format) {
+            av_log(NULL, AV_LOG_DEBUG, "Frame parameters mismatch context %d,%d,%d != %d,%d,%d\n",
+                decoded_frame->width,
+                decoded_frame->height,
+                decoded_frame->format,
+                ist->dec_ctx->width,
+                ist->dec_ctx->height,
+                ist->dec_ctx->pix_fmt);
+        }
+    }
+
     if (!*got_output || ret < 0) {
         if (!pkt->size) {
             for (i = 0; i < ist->nb_filters; i++)
@@ -3779,6 +3838,7 @@
                 av_dict_free(&ost->encoder_opts);
                 av_dict_free(&ost->swr_opts);
                 av_dict_free(&ost->resample_opts);
+                av_dict_free(&ost->bsf_args);
             }
         }
     }
diff --git a/ffmpeg.h b/ffmpeg.h
index c456603..117a35c 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -388,6 +388,8 @@
     AVCodec *enc;
     int64_t max_frames;
     AVFrame *filtered_frame;
+    AVFrame *last_frame;
+    int last_droped;
 
     /* video only */
     AVRational frame_rate;
@@ -420,6 +422,7 @@
     AVDictionary *encoder_opts;
     AVDictionary *swr_opts;
     AVDictionary *resample_opts;
+    AVDictionary *bsf_args;
     char *apad;
     OSTFinished finished;        /* no more packets should be written for this stream */
     int unavailable;                     /* true if the steram is unavailable (possibly temporarily) */
@@ -481,6 +484,7 @@
 extern int do_hex_dump;
 extern int do_pkt_dump;
 extern int copy_ts;
+extern int start_at_zero;
 extern int copy_tb;
 extern int debug_ts;
 extern int exit_on_error;
diff --git a/ffmpeg_filter.c b/ffmpeg_filter.c
index 2ba2d9b..264840b 100644
--- a/ffmpeg_filter.c
+++ b/ffmpeg_filter.c
@@ -619,6 +619,7 @@
     ist->sub2video.frame = av_frame_alloc();
     if (!ist->sub2video.frame)
         return AVERROR(ENOMEM);
+    ist->sub2video.last_pts = INT64_MIN;
     return 0;
 }
 
@@ -636,6 +637,7 @@
     AVBPrint args;
     char name[255];
     int ret, pad_idx = 0;
+    int64_t tsoffset = 0;
 
     if (ist->dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
         av_log(NULL, AV_LOG_ERROR, "Cannot connect video filter to audio input\n");
@@ -710,8 +712,14 @@
 
     snprintf(name, sizeof(name), "trim for input stream %d:%d",
              ist->file_index, ist->st->index);
+    if (copy_ts) {
+        tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time;
+        if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE)
+            tsoffset += f->ctx->start_time;
+    }
     ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ?
-                      AV_NOPTS_VALUE : 0, f->recording_time, &last_filter, &pad_idx, name);
+                      AV_NOPTS_VALUE : tsoffset, f->recording_time,
+                      &last_filter, &pad_idx, name);
     if (ret < 0)
         return ret;
 
@@ -730,6 +738,7 @@
     AVBPrint args;
     char name[255];
     int ret, pad_idx = 0;
+    int64_t tsoffset = 0;
 
     if (ist->dec_ctx->codec_type != AVMEDIA_TYPE_AUDIO) {
         av_log(NULL, AV_LOG_ERROR, "Cannot connect audio filter to non audio input\n");
@@ -812,8 +821,14 @@
 
     snprintf(name, sizeof(name), "trim for input stream %d:%d",
              ist->file_index, ist->st->index);
+    if (copy_ts) {
+        tsoffset = f->start_time == AV_NOPTS_VALUE ? 0 : f->start_time;
+        if (!start_at_zero && f->ctx->start_time != AV_NOPTS_VALUE)
+            tsoffset += f->ctx->start_time;
+    }
     ret = insert_trim(((f->start_time == AV_NOPTS_VALUE) || !f->accurate_seek) ?
-                      AV_NOPTS_VALUE : 0, f->recording_time, &last_filter, &pad_idx, name);
+                      AV_NOPTS_VALUE : tsoffset, f->recording_time,
+                      &last_filter, &pad_idx, name);
     if (ret < 0)
         return ret;
 
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index 27e0890..1f281f6 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -704,7 +704,7 @@
             MATCH_PER_STREAM_OPT(fix_sub_duration, i, ist->fix_sub_duration, ic, st);
             MATCH_PER_STREAM_OPT(canvas_sizes, str, canvas_size, ic, st);
             if (canvas_size &&
-                av_parse_video_size(&dec->width, &dec->height, canvas_size) < 0) {
+                av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, canvas_size) < 0) {
                 av_log(NULL, AV_LOG_FATAL, "Invalid canvas size: %s.\n", canvas_size);
                 exit_program(1);
             }
@@ -794,6 +794,7 @@
     char *   video_codec_name = NULL;
     char *   audio_codec_name = NULL;
     char *subtitle_codec_name = NULL;
+    int scan_all_pmts_set = 0;
 
     if (o->format) {
         if (!(file_iformat = av_find_input_format(o->format))) {
@@ -864,12 +865,18 @@
     ic->flags |= AVFMT_FLAG_NONBLOCK;
     ic->interrupt_callback = int_cb;
 
+    if (!av_dict_get(o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
+        av_dict_set(&o->g->format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
+        scan_all_pmts_set = 1;
+    }
     /* open the input file with generic avformat function */
     err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);
     if (err < 0) {
         print_error(filename, err);
         exit_program(1);
     }
+    if (scan_all_pmts_set)
+        av_dict_set(&o->g->format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
     remove_avoptions(&o->g->format_opts, o->g->codec_opts);
     assert_avoptions(o->g->format_opts);
 
@@ -1131,8 +1138,11 @@
 
     MATCH_PER_STREAM_OPT(bitstream_filters, str, bsf, oc, st);
     while (bsf) {
+        char *arg = NULL;
         if (next = strchr(bsf, ','))
             *next++ = 0;
+        if (arg = strchr(bsf, '='))
+            *arg++ = 0;
         if (!(bsfc = av_bitstream_filter_init(bsf))) {
             av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf);
             exit_program(1);
@@ -1141,6 +1151,7 @@
             bsfc_prev->next = bsfc;
         else
             ost->bitstream_filters = bsfc;
+        av_dict_set(&ost->bsf_args, bsfc->filter->name, arg, 0);
 
         bsfc_prev = bsfc;
         bsf       = next;
@@ -1624,31 +1635,36 @@
         AVStream *st;
         OutputStream *ost;
         AVCodec *codec;
-        AVCodecContext *avctx;
+        const char *enc_config;
 
         codec = avcodec_find_encoder(ic->streams[i]->codec->codec_id);
         if (!codec) {
             av_log(s, AV_LOG_ERROR, "no encoder found for codec id %i\n", ic->streams[i]->codec->codec_id);
             return AVERROR(EINVAL);
         }
+        if (codec->type == AVMEDIA_TYPE_AUDIO)
+            opt_audio_codec(o, "c:a", codec->name);
+        else if (codec->type == AVMEDIA_TYPE_VIDEO)
+            opt_video_codec(o, "c:v", codec->name);
         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);
+        avcodec_get_context_defaults3(st->codec, codec);
+        enc_config = av_stream_get_recommended_encoder_configuration(ic->streams[i]);
+        if (enc_config) {
+            AVDictionary *opts = NULL;
+            av_dict_parse_string(&opts, enc_config, "=", ",", 0);
+            av_opt_set_dict2(st->codec, &opts, AV_OPT_SEARCH_CHILDREN);
+            av_dict_free(&opts);
+        }
 
         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, st->codec, codec, st->codec->pix_fmt);
         avcodec_copy_context(ost->enc_ctx, st->codec);
+        if (enc_config)
+            av_dict_parse_string(&ost->encoder_opts, enc_config, "=", ",", 0);
     }
 
     avformat_close_input(&ic);
@@ -2815,7 +2831,7 @@
         "add metadata", "string=string" },
     { "dframes",        HAS_ARG | OPT_PERFILE | OPT_EXPERT |
                         OPT_OUTPUT,                                  { .func_arg = opt_data_frames },
-        "set the number of data frames to record", "number" },
+        "set the number of data frames to output", "number" },
     { "benchmark",      OPT_BOOL | OPT_EXPERT,                       { &do_benchmark },
         "add timings for benchmarking" },
     { "benchmark_all",  OPT_BOOL | OPT_EXPERT,                       { &do_benchmark_all },
@@ -2866,7 +2882,7 @@
     { "copypriorss",    OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT,   { .off = OFFSET(copy_prior_start) },
         "copy or discard frames before start time" },
     { "frames",         OPT_INT64 | HAS_ARG | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(max_frames) },
-        "set the number of frames to record", "number" },
+        "set the number of frames to output", "number" },
     { "tag",            OPT_STRING | HAS_ARG | OPT_SPEC |
                         OPT_EXPERT | OPT_OUTPUT | OPT_INPUT,         { .off = OFFSET(codec_tags) },
         "force codec tag/fourcc", "fourcc/tag" },
@@ -2908,7 +2924,7 @@
 
     /* video options */
     { "vframes",      OPT_VIDEO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_video_frames },
-        "set the number of video frames to record", "number" },
+        "set the number of video frames to output", "number" },
     { "r",            OPT_VIDEO | HAS_ARG  | OPT_STRING | OPT_SPEC |
                       OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(frame_rates) },
         "set frame rate (Hz value, fraction or abbreviation)", "rate" },
@@ -2996,7 +3012,7 @@
 
     /* audio options */
     { "aframes",        OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_frames },
-        "set the number of audio frames to record", "number" },
+        "set the number of audio frames to output", "number" },
     { "aq",             OPT_AUDIO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_audio_qscale },
         "set audio quality (codec-specific)", "quality", },
     { "ar",             OPT_AUDIO | HAS_ARG  | OPT_INT | OPT_SPEC |
diff --git a/ffplay.c b/ffplay.c
index a979164..1914a66 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -121,7 +121,8 @@
 
 #define VIDEO_PICTURE_QUEUE_SIZE 3
 #define SUBPICTURE_QUEUE_SIZE 16
-#define FRAME_QUEUE_SIZE FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE)
+#define SAMPLE_QUEUE_SIZE 9
+#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE))
 
 typedef struct AudioParams {
     int freq;
@@ -196,6 +197,7 @@
 typedef struct VideoState {
     SDL_Thread *read_tid;
     SDL_Thread *video_tid;
+    SDL_Thread *audio_tid;
     AVInputFormat *iformat;
     int no_background;
     int abort_request;
@@ -217,6 +219,7 @@
 
     FrameQueue pictq;
     FrameQueue subpq;
+    FrameQueue sampq;
 
     Decoder auddec;
     Decoder viddec;
@@ -242,8 +245,6 @@
     unsigned int audio_buf1_size;
     int audio_buf_index; /* in bytes */
     int audio_write_buf_size;
-    int audio_buf_frames_pending;
-    int audio_last_serial;
     struct AudioParams audio_src;
 #if CONFIG_AVFILTER
     struct AudioParams audio_filter_src;
@@ -252,7 +253,6 @@
     struct SwrContext *swr_ctx;
     int frame_drops_early;
     int frame_drops_late;
-    AVFrame *frame;
 
     enum ShowMode {
         SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
@@ -712,12 +712,29 @@
     return &f->queue[f->windex];
 }
 
+static Frame *frame_queue_peek_readable(FrameQueue *f)
+{
+    /* wait until we have a readable a new frame */
+    SDL_LockMutex(f->mutex);
+    while (f->size - f->rindex_shown <= 0 &&
+           !f->pktq->abort_request) {
+        SDL_CondWait(f->cond, f->mutex);
+    }
+    SDL_UnlockMutex(f->mutex);
+
+    if (f->pktq->abort_request)
+        return NULL;
+
+    return &f->queue[(f->rindex + f->rindex_shown) % f->max_size];
+}
+
 static void frame_queue_push(FrameQueue *f)
 {
     if (++f->windex == f->max_size)
         f->windex = 0;
     SDL_LockMutex(f->mutex);
     f->size++;
+    SDL_CondSignal(f->cond);
     SDL_UnlockMutex(f->mutex);
 }
 
@@ -1280,6 +1297,7 @@
 
     /* free all pictures */
     frame_queue_destory(&is->pictq);
+    frame_queue_destory(&is->sampq);
     frame_queue_destory(&is->subpq);
     SDL_DestroyCond(is->continue_read_thread);
 #if !CONFIG_AVFILTER
@@ -2100,6 +2118,93 @@
 }
 #endif  /* CONFIG_AVFILTER */
 
+static int audio_thread(void *arg)
+{
+    VideoState *is = arg;
+    AVFrame *frame = av_frame_alloc();
+    Frame *af;
+#if CONFIG_AVFILTER
+    int last_serial = -1;
+    int64_t dec_channel_layout;
+    int reconfigure;
+#endif
+    int got_frame = 0;
+    AVRational tb;
+    int ret = 0;
+
+    if (!frame)
+        return AVERROR(ENOMEM);
+
+    do {
+        if ((got_frame = decoder_decode_frame(&is->auddec, frame, NULL)) < 0)
+            goto the_end;
+
+        if (got_frame) {
+                tb = (AVRational){1, frame->sample_rate};
+
+#if CONFIG_AVFILTER
+                dec_channel_layout = get_valid_channel_layout(frame->channel_layout, av_frame_get_channels(frame));
+
+                reconfigure =
+                    cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
+                                   frame->format, av_frame_get_channels(frame))    ||
+                    is->audio_filter_src.channel_layout != dec_channel_layout ||
+                    is->audio_filter_src.freq           != frame->sample_rate ||
+                    is->auddec.pkt_serial               != last_serial;
+
+                if (reconfigure) {
+                    char buf1[1024], buf2[1024];
+                    av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
+                    av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
+                    av_log(NULL, AV_LOG_DEBUG,
+                           "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
+                           is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial,
+                           frame->sample_rate, av_frame_get_channels(frame), av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial);
+
+                    is->audio_filter_src.fmt            = frame->format;
+                    is->audio_filter_src.channels       = av_frame_get_channels(frame);
+                    is->audio_filter_src.channel_layout = dec_channel_layout;
+                    is->audio_filter_src.freq           = frame->sample_rate;
+                    last_serial                         = is->auddec.pkt_serial;
+
+                    if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
+                        goto the_end;
+                }
+
+            if ((ret = av_buffersrc_add_frame(is->in_audio_filter, frame)) < 0)
+                goto the_end;
+
+            while ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, frame, 0)) >= 0) {
+                tb = is->out_audio_filter->inputs[0]->time_base;
+#endif
+                if (!(af = frame_queue_peek_writable(&is->sampq)))
+                    goto the_end;
+
+                af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
+                af->pos = av_frame_get_pkt_pos(frame);
+                af->serial = is->auddec.pkt_serial;
+                af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate});
+
+                av_frame_move_ref(af->frame, frame);
+                frame_queue_push(&is->sampq);
+
+#if CONFIG_AVFILTER
+                if (is->audioq.serial != is->auddec.pkt_serial)
+                    break;
+            }
+            if (ret == AVERROR_EOF)
+                is->auddec.finished = is->auddec.pkt_serial;
+#endif
+        }
+    } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF);
+ the_end:
+#if CONFIG_AVFILTER
+    avfilter_graph_free(&is->agraph);
+#endif
+    av_frame_free(&frame);
+    return ret;
+}
+
 static int video_thread(void *arg)
 {
     VideoState *is = arg;
@@ -2315,173 +2420,105 @@
 {
     int data_size, resampled_data_size;
     int64_t dec_channel_layout;
-    int got_frame = 0;
     av_unused double audio_clock0;
     int wanted_nb_samples;
-    AVRational tb;
-    int ret;
-    int reconfigure;
+    Frame *af;
 
-    if (!is->frame)
-        if (!(is->frame = av_frame_alloc()))
-            return AVERROR(ENOMEM);
+    if (is->paused)
+        return -1;
 
-    for (;;) {
-        if (is->audioq.serial != is->auddec.pkt_serial)
-            is->audio_buf_frames_pending = got_frame = 0;
-
-        if (!got_frame)
-            av_frame_unref(is->frame);
-
-        if (is->paused)
+    do {
+        if (!(af = frame_queue_peek_readable(&is->sampq)))
             return -1;
+        frame_queue_next(&is->sampq);
+    } while (af->serial != is->audioq.serial);
 
-        while (is->audio_buf_frames_pending || got_frame) {
-            if (!is->audio_buf_frames_pending) {
-                got_frame = 0;
-                tb = (AVRational){1, is->frame->sample_rate};
+    data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(af->frame),
+                                           af->frame->nb_samples,
+                                           af->frame->format, 1);
 
-#if CONFIG_AVFILTER
-                dec_channel_layout = get_valid_channel_layout(is->frame->channel_layout, av_frame_get_channels(is->frame));
+    dec_channel_layout =
+        (af->frame->channel_layout && av_frame_get_channels(af->frame) == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ?
+        af->frame->channel_layout : av_get_default_channel_layout(av_frame_get_channels(af->frame));
+    wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples);
 
-                reconfigure =
-                    cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels,
-                                   is->frame->format, av_frame_get_channels(is->frame))    ||
-                    is->audio_filter_src.channel_layout != dec_channel_layout ||
-                    is->audio_filter_src.freq           != is->frame->sample_rate ||
-                    is->auddec.pkt_serial               != is->audio_last_serial;
-
-                if (reconfigure) {
-                    char buf1[1024], buf2[1024];
-                    av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout);
-                    av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout);
-                    av_log(NULL, AV_LOG_DEBUG,
-                           "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n",
-                           is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, is->audio_last_serial,
-                           is->frame->sample_rate, av_frame_get_channels(is->frame), av_get_sample_fmt_name(is->frame->format), buf2, is->auddec.pkt_serial);
-
-                    is->audio_filter_src.fmt            = is->frame->format;
-                    is->audio_filter_src.channels       = av_frame_get_channels(is->frame);
-                    is->audio_filter_src.channel_layout = dec_channel_layout;
-                    is->audio_filter_src.freq           = is->frame->sample_rate;
-                    is->audio_last_serial               = is->auddec.pkt_serial;
-
-                    if ((ret = configure_audio_filters(is, afilters, 1)) < 0)
-                        return ret;
-                }
-
-                if ((ret = av_buffersrc_add_frame(is->in_audio_filter, is->frame)) < 0)
-                    return ret;
-#endif
-            }
-#if CONFIG_AVFILTER
-            if ((ret = av_buffersink_get_frame_flags(is->out_audio_filter, is->frame, 0)) < 0) {
-                if (ret == AVERROR(EAGAIN)) {
-                    is->audio_buf_frames_pending = 0;
-                    continue;
-                }
-                if (ret == AVERROR_EOF)
-                    is->auddec.finished = is->auddec.pkt_serial;
-                return ret;
-            }
-            is->audio_buf_frames_pending = 1;
-            tb = is->out_audio_filter->inputs[0]->time_base;
-#endif
-
-            data_size = av_samples_get_buffer_size(NULL, av_frame_get_channels(is->frame),
-                                                   is->frame->nb_samples,
-                                                   is->frame->format, 1);
-
-            dec_channel_layout =
-                (is->frame->channel_layout && av_frame_get_channels(is->frame) == av_get_channel_layout_nb_channels(is->frame->channel_layout)) ?
-                is->frame->channel_layout : av_get_default_channel_layout(av_frame_get_channels(is->frame));
-            wanted_nb_samples = synchronize_audio(is, is->frame->nb_samples);
-
-            if (is->frame->format        != is->audio_src.fmt            ||
-                dec_channel_layout       != is->audio_src.channel_layout ||
-                is->frame->sample_rate   != is->audio_src.freq           ||
-                (wanted_nb_samples       != is->frame->nb_samples && !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,           is->frame->format, is->frame->sample_rate,
-                                                 0, NULL);
-                if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
-                    av_log(NULL, AV_LOG_ERROR,
-                           "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
-                            is->frame->sample_rate, av_get_sample_fmt_name(is->frame->format), av_frame_get_channels(is->frame),
-                            is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
-                    swr_free(&is->swr_ctx);
-                    break;
-                }
-                is->audio_src.channel_layout = dec_channel_layout;
-                is->audio_src.channels       = av_frame_get_channels(is->frame);
-                is->audio_src.freq = is->frame->sample_rate;
-                is->audio_src.fmt = is->frame->format;
-            }
-
-            if (is->swr_ctx) {
-                const uint8_t **in = (const uint8_t **)is->frame->extended_data;
-                uint8_t **out = &is->audio_buf1;
-                int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / is->frame->sample_rate + 256;
-                int out_size  = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
-                int len2;
-                if (out_size < 0) {
-                    av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
-                    break;
-                }
-                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 / is->frame->sample_rate,
-                                                wanted_nb_samples * is->audio_tgt.freq / is->frame->sample_rate) < 0) {
-                        av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
-                        break;
-                    }
-                }
-                av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
-                if (!is->audio_buf1)
-                    return AVERROR(ENOMEM);
-                len2 = swr_convert(is->swr_ctx, out, out_count, in, is->frame->nb_samples);
-                if (len2 < 0) {
-                    av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
-                    break;
-                }
-                if (len2 == out_count) {
-                    av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
-                    if (swr_init(is->swr_ctx) < 0)
-                        swr_free(&is->swr_ctx);
-                }
-                is->audio_buf = is->audio_buf1;
-                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];
-                resampled_data_size = data_size;
-            }
-
-            audio_clock0 = is->audio_clock;
-            /* update the audio clock with the pts */
-            if (is->frame->pts != AV_NOPTS_VALUE)
-                is->audio_clock = is->frame->pts * av_q2d(tb) + (double) is->frame->nb_samples / is->frame->sample_rate;
-            else
-                is->audio_clock = NAN;
-            is->audio_clock_serial = is->auddec.pkt_serial;
-#ifdef DEBUG
-            {
-                static double last_clock;
-                printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
-                       is->audio_clock - last_clock,
-                       is->audio_clock, audio_clock0);
-                last_clock = is->audio_clock;
-            }
-#endif
-            return resampled_data_size;
+    if (af->frame->format        != is->audio_src.fmt            ||
+        dec_channel_layout       != is->audio_src.channel_layout ||
+        af->frame->sample_rate   != is->audio_src.freq           ||
+        (wanted_nb_samples       != af->frame->nb_samples && !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,           af->frame->format, af->frame->sample_rate,
+                                         0, NULL);
+        if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) {
+            av_log(NULL, AV_LOG_ERROR,
+                   "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n",
+                    af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), av_frame_get_channels(af->frame),
+                    is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels);
+            swr_free(&is->swr_ctx);
+            return -1;
         }
-
-        if ((got_frame = decoder_decode_frame(&is->auddec, is->frame, NULL)) < 0)
-            return -1;
-
-        if (is->auddec.flushed)
-            is->audio_buf_frames_pending = 0;
+        is->audio_src.channel_layout = dec_channel_layout;
+        is->audio_src.channels       = av_frame_get_channels(af->frame);
+        is->audio_src.freq = af->frame->sample_rate;
+        is->audio_src.fmt = af->frame->format;
     }
+
+    if (is->swr_ctx) {
+        const uint8_t **in = (const uint8_t **)af->frame->extended_data;
+        uint8_t **out = &is->audio_buf1;
+        int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256;
+        int out_size  = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0);
+        int len2;
+        if (out_size < 0) {
+            av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n");
+            return -1;
+        }
+        if (wanted_nb_samples != af->frame->nb_samples) {
+            if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate,
+                                        wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) {
+                av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n");
+                return -1;
+            }
+        }
+        av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size);
+        if (!is->audio_buf1)
+            return AVERROR(ENOMEM);
+        len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples);
+        if (len2 < 0) {
+            av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n");
+            return -1;
+        }
+        if (len2 == out_count) {
+            av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n");
+            if (swr_init(is->swr_ctx) < 0)
+                swr_free(&is->swr_ctx);
+        }
+        is->audio_buf = is->audio_buf1;
+        resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt);
+    } else {
+        is->audio_buf = af->frame->data[0];
+        resampled_data_size = data_size;
+    }
+
+    audio_clock0 = is->audio_clock;
+    /* update the audio clock with the pts */
+    if (!isnan(af->pts))
+        is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate;
+    else
+        is->audio_clock = NAN;
+    is->audio_clock_serial = af->serial;
+#ifdef DEBUG
+    {
+        static double last_clock;
+        printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n",
+               is->audio_clock - last_clock,
+               is->audio_clock, audio_clock0);
+        last_clock = is->audio_clock;
+    }
+#endif
+    return resampled_data_size;
 }
 
 /* prepare a new audio buffer */
@@ -2707,6 +2744,7 @@
             is->auddec.start_pts = is->audio_st->start_time;
             is->auddec.start_pts_tb = is->audio_st->time_base;
         }
+        is->audio_tid = SDL_CreateThread(audio_thread, is);
         SDL_PauseAudio(0);
         break;
     case AVMEDIA_TYPE_VIDEO:
@@ -2748,8 +2786,9 @@
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
         packet_queue_abort(&is->audioq);
-
+        frame_queue_signal(&is->sampq);
         SDL_CloseAudio();
+        SDL_WaitThread(is->audio_tid, NULL);
 
         decoder_destroy(&is->auddec);
         packet_queue_flush(&is->audioq);
@@ -2757,7 +2796,6 @@
         av_freep(&is->audio_buf1);
         is->audio_buf1_size = 0;
         is->audio_buf = NULL;
-        av_frame_free(&is->frame);
 
         if (is->rdft) {
             av_rdft_end(is->rdft);
@@ -2765,9 +2803,6 @@
             is->rdft = NULL;
             is->rdft_bits = 0;
         }
-#if CONFIG_AVFILTER
-        avfilter_graph_free(&is->agraph);
-#endif
         break;
     case AVMEDIA_TYPE_VIDEO:
         packet_queue_abort(&is->videoq);
@@ -2854,6 +2889,7 @@
     AVDictionary **opts;
     int orig_nb_streams;
     SDL_mutex *wait_mutex = SDL_CreateMutex();
+    int scan_all_pmts_set = 0;
 
     memset(st_index, -1, sizeof(st_index));
     is->last_video_stream = is->video_stream = -1;
@@ -2863,12 +2899,19 @@
     ic = avformat_alloc_context();
     ic->interrupt_callback.callback = decode_interrupt_cb;
     ic->interrupt_callback.opaque = is;
+    if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
+        av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
+        scan_all_pmts_set = 1;
+    }
     err = avformat_open_input(&ic, is->filename, is->iformat, &format_opts);
     if (err < 0) {
         print_error(is->filename, err);
         ret = -1;
         goto fail;
     }
+    if (scan_all_pmts_set)
+        av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
+
     if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
         av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
         ret = AVERROR_OPTION_NOT_FOUND;
@@ -3065,7 +3108,7 @@
             continue;
         }
         if (!is->paused &&
-            (!is->audio_st || is->auddec.finished == is->audioq.serial) &&
+            (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) &&
             (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) {
             if (loop != 1 && (!loop || --loop)) {
                 stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
@@ -3074,27 +3117,25 @@
                 goto fail;
             }
         }
-        if (eof) {
-            if (is->video_stream >= 0)
-                packet_queue_put_nullpacket(&is->videoq, is->video_stream);
-            if (is->audio_stream >= 0)
-                packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
-            if (is->subtitle_stream >= 0)
-                packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
-            SDL_Delay(10);
-            eof=0;
-            continue;
-        }
         ret = av_read_frame(ic, pkt);
         if (ret < 0) {
-            if (ret == AVERROR_EOF || avio_feof(ic->pb))
+            if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !eof) {
+                if (is->video_stream >= 0)
+                    packet_queue_put_nullpacket(&is->videoq, is->video_stream);
+                if (is->audio_stream >= 0)
+                    packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
+                if (is->subtitle_stream >= 0)
+                    packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
                 eof = 1;
+            }
             if (ic->pb && ic->pb->error)
                 break;
             SDL_LockMutex(wait_mutex);
             SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
             SDL_UnlockMutex(wait_mutex);
             continue;
+        } else {
+            eof = 0;
         }
         /* check if packet is in play range specified by user, then queue, otherwise discard */
         stream_start_time = ic->streams[pkt->stream_index]->start_time;
@@ -3128,8 +3169,9 @@
         stream_component_close(is, is->video_stream);
     if (is->subtitle_stream >= 0)
         stream_component_close(is, is->subtitle_stream);
-    if (is->ic) {
-        avformat_close_input(&is->ic);
+    if (ic) {
+        avformat_close_input(&ic);
+        is->ic = NULL;
     }
 
     if (ret != 0) {
@@ -3160,6 +3202,8 @@
         goto fail;
     if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
         goto fail;
+    if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
+        goto fail;
 
     packet_queue_init(&is->videoq);
     packet_queue_init(&is->audioq);
@@ -3171,7 +3215,6 @@
     init_clock(&is->audclk, &is->audioq.serial);
     init_clock(&is->extclk, &is->extclk.serial);
     is->audio_clock_serial = -1;
-    is->audio_last_serial = -1;
     is->av_sync_type = av_sync_type;
     is->read_tid     = SDL_CreateThread(read_thread, is);
     if (!is->read_tid) {
@@ -3421,8 +3464,8 @@
                         pos = -1;
                         if (pos < 0 && cur_stream->video_stream >= 0)
                             pos = frame_queue_last_pos(&cur_stream->pictq);
-                        if (pos < 0 && cur_stream->audio_stream >= 0 && cur_stream->frame)
-                            pos = av_frame_get_pkt_pos(cur_stream->frame);
+                        if (pos < 0 && cur_stream->audio_stream >= 0)
+                            pos = frame_queue_last_pos(&cur_stream->sampq);
                         if (pos < 0)
                             pos = avio_tell(cur_stream->ic->pb);
                         if (cur_stream->ic->bit_rate)
diff --git a/ffprobe.c b/ffprobe.c
index 3eb0208..24ecafd 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -2386,12 +2386,19 @@
     AVFormatContext *fmt_ctx = NULL;
     AVDictionaryEntry *t;
     AVDictionary **opts;
+    int scan_all_pmts_set = 0;
 
+    if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
+        av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
+        scan_all_pmts_set = 1;
+    }
     if ((err = avformat_open_input(&fmt_ctx, filename,
                                    iformat, &format_opts)) < 0) {
         print_error(filename, err);
         return err;
     }
+    if (scan_all_pmts_set)
+        av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
     if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
         av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
         return AVERROR_OPTION_NOT_FOUND;
diff --git a/ffserver.c b/ffserver.c
index ea2a2ae..8ef51a1 100644
--- a/ffserver.c
+++ b/ffserver.c
@@ -201,6 +201,7 @@
     .nb_max_http_connections = 2000,
     .nb_max_connections = 5,
     .max_bandwidth = 1000,
+    .use_defaults = 1,
 };
 
 static void new_connection(int server_fd, int is_rtsp);
@@ -1355,7 +1356,7 @@
         redir_type = REDIR_ASX;
         filename[strlen(filename)-1] = 'f';
     } else if (av_match_ext(filename, "asf") &&
-        (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
+        (!useragent || av_strncasecmp(useragent, "NSPlayer", 8))) {
         /* if this isn't WMP or lookalike, return the redirector file */
         redir_type = REDIR_ASF;
     } else if (av_match_ext(filename, "rpm,ram")) {
@@ -2253,6 +2254,7 @@
                         c->state = HTTPSTATE_SEND_DATA_TRAILER;
                     }
 
+                    av_freep(&c->pb_buffer);
                     len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
                     c->cur_frame_bytes = len;
                     c->buffer_ptr = c->pb_buffer;
@@ -2303,7 +2305,7 @@
             ret = http_prepare_data(c);
             if (ret < 0)
                 return -1;
-            else if (ret != 0)
+            else if (ret)
                 /* state change requested */
                 break;
         } else {
@@ -2686,7 +2688,7 @@
     }
 
     /* check version name */
-    if (strcmp(protocol, "RTSP/1.0") != 0) {
+    if (strcmp(protocol, "RTSP/1.0")) {
         rtsp_reply_error(c, RTSP_STATUS_VERSION);
         goto the_end;
     }
@@ -3325,8 +3327,7 @@
 
     av = st->codec;
     for(i=0;i<feed->nb_streams;i++) {
-        st = feed->streams[i];
-        av1 = st->codec;
+        av1 = feed->streams[i]->codec;
         if (av1->codec_id == av->codec_id &&
             av1->codec_type == av->codec_type &&
             av1->bit_rate == av->bit_rate) {
@@ -3354,6 +3355,9 @@
     fst = add_av_stream1(feed, av, 0);
     if (!fst)
         return -1;
+    if (av_stream_get_recommended_encoder_configuration(st))
+        av_stream_set_recommended_encoder_configuration(fst,
+            av_strdup(av_stream_get_recommended_encoder_configuration(st)));
     return feed->nb_streams - 1;
 }
 
@@ -3660,7 +3664,7 @@
 
                 if (uptime < 30)
                     /* Turn off any more restarts */
-                    feed->child_argv = 0;
+                    ffserver_free_child_args(&feed->child_argv);
             }
         }
     }
diff --git a/ffserver_config.c b/ffserver_config.c
index e44cdf7..5f01e43 100644
--- a/ffserver_config.c
+++ b/ffserver_config.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <float.h>
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/avstring.h"
@@ -30,6 +31,15 @@
 #include "cmdutils.h"
 #include "ffserver_config.h"
 
+#define MAX_CHILD_ARGS 64
+
+static int ffserver_save_avoption(const char *opt, const char *arg, int type,
+                                  FFServerConfig *config);
+static void vreport_config_error(const char *filename, int line_num, int log_level,
+                                 int *errors, const char *fmt, va_list vl);
+static void report_config_error(const char *filename, int line_num, int log_level,
+                                int *errors, const char *fmt, ...);
+
 /* FIXME: make ffserver work with IPv6 */
 /* resolve host with also IP address parsing */
 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
@@ -118,7 +128,7 @@
 
     ffserver_get_arg(arg, sizeof(arg), &p);
 
-    if (resolve_host(&acl.first, arg) != 0) {
+    if (resolve_host(&acl.first, arg)) {
         fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n",
                 filename, line_num, arg);
         errors++;
@@ -128,8 +138,9 @@
     ffserver_get_arg(arg, sizeof(arg), &p);
 
     if (arg[0]) {
-        if (resolve_host(&acl.last, arg) != 0) {
-            fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n",
+        if (resolve_host(&acl.last, arg)) {
+            fprintf(stderr,
+                    "%s:%d: ACL refers to invalid host or IP address '%s'\n",
                     filename, line_num, arg);
             errors++;
         }
@@ -165,116 +176,202 @@
 }
 
 /* add a codec and set the default parameters */
-static void add_codec(FFServerStream *stream, AVCodecContext *av)
+static void add_codec(FFServerStream *stream, AVCodecContext *av,
+                      FFServerConfig *config)
 {
     AVStream *st;
+    AVDictionary **opts, *recommended = NULL;
+    char *enc_config;
 
     if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
         return;
 
+    opts = av->codec_type == AVMEDIA_TYPE_AUDIO ?
+           &config->audio_opts : &config->video_opts;
+    av_dict_copy(&recommended, *opts, 0);
+    av_opt_set_dict2(av->priv_data, opts, AV_OPT_SEARCH_CHILDREN);
+    av_opt_set_dict2(av, opts, AV_OPT_SEARCH_CHILDREN);
+    if (av_dict_count(*opts))
+        av_log(NULL, AV_LOG_WARNING,
+               "Something is wrong, %d options are not set!\n", av_dict_count(*opts));
+
+    if (config->stream_use_defaults) {
+    //TODO: reident
     /* compute default parameters */
     switch(av->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
-        if (av->bit_rate == 0)
+        if (av->bit_rate == 0) {
             av->bit_rate = 64000;
-        if (av->sample_rate == 0)
+            av_dict_set_int(&recommended, "ab", av->bit_rate, 0);
+        }
+        if (av->sample_rate == 0) {
             av->sample_rate = 22050;
-        if (av->channels == 0)
+            av_dict_set_int(&recommended, "ar", av->sample_rate, 0);
+        }
+        if (av->channels == 0) {
             av->channels = 1;
+            av_dict_set_int(&recommended, "ac", av->channels, 0);
+        }
         break;
     case AVMEDIA_TYPE_VIDEO:
-        if (av->bit_rate == 0)
+        if (av->bit_rate == 0) {
             av->bit_rate = 64000;
+            av_dict_set_int(&recommended, "b", av->bit_rate, 0);
+        }
         if (av->time_base.num == 0){
             av->time_base.den = 5;
             av->time_base.num = 1;
+            av_dict_set(&recommended, "time_base", "1/5", 0);
         }
         if (av->width == 0 || av->height == 0) {
             av->width = 160;
             av->height = 128;
+            av_dict_set(&recommended, "video_size", "160x128", 0);
         }
         /* Bitrate tolerance is less for streaming */
-        if (av->bit_rate_tolerance == 0)
+        if (av->bit_rate_tolerance == 0) {
             av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
                       (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
-        if (av->qmin == 0)
+            av_dict_set_int(&recommended, "bt", av->bit_rate_tolerance, 0);
+        }
+        if (av->qmin == 0) {
             av->qmin = 3;
-        if (av->qmax == 0)
+            av_dict_set_int(&recommended, "qmin", av->qmin, 0);
+        }
+        if (av->qmax == 0) {
             av->qmax = 31;
-        if (av->max_qdiff == 0)
+            av_dict_set_int(&recommended, "qmax", av->qmax, 0);
+        }
+        if (av->max_qdiff == 0) {
             av->max_qdiff = 3;
+            av_dict_set_int(&recommended, "qdiff", av->max_qdiff, 0);
+        }
+        /*FIXME: 0.5 is a default for these two, it is a dead code */
         av->qcompress = 0.5;
+        av_dict_set(&recommended, "qcomp", "0.5", 0);
         av->qblur = 0.5;
+        av_dict_set(&recommended, "qblur", "0.5", 0);
 
-        if (!av->nsse_weight)
+        if (!av->nsse_weight) {
             av->nsse_weight = 8;
+            av_dict_set_int(&recommended, "nssew", av->nsse_weight, 0);
+        }
 
         av->frame_skip_cmp = FF_CMP_DCTMAX;
-        if (!av->me_method)
+        av_dict_set_int(&recommended, "skipcmp", FF_CMP_DCTMAX, 0);
+        if (!av->me_method) {
             av->me_method = ME_EPZS;
-        av->rc_buffer_aggressivity = 1.0;
+            av_dict_set_int(&recommended, "me_method", ME_EPZS, 0);
+        }
 
-        if (!av->rc_eq)
+        /* FIXME: rc_buffer_aggressivity and rc_eq are deprecated */
+        av->rc_buffer_aggressivity = 1.0;
+        av_dict_set(&recommended, "rc_buf_aggressivity", "1.0", 0);
+
+        if (!av->rc_eq) {
             av->rc_eq = av_strdup("tex^qComp");
-        if (!av->i_quant_factor)
+            av_dict_set(&recommended, "rc_eq", "tex^qComp", 0);
+        }
+        if (!av->i_quant_factor) {
             av->i_quant_factor = -0.8;
-        if (!av->b_quant_factor)
+            av_dict_set(&recommended, "i_qfactor", "-0.8", 0);
+        }
+        if (!av->b_quant_factor) {
             av->b_quant_factor = 1.25;
-        if (!av->b_quant_offset)
+            av_dict_set(&recommended, "b_qfactor", "1.25", 0);
+        }
+        if (!av->b_quant_offset) {
             av->b_quant_offset = 1.25;
-        if (!av->rc_max_rate)
+            av_dict_set(&recommended, "b_qoffset", "1.25", 0);
+        }
+        if (!av->rc_max_rate) {
             av->rc_max_rate = av->bit_rate * 2;
+            av_dict_set_int(&recommended, "maxrate", av->rc_max_rate, 0);
+        }
 
         if (av->rc_max_rate && !av->rc_buffer_size) {
             av->rc_buffer_size = av->rc_max_rate;
+            av_dict_set_int(&recommended, "bufsize", av->rc_buffer_size, 0);
         }
-
-
         break;
     default:
         abort();
     }
+    } else {
+        switch(av->codec_type) {
+        case AVMEDIA_TYPE_AUDIO:
+            if (av->bit_rate == 0)
+                report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                                    &config->errors, "audio bit rate is not set\n");
+            if (av->sample_rate == 0)
+                report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                                    &config->errors, "audio sample rate is not set\n");
+            break;
+        case AVMEDIA_TYPE_VIDEO:
+            if (av->width == 0 || av->height == 0)
+                report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                                    &config->errors, "video size is not set\n");
+            break;
+        default:
+            av_assert0(0);
+        }
+    }
 
     st = av_mallocz(sizeof(AVStream));
     if (!st)
         return;
-    st->codec = avcodec_alloc_context3(NULL);
+    av_dict_get_string(recommended, &enc_config, '=', ',');
+    av_dict_free(&recommended);
+    av_stream_set_recommended_encoder_configuration(st, enc_config);
+    st->codec = av;
     stream->streams[stream->nb_streams++] = st;
-    memcpy(st->codec, av, sizeof(AVCodecContext));
 }
 
-static enum AVCodecID opt_codec(const char *name, enum AVMediaType type)
+static int ffserver_set_codec(AVCodecContext *ctx, const char *codec_name, FFServerConfig *config)
 {
-    AVCodec *codec = avcodec_find_encoder_by_name(name);
-
-    if (!codec || codec->type != type)
-        return AV_CODEC_ID_NONE;
-    return codec->id;
+    int ret;
+    AVCodec *codec = avcodec_find_encoder_by_name(codec_name);
+    if (!codec || codec->type != ctx->codec_type) {
+        report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                            &config->errors, "Invalid codec name: %s\n", codec_name);
+        return 0;
+    }
+    if (ctx->codec_id == AV_CODEC_ID_NONE && !ctx->priv_data) {
+        if ((ret = avcodec_get_context_defaults3(ctx, codec)) < 0)
+            return ret;
+        ctx->codec = codec;
+    }
+    if (ctx->codec_id != codec->id)
+        report_config_error(config->filename, config->line_num, AV_LOG_ERROR, &config->errors,
+                            "Inconsistent configuration: trying to set %s codec option, but %s codec is used previously\n",
+                            codec_name, avcodec_get_name(ctx->codec_id));
+    return 0;
 }
 
-static int ffserver_opt_default(const char *opt, const char *arg,
-                       AVCodecContext *avctx, int type)
-{
-    int ret = 0;
-    const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
-    if(o)
-        ret = av_opt_set(avctx, opt, arg, 0);
-    return ret;
-}
-
-static int ffserver_opt_preset(const char *arg,
-                       AVCodecContext *avctx, int type,
-                       enum AVCodecID *audio_id, enum AVCodecID *video_id)
+static int ffserver_opt_preset(const char *arg, int type, FFServerConfig *config)
 {
     FILE *f=NULL;
     char filename[1000], tmp[1000], tmp2[1000], line[1000];
     int ret = 0;
-    AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
+    AVCodecContext *avctx;
+    const AVCodec *codec;
+
+    switch(type) {
+    case AV_OPT_FLAG_AUDIO_PARAM:
+        avctx = config->dummy_actx;
+        break;
+    case AV_OPT_FLAG_VIDEO_PARAM:
+        avctx = config->dummy_vctx;
+        break;
+    default:
+        av_assert0(0);
+    }
+    codec = avcodec_find_encoder(avctx->codec_id);
 
     if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
                               codec ? codec->name : NULL))) {
-        fprintf(stderr, "File for preset '%s' not found\n", arg);
-        return 1;
+        av_log(NULL, AV_LOG_ERROR, "File for preset '%s' not found\n", arg);
+        return AVERROR(EINVAL);
     }
 
     while(!feof(f)){
@@ -283,21 +380,21 @@
             continue;
         e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
         if(e){
-            fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
-            ret = 1;
+            av_log(NULL, AV_LOG_ERROR, "%s: Invalid syntax: '%s'\n", filename, line);
+            ret = AVERROR(EINVAL);
             break;
         }
-        if(!strcmp(tmp, "acodec")){
-            *audio_id = opt_codec(tmp2, AVMEDIA_TYPE_AUDIO);
-        }else if(!strcmp(tmp, "vcodec")){
-            *video_id = opt_codec(tmp2, AVMEDIA_TYPE_VIDEO);
-        }else if(!strcmp(tmp, "scodec")){
-            /* opt_subtitle_codec(tmp2); */
-        }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
-            fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
-            ret = 1;
+        if ((!strcmp(tmp, "acodec") && avctx->codec_type == AVMEDIA_TYPE_AUDIO) ||
+             !strcmp(tmp, "vcodec") && avctx->codec_type == AVMEDIA_TYPE_VIDEO)
+        {
+            if (ffserver_set_codec(avctx, tmp2, config) < 0)
+                break;
+        } else if (!strcmp(tmp, "scodec")) {
+            av_log(NULL, AV_LOG_ERROR, "Subtitles preset found.\n");
+            ret = AVERROR(EINVAL);
             break;
-        }
+        } else if (ffserver_save_avoption(tmp, tmp2, type, config) < 0)
+            break;
     }
 
     fclose(f);
@@ -313,7 +410,8 @@
         AVOutputFormat *stream_fmt;
         char stream_format_name[64];
 
-        snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
+        snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream",
+                fmt->name);
         stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
 
         if (stream_fmt)
@@ -323,22 +421,172 @@
     return fmt;
 }
 
+static void vreport_config_error(const char *filename, int line_num, int log_level, int *errors, const char *fmt, va_list vl)
+{
+    av_log(NULL, log_level, "%s:%d: ", filename, line_num);
+    av_vlog(NULL, log_level, fmt, vl);
+    if (errors)
+        (*errors)++;
+}
+
 static void report_config_error(const char *filename, int line_num, int log_level, int *errors, const char *fmt, ...)
 {
     va_list vl;
     va_start(vl, fmt);
-    av_log(NULL, log_level, "%s:%d: ", filename, line_num);
-    av_vlog(NULL, log_level, fmt, vl);
+    vreport_config_error(filename, line_num, log_level, errors, fmt, vl);
     va_end(vl);
-
-    (*errors)++;
 }
 
-#define ERROR(...)   report_config_error(config->filename, line_num, AV_LOG_ERROR,   &config->errors,   __VA_ARGS__)
-#define WARNING(...) report_config_error(config->filename, line_num, AV_LOG_WARNING, &config->warnings, __VA_ARGS__)
+static int ffserver_set_int_param(int *dest, const char *value, int factor, int min, int max,
+                                  FFServerConfig *config, const char *error_msg, ...)
+{
+    int tmp;
+    char *tailp;
+    if (!value || !value[0])
+        goto error;
+    errno = 0;
+    tmp = strtol(value, &tailp, 0);
+    if (tmp < min || tmp > max)
+        goto error;
+    if (factor) {
+        if (FFABS(tmp) > INT_MAX / FFABS(factor))
+            goto error;
+        tmp *= factor;
+    }
+    if (tailp[0] || errno)
+        goto error;
+    if (dest)
+        *dest = tmp;
+    return 0;
+  error:
+    if (config) {
+        va_list vl;
+        va_start(vl, error_msg);
+        vreport_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                &config->errors, error_msg, vl);
+        va_end(vl);
+    }
+    return AVERROR(EINVAL);
+}
+
+static int ffserver_set_float_param(float *dest, const char *value, float factor, float min, float max,
+                                    FFServerConfig *config, const char *error_msg, ...)
+{
+    double tmp;
+    char *tailp;
+    if (!value || !value[0])
+        goto error;
+    errno = 0;
+    tmp = strtod(value, &tailp);
+    if (tmp < min || tmp > max)
+        goto error;
+    if (factor)
+        tmp *= factor;
+    if (tailp[0] || errno)
+        goto error;
+    if (dest)
+        *dest = tmp;
+    return 0;
+  error:
+    if (config) {
+        va_list vl;
+        va_start(vl, error_msg);
+        vreport_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                &config->errors, error_msg, vl);
+        va_end(vl);
+    }
+    return AVERROR(EINVAL);
+}
+
+static int ffserver_save_avoption(const char *opt, const char *arg, int type, FFServerConfig *config)
+{
+    static int hinted = 0;
+    int ret = 0;
+    AVDictionaryEntry *e;
+    const AVOption *o = NULL;
+    const char *option = NULL;
+    const char *codec_name = NULL;
+    char buff[1024];
+    AVCodecContext *ctx;
+    AVDictionary **dict;
+    enum AVCodecID guessed_codec_id;
+
+    switch (type) {
+    case AV_OPT_FLAG_VIDEO_PARAM:
+        ctx = config->dummy_vctx;
+        dict = &config->video_opts;
+        guessed_codec_id = config->guessed_video_codec_id != AV_CODEC_ID_NONE ?
+                           config->guessed_video_codec_id : AV_CODEC_ID_H264;
+        break;
+    case AV_OPT_FLAG_AUDIO_PARAM:
+        ctx = config->dummy_actx;
+        dict = &config->audio_opts;
+        guessed_codec_id = config->guessed_audio_codec_id != AV_CODEC_ID_NONE ?
+                           config->guessed_audio_codec_id : AV_CODEC_ID_AAC;
+        break;
+    default:
+        av_assert0(0);
+    }
+
+    if (strchr(opt, ':')) {
+        //explicit private option
+        snprintf(buff, sizeof(buff), "%s", opt);
+        codec_name = buff;
+        option = strchr(buff, ':');
+        buff[option - buff] = '\0';
+        option++;
+        if ((ret = ffserver_set_codec(ctx, codec_name, config)) < 0)
+            return ret;
+        if (!ctx->codec || !ctx->priv_data)
+            return -1;
+    } else {
+        option = opt;
+    }
+
+    o = av_opt_find(ctx, option, NULL, type | AV_OPT_FLAG_ENCODING_PARAM, AV_OPT_SEARCH_CHILDREN);
+    if (!o && (!strcmp(option, "time_base")  || !strcmp(option, "pixel_format") ||
+               !strcmp(option, "video_size") || !strcmp(option, "codec_tag")))
+        o = av_opt_find(ctx, option, NULL, 0, 0);
+    if (!o) {
+        report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                            &config->errors, "Option not found: %s\n", opt);
+        if (!hinted && ctx->codec_id == AV_CODEC_ID_NONE) {
+            hinted = 1;
+            report_config_error(config->filename, config->line_num, AV_LOG_ERROR, NULL,
+                                "If '%s' is a codec private option, then prefix it with codec name, "
+                                "for example '%s:%s %s' or define codec earlier.\n",
+                                opt, avcodec_get_name(guessed_codec_id) ,opt, arg);
+        }
+    } else if ((ret = av_opt_set(ctx, option, arg, AV_OPT_SEARCH_CHILDREN)) < 0) {
+        report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                &config->errors, "Invalid value for option %s (%s): %s\n", opt,
+                arg, av_err2str(ret));
+    } else if ((e = av_dict_get(*dict, option, NULL, 0))) {
+        if ((o->type == AV_OPT_TYPE_FLAGS) && arg && (arg[0] == '+' || arg[0] == '-'))
+            return av_dict_set(dict, option, arg, AV_DICT_APPEND);
+        report_config_error(config->filename, config->line_num, AV_LOG_ERROR,
+                &config->errors,
+                "Redeclaring value of the option %s, previous value: %s\n",
+                opt, e->value);
+    } else if (av_dict_set(dict, option, arg, 0) < 0) {
+        return AVERROR(ENOMEM);
+    }
+    return 0;
+}
+
+static int ffserver_save_avoption_int(const char *opt, int64_t arg,
+                                      int type, FFServerConfig *config)
+{
+    char buf[22];
+    snprintf(buf, sizeof(buf), "%"PRId64, arg);
+    return ffserver_save_avoption(opt, buf, type, config);
+}
+
+#define ERROR(...)   report_config_error(config->filename, config->line_num, AV_LOG_ERROR,   &config->errors,   __VA_ARGS__)
+#define WARNING(...) report_config_error(config->filename, config->line_num, AV_LOG_WARNING, &config->warnings, __VA_ARGS__)
 
 static int ffserver_parse_config_global(FFServerConfig *config, const char *cmd,
-                                        const char **p, int line_num)
+                                        const char **p)
 {
     int val;
     char arg[1024];
@@ -346,9 +594,8 @@
         if (!av_strcasecmp(cmd, "Port"))
             WARNING("Port option is deprecated, use HTTPPort instead\n");
         ffserver_get_arg(arg, sizeof(arg), p);
-        val = atoi(arg);
-        if (val < 1 || val > 65536)
-            ERROR("Invalid port: %s\n", arg);
+        ffserver_set_int_param(&val, arg, 0, 1, 65535, config,
+                "Invalid port: %s\n", arg);
         if (val < 1024)
             WARNING("Trying to use IETF assigned system port: %d\n", val);
         config->http_addr.sin_port = htons(val);
@@ -356,38 +603,42 @@
         if (!av_strcasecmp(cmd, "BindAddress"))
             WARNING("BindAddress option is deprecated, use HTTPBindAddress instead\n");
         ffserver_get_arg(arg, sizeof(arg), p);
-        if (resolve_host(&config->http_addr.sin_addr, arg) != 0)
-            ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
+        if (resolve_host(&config->http_addr.sin_addr, arg))
+            ERROR("Invalid host/IP address: %s\n", arg);
     } else if (!av_strcasecmp(cmd, "NoDaemon")) {
         WARNING("NoDaemon option has no effect, you should remove it\n");
     } else if (!av_strcasecmp(cmd, "RTSPPort")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        val = atoi(arg);
-        if (val < 1 || val > 65536)
-            ERROR("%s:%d: Invalid port: %s\n", arg);
-        config->rtsp_addr.sin_port = htons(atoi(arg));
+        ffserver_set_int_param(&val, arg, 0, 1, 65535, config,
+                "Invalid port: %s\n", arg);
+        config->rtsp_addr.sin_port = htons(val);
     } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        if (resolve_host(&config->rtsp_addr.sin_addr, arg) != 0)
+        if (resolve_host(&config->rtsp_addr.sin_addr, arg))
             ERROR("Invalid host/IP address: %s\n", arg);
     } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        val = atoi(arg);
-        if (val < 1 || val > 65536)
-            ERROR("Invalid MaxHTTPConnections: %s\n", arg);
+        ffserver_set_int_param(&val, arg, 0, 1, 65535, config,
+                "Invalid MaxHTTPConnections: %s\n", arg);
         config->nb_max_http_connections = val;
+        if (config->nb_max_connections > config->nb_max_http_connections)
+            ERROR("Inconsistent configuration: MaxClients(%d) > MaxHTTPConnections(%d)\n",
+                  config->nb_max_connections, config->nb_max_http_connections);
     } else if (!av_strcasecmp(cmd, "MaxClients")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        val = atoi(arg);
-        if (val < 1 || val > config->nb_max_http_connections)
-            ERROR("Invalid MaxClients: %s\n", arg);
-        else
-            config->nb_max_connections = val;
+        ffserver_set_int_param(&val, arg, 0, 1, 65535, config,
+                "Invalid MaxClients: %s\n", arg);
+        config->nb_max_connections = val;
+        if (config->nb_max_connections > config->nb_max_http_connections)
+            ERROR("Inconsistent configuration: MaxClients(%d) > MaxHTTPConnections(%d)\n",
+                  config->nb_max_connections, config->nb_max_http_connections);
     } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
         int64_t llval;
+        char *tailp;
         ffserver_get_arg(arg, sizeof(arg), p);
-        llval = strtoll(arg, NULL, 10);
-        if (llval < 10 || llval > 10000000)
+        errno = 0;
+        llval = strtoll(arg, &tailp, 10);
+        if (llval < 10 || llval > 10000000 || tailp[0] || errno)
             ERROR("Invalid MaxBandwidth: %s\n", arg);
         else
             config->max_bandwidth = llval;
@@ -395,14 +646,18 @@
         if (!config->debug)
             ffserver_get_arg(config->logfilename, sizeof(config->logfilename), p);
     } else if (!av_strcasecmp(cmd, "LoadModule")) {
-        ERROR("Loadable modules no longer supported\n");
+        ERROR("Loadable modules are no longer supported\n");
+    } else if (!av_strcasecmp(cmd, "NoDefaults")) {
+        config->use_defaults = 0;
+    } else if (!av_strcasecmp(cmd, "UseDefaults")) {
+        config->use_defaults = 1;
     } else
         ERROR("Incorrect keyword: '%s'\n", cmd);
     return 0;
 }
 
 static int ffserver_parse_config_feed(FFServerConfig *config, const char *cmd, const char **p,
-                                      int line_num, FFServerStream **pfeed)
+                                      FFServerStream **pfeed)
 {
     FFServerStream *feed;
     char arg[1024];
@@ -438,10 +693,10 @@
     if (!av_strcasecmp(cmd, "Launch")) {
         int i;
 
-        feed->child_argv = av_mallocz(64 * sizeof(char *));
+        feed->child_argv = av_mallocz_array(MAX_CHILD_ARGS, sizeof(char *));
         if (!feed->child_argv)
             return AVERROR(ENOMEM);
-        for (i = 0; i < 62; i++) {
+        for (i = 0; i < MAX_CHILD_ARGS - 2; i++) {
             ffserver_get_arg(arg, sizeof(arg), p);
             if (!arg[0])
                 break;
@@ -459,7 +714,8 @@
         if (!feed->child_argv[i])
             return AVERROR(ENOMEM);
     } else if (!av_strcasecmp(cmd, "ACL")) {
-        ffserver_parse_acl_row(NULL, feed, NULL, *p, config->filename, line_num);
+        ffserver_parse_acl_row(NULL, feed, NULL, *p, config->filename,
+                config->line_num);
     } else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
         ffserver_get_arg(feed->feed_filename, sizeof(feed->feed_filename), p);
         feed->readonly = !av_strcasecmp(cmd, "ReadOnlyFile");
@@ -490,10 +746,14 @@
         case 'G':
             fsize *= 1024 * 1024 * 1024;
             break;
+        default:
+            ERROR("Invalid file size: %s\n", arg);
+            break;
         }
         feed->feed_max_size = (int64_t)fsize;
         if (feed->feed_max_size < FFM_PACKET_SIZE*4)
-            ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
+            ERROR("Feed max file size is too small, must be at least %d\n",
+                    FFM_PACKET_SIZE*4);
     } else if (!av_strcasecmp(cmd, "</Feed>")) {
         *pfeed = NULL;
     } else {
@@ -503,10 +763,11 @@
 }
 
 static int ffserver_parse_config_stream(FFServerConfig *config, const char *cmd, const char **p,
-                                        int line_num, FFServerStream **pstream)
+                                        FFServerStream **pstream)
 {
     char arg[1024], arg2[1024];
     FFServerStream *stream;
+    int val;
 
     av_assert0(pstream);
     stream = *pstream;
@@ -517,6 +778,16 @@
         stream = av_mallocz(sizeof(FFServerStream));
         if (!stream)
             return AVERROR(ENOMEM);
+        config->dummy_actx = avcodec_alloc_context3(NULL);
+        config->dummy_vctx = avcodec_alloc_context3(NULL);
+        if (!config->dummy_vctx || !config->dummy_actx) {
+            av_free(stream);
+            avcodec_free_context(&config->dummy_vctx);
+            avcodec_free_context(&config->dummy_actx);
+            return AVERROR(ENOMEM);
+        }
+        config->dummy_actx->codec_type = AVMEDIA_TYPE_AUDIO;
+        config->dummy_vctx->codec_type = AVMEDIA_TYPE_VIDEO;
         ffserver_get_arg(stream->filename, sizeof(stream->filename), p);
         q = strrchr(stream->filename, '>');
         if (q)
@@ -528,15 +799,14 @@
         }
 
         stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
-        avcodec_get_context_defaults3(&config->video_enc, NULL);
-        avcodec_get_context_defaults3(&config->audio_enc, NULL);
-
-        config->audio_id = AV_CODEC_ID_NONE;
-        config->video_id = AV_CODEC_ID_NONE;
         if (stream->fmt) {
-            config->audio_id = stream->fmt->audio_codec;
-            config->video_id = stream->fmt->video_codec;
+            config->guessed_audio_codec_id = stream->fmt->audio_codec;
+            config->guessed_video_codec_id = stream->fmt->video_codec;
+        } else {
+            config->guessed_audio_codec_id = AV_CODEC_ID_NONE;
+            config->guessed_video_codec_id = AV_CODEC_ID_NONE;
         }
+        config->stream_use_defaults = config->use_defaults;
         *pstream = stream;
         return 0;
     }
@@ -551,7 +821,8 @@
             sfeed = sfeed->next_feed;
         }
         if (!sfeed)
-            ERROR("Feed with name '%s' for stream '%s' is not defined\n", arg, stream->filename);
+            ERROR("Feed with name '%s' for stream '%s' is not defined\n", arg,
+                    stream->filename);
         else
             stream->feed = sfeed;
     } else if (!av_strcasecmp(cmd, "Format")) {
@@ -569,8 +840,8 @@
                 ERROR("Unknown Format: %s\n", arg);
         }
         if (stream->fmt) {
-            config->audio_id = stream->fmt->audio_codec;
-            config->video_id = stream->fmt->video_codec;
+            config->guessed_audio_codec_id = stream->fmt->audio_codec;
+            config->guessed_video_codec_id = stream->fmt->video_codec;
         }
     } else if (!av_strcasecmp(cmd, "InputFormat")) {
         ffserver_get_arg(arg, sizeof(arg), p);
@@ -579,7 +850,8 @@
             ERROR("Unknown input format: %s\n", arg);
     } else if (!av_strcasecmp(cmd, "FaviconURL")) {
         if (stream->stream_type == STREAM_TYPE_STATUS)
-            ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename), p);
+            ffserver_get_arg(stream->feed_filename,
+                    sizeof(stream->feed_filename), p);
         else
             ERROR("FaviconURL only permitted for status streams\n");
     } else if (!av_strcasecmp(cmd, "Author")    ||
@@ -587,23 +859,20 @@
                !av_strcasecmp(cmd, "Copyright") ||
                !av_strcasecmp(cmd, "Title")) {
         char key[32];
-        int i, ret;
+        int i;
         ffserver_get_arg(arg, sizeof(arg), p);
         for (i = 0; i < strlen(cmd); i++)
             key[i] = av_tolower(cmd[i]);
         key[i] = 0;
         WARNING("'%s' option in configuration file is deprecated, "
                 "use 'Metadata %s VALUE' instead\n", cmd, key);
-        if ((ret = av_dict_set(&stream->metadata, key, arg, 0)) < 0)
-            ERROR("Could not set metadata '%s' to value '%s': %s\n", key, arg, av_err2str(ret));
+        if (av_dict_set(&stream->metadata, key, arg, 0) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "Metadata")) {
-        int ret;
         ffserver_get_arg(arg, sizeof(arg), p);
         ffserver_get_arg(arg2, sizeof(arg2), p);
-        if ((ret = av_dict_set(&stream->metadata, arg, arg2, 0)) < 0) {
-            ERROR("Could not set metadata '%s' to value '%s': %s\n",
-                  arg, arg2, av_err2str(ret));
-        }
+        if (av_dict_set(&stream->metadata, arg, arg2, 0) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "Preroll")) {
         ffserver_get_arg(arg, sizeof(arg), p);
         stream->prebuffer = atof(arg) * 1000;
@@ -611,155 +880,180 @@
         stream->send_on_key = 1;
     } else if (!av_strcasecmp(cmd, "AudioCodec")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->audio_id = opt_codec(arg, AVMEDIA_TYPE_AUDIO);
-        if (config->audio_id == AV_CODEC_ID_NONE)
-            ERROR("Unknown AudioCodec: %s\n", arg);
+        ffserver_set_codec(config->dummy_actx, arg, config);
     } else if (!av_strcasecmp(cmd, "VideoCodec")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_id = opt_codec(arg, AVMEDIA_TYPE_VIDEO);
-        if (config->video_id == AV_CODEC_ID_NONE)
-            ERROR("Unknown VideoCodec: %s\n", arg);
+        ffserver_set_codec(config->dummy_vctx, arg, config);
     } else if (!av_strcasecmp(cmd, "MaxTime")) {
         ffserver_get_arg(arg, sizeof(arg), p);
         stream->max_time = atof(arg) * 1000;
     } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
+        float f;
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->audio_enc.bit_rate = lrintf(atof(arg) * 1000);
+        ffserver_set_float_param(&f, arg, 1000, -FLT_MAX, FLT_MAX, config,
+                "Invalid %s: %s\n", cmd, arg);
+        if (ffserver_save_avoption_int("ab", (int64_t)lrintf(f), AV_OPT_FLAG_AUDIO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "AudioChannels")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->audio_enc.channels = atoi(arg);
+        if (ffserver_save_avoption("ac", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->audio_enc.sample_rate = atoi(arg);
+        if (ffserver_save_avoption("ar", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
         int minrate, maxrate;
+        char *dash;
         ffserver_get_arg(arg, sizeof(arg), p);
-        if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
-            config->video_enc.rc_min_rate = minrate * 1000;
-            config->video_enc.rc_max_rate = maxrate * 1000;
+        dash = strchr(arg, '-');
+        if (dash) {
+            *dash = '\0';
+            dash++;
+            if (ffserver_set_int_param(&minrate, arg,  1000, 0, INT_MAX, config, "Invalid %s: %s", cmd, arg) >= 0 &&
+                ffserver_set_int_param(&maxrate, dash, 1000, 0, INT_MAX, config, "Invalid %s: %s", cmd, arg) >= 0) {
+                if (ffserver_save_avoption_int("minrate", minrate, AV_OPT_FLAG_VIDEO_PARAM, config) < 0 ||
+                    ffserver_save_avoption_int("maxrate", maxrate, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+                goto nomem;
+            }
         } else
-            ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
+            ERROR("Incorrect format for VideoBitRateRange -- should be "
+                    "<min>-<max>: %s\n", arg);
     } else if (!av_strcasecmp(cmd, "Debug")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.debug = strtol(arg,0,0);
+        if (ffserver_save_avoption("debug", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0 ||
+            ffserver_save_avoption("debug", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "Strict")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.strict_std_compliance = atoi(arg);
+        if (ffserver_save_avoption("strict", arg, AV_OPT_FLAG_AUDIO_PARAM, config) < 0 ||
+            ffserver_save_avoption("strict", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.rc_buffer_size = atoi(arg) * 8*1024;
+        ffserver_set_int_param(&val, arg, 8*1024, 0, INT_MAX, config,
+                "Invalid %s: %s", cmd, arg);
+        if (ffserver_save_avoption_int("bufsize", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.bit_rate_tolerance = atoi(arg) * 1000;
+        ffserver_set_int_param(&val, arg, 1000, INT_MIN, INT_MAX, config,
+                "Invalid %s: %s", cmd, arg);
+        if (ffserver_save_avoption_int("bt", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.bit_rate = atoi(arg) * 1000;
+        ffserver_set_int_param(&val, arg, 1000, INT_MIN, INT_MAX, config,
+                "Invalid %s: %s", cmd, arg);
+        if (ffserver_save_avoption_int("b", val, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+           goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoSize")) {
-        int ret;
+        int ret, w, h;
         ffserver_get_arg(arg, sizeof(arg), p);
-        ret = av_parse_video_size(&config->video_enc.width, &config->video_enc.height, arg);
+        ret = av_parse_video_size(&w, &h, arg);
         if (ret < 0)
             ERROR("Invalid video size '%s'\n", arg);
-        else if ((config->video_enc.width % 16) != 0 || (config->video_enc.height % 16) != 0)
-            ERROR("Image size must be a multiple of 16\n");
-    } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
-        AVRational frame_rate;
-        ffserver_get_arg(arg, sizeof(arg), p);
-        if (av_parse_video_rate(&frame_rate, arg) < 0) {
-            ERROR("Incorrect frame rate: %s\n", arg);
-        } else {
-            config->video_enc.time_base.num = frame_rate.den;
-            config->video_enc.time_base.den = frame_rate.num;
+        else {
+            if (w % 2 || h % 2)
+                WARNING("Image size is not a multiple of 2\n");
+            if (ffserver_save_avoption("video_size", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+                goto nomem;
         }
+    } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
+        ffserver_get_arg(&arg[2], sizeof(arg) - 2, p);
+        arg[0] = '1'; arg[1] = '/';
+        if (ffserver_save_avoption("time_base", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "PixelFormat")) {
+        enum AVPixelFormat pix_fmt;
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.pix_fmt = av_get_pix_fmt(arg);
-        if (config->video_enc.pix_fmt == AV_PIX_FMT_NONE)
+        pix_fmt = av_get_pix_fmt(arg);
+        if (pix_fmt == AV_PIX_FMT_NONE)
             ERROR("Unknown pixel format: %s\n", arg);
+        else if (ffserver_save_avoption("pixel_format", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.gop_size = atoi(arg);
+        if (ffserver_save_avoption("g", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
-        config->video_enc.gop_size = 1;
+        if (ffserver_save_avoption("g", "1", AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
-        config->video_enc.mb_decision = FF_MB_DECISION_BITS;
+        if (ffserver_save_avoption("mbd", "+bits", AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
-        config->video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
-        config->video_enc.flags |= CODEC_FLAG_4MV;
+        if (ffserver_save_avoption("mbd", "+bits",  AV_OPT_FLAG_VIDEO_PARAM, config) < 0 || //FIXME remove
+            ffserver_save_avoption("flags", "+mv4", AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
                !av_strcasecmp(cmd, "AVOptionAudio")) {
-        AVCodecContext *avctx;
-        int type;
+        int ret;
         ffserver_get_arg(arg, sizeof(arg), p);
         ffserver_get_arg(arg2, sizeof(arg2), p);
-        if (!av_strcasecmp(cmd, "AVOptionVideo")) {
-            avctx = &config->video_enc;
-            type = AV_OPT_FLAG_VIDEO_PARAM;
-        } else {
-            avctx = &config->audio_enc;
-            type = AV_OPT_FLAG_AUDIO_PARAM;
-        }
-        if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
-            ERROR("Error setting %s option to %s %s\n", cmd, arg, arg2);
-        }
+        if (!av_strcasecmp(cmd, "AVOptionVideo"))
+            ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_VIDEO_PARAM, config);
+        else
+            ret = ffserver_save_avoption(arg, arg2, AV_OPT_FLAG_AUDIO_PARAM, config);
+        if (ret < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
                !av_strcasecmp(cmd, "AVPresetAudio")) {
-        AVCodecContext *avctx;
-        int type;
         ffserver_get_arg(arg, sizeof(arg), p);
-        if (!av_strcasecmp(cmd, "AVPresetVideo")) {
-            avctx = &config->video_enc;
-            config->video_enc.codec_id = config->video_id;
-            type = AV_OPT_FLAG_VIDEO_PARAM;
-        } else {
-            avctx = &config->audio_enc;
-            config->audio_enc.codec_id = config->audio_id;
-            type = AV_OPT_FLAG_AUDIO_PARAM;
-        }
-        if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &config->audio_id, &config->video_id)) {
-            ERROR("AVPreset error: %s\n", arg);
-        }
+        if (!av_strcasecmp(cmd, "AVPresetVideo"))
+            ffserver_opt_preset(arg, AV_OPT_FLAG_VIDEO_PARAM, config);
+        else
+            ffserver_opt_preset(arg, AV_OPT_FLAG_AUDIO_PARAM, config);
     } else if (!av_strcasecmp(cmd, "VideoTag")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        if (strlen(arg) == 4)
-            config->video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
+        if (strlen(arg) == 4 &&
+            ffserver_save_avoption_int("codec_tag", MKTAG(arg[0], arg[1], arg[2], arg[3]),
+                                       AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "BitExact")) {
-        config->video_enc.flags |= CODEC_FLAG_BITEXACT;
+        if (ffserver_save_avoption("flags", "+bitexact", AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "DctFastint")) {
-        config->video_enc.dct_algo  = FF_DCT_FASTINT;
+        if (ffserver_save_avoption("dct", "fastint", AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "IdctSimple")) {
-        config->video_enc.idct_algo = FF_IDCT_SIMPLE;
+        if (ffserver_save_avoption("idct", "simple", AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "Qscale")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.flags |= CODEC_FLAG_QSCALE;
-        config->video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
+        ffserver_set_int_param(&val, arg, 0, INT_MIN, INT_MAX, config,
+                               "Invalid Qscale: %s\n", arg);
+        if (ffserver_save_avoption("flags", "+qscale", AV_OPT_FLAG_VIDEO_PARAM, config) < 0 ||
+            ffserver_save_avoption_int("global_quality", FF_QP2LAMBDA * val,
+                                       AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.max_qdiff = atoi(arg);
-        if (config->video_enc.max_qdiff < 1 || config->video_enc.max_qdiff > 31)
-            ERROR("VideoQDiff out of range\n");
+        if (ffserver_save_avoption("qdiff", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoQMax")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.qmax = atoi(arg);
-        if (config->video_enc.qmax < 1 || config->video_enc.qmax > 31)
-            ERROR("VideoQMax out of range\n");
+        if (ffserver_save_avoption("qmax", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "VideoQMin")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.qmin = atoi(arg);
-        if (config->video_enc.qmin < 1 || config->video_enc.qmin > 31)
-            ERROR("VideoQMin out of range\n");
+        if (ffserver_save_avoption("qmin", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "LumiMask")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.lumi_masking = atof(arg);
+        if (ffserver_save_avoption("lumi_mask", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "DarkMask")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        config->video_enc.dark_masking = atof(arg);
+        if (ffserver_save_avoption("dark_mask", arg, AV_OPT_FLAG_VIDEO_PARAM, config) < 0)
+            goto nomem;
     } else if (!av_strcasecmp(cmd, "NoVideo")) {
-        config->video_id = AV_CODEC_ID_NONE;
+        config->no_video = 1;
     } else if (!av_strcasecmp(cmd, "NoAudio")) {
-        config->audio_id = AV_CODEC_ID_NONE;
+        config->no_audio = 1;
     } else if (!av_strcasecmp(cmd, "ACL")) {
-        ffserver_parse_acl_row(stream, NULL, NULL, *p, config->filename, line_num);
+        ffserver_parse_acl_row(stream, NULL, NULL, *p, config->filename,
+                config->line_num);
     } else if (!av_strcasecmp(cmd, "DynamicACL")) {
         ffserver_get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), p);
     } else if (!av_strcasecmp(cmd, "RTSPOption")) {
@@ -768,42 +1062,69 @@
         stream->rtsp_option = av_strdup(arg);
     } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        if (resolve_host(&stream->multicast_ip, arg) != 0)
+        if (resolve_host(&stream->multicast_ip, arg))
             ERROR("Invalid host/IP address: %s\n", arg);
         stream->is_multicast = 1;
         stream->loop = 1; /* default is looping */
     } else if (!av_strcasecmp(cmd, "MulticastPort")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        stream->multicast_port = atoi(arg);
+        ffserver_set_int_param(&val, arg, 0, 1, 65535, config,
+                "Invalid MulticastPort: %s\n", arg);
+        stream->multicast_port = val;
     } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
         ffserver_get_arg(arg, sizeof(arg), p);
-        stream->multicast_ttl = atoi(arg);
+        ffserver_set_int_param(&val, arg, 0, INT_MIN, INT_MAX, config,
+                "Invalid MulticastTTL: %s\n", arg);
+        stream->multicast_ttl = val;
     } else if (!av_strcasecmp(cmd, "NoLoop")) {
         stream->loop = 0;
     } else if (!av_strcasecmp(cmd, "</Stream>")) {
-        if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
-            if (config->audio_id != AV_CODEC_ID_NONE) {
-                config->audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
-                config->audio_enc.codec_id = config->audio_id;
-                add_codec(stream, &config->audio_enc);
+        config->stream_use_defaults &= 1;
+        if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm")) {
+            if (config->dummy_actx->codec_id == AV_CODEC_ID_NONE)
+                config->dummy_actx->codec_id = config->guessed_audio_codec_id;
+            if (!config->no_audio && config->dummy_actx->codec_id != AV_CODEC_ID_NONE) {
+                AVCodecContext *audio_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_actx->codec_id));
+                add_codec(stream, audio_enc, config);
             }
-            if (config->video_id != AV_CODEC_ID_NONE) {
-                config->video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
-                config->video_enc.codec_id = config->video_id;
-                add_codec(stream, &config->video_enc);
+            if (config->dummy_vctx->codec_id == AV_CODEC_ID_NONE)
+                config->dummy_vctx->codec_id = config->guessed_video_codec_id;
+            if (!config->no_video && config->dummy_vctx->codec_id != AV_CODEC_ID_NONE) {
+                AVCodecContext *video_enc = avcodec_alloc_context3(avcodec_find_encoder(config->dummy_vctx->codec_id));
+                add_codec(stream, video_enc, config);
             }
         }
+        av_dict_free(&config->video_opts);
+        av_dict_free(&config->audio_opts);
+        avcodec_free_context(&config->dummy_vctx);
+        avcodec_free_context(&config->dummy_actx);
         *pstream = NULL;
     } else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
-        ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename), p);
+        ffserver_get_arg(stream->feed_filename, sizeof(stream->feed_filename),
+                p);
+    } else if (!av_strcasecmp(cmd, "UseDefaults")) {
+        if (config->stream_use_defaults > 1)
+            WARNING("Multiple UseDefaults/NoDefaults entries.\n");
+        config->stream_use_defaults = 3;
+    } else if (!av_strcasecmp(cmd, "NoDefaults")) {
+        if (config->stream_use_defaults > 1)
+            WARNING("Multiple UseDefaults/NoDefaults entries.\n");
+        config->stream_use_defaults = 2;
     } else {
         ERROR("Invalid entry '%s' inside <Stream></Stream>\n", cmd);
     }
     return 0;
+  nomem:
+    av_log(NULL, AV_LOG_ERROR, "Out of memory. Aborting.\n");
+    av_dict_free(&config->video_opts);
+    av_dict_free(&config->audio_opts);
+    avcodec_free_context(&config->dummy_vctx);
+    avcodec_free_context(&config->dummy_actx);
+    return AVERROR(ENOMEM);
 }
 
 static int ffserver_parse_config_redirect(FFServerConfig *config, const char *cmd, const char **p,
-                                          int line_num, FFServerStream **predirect)
+                                          FFServerStream **predirect)
 {
     FFServerStream *redirect;
     av_assert0(predirect);
@@ -825,7 +1146,8 @@
     }
     av_assert0(redirect);
     if (!av_strcasecmp(cmd, "URL")) {
-        ffserver_get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), p);
+        ffserver_get_arg(redirect->feed_filename,
+                sizeof(redirect->feed_filename), p);
     } else if (!av_strcasecmp(cmd, "</Redirect>")) {
         if (!redirect->feed_filename[0])
             ERROR("No URL found for <Redirect>\n");
@@ -842,17 +1164,18 @@
     char line[1024];
     char cmd[64];
     const char *p;
-    int line_num = 0;
     FFServerStream **last_stream, *stream = NULL, *redirect = NULL;
     FFServerStream **last_feed, *feed = NULL;
     int ret = 0;
 
     av_assert0(config);
 
+    config->line_num = 0;
     f = fopen(filename, "r");
     if (!f) {
         ret = AVERROR(errno);
-        av_log(NULL, AV_LOG_ERROR, "Could not open the configuration file '%s'\n", filename);
+        av_log(NULL, AV_LOG_ERROR,
+                "Could not open the configuration file '%s'\n", filename);
         return ret;
     }
 
@@ -865,7 +1188,7 @@
     for(;;) {
         if (fgets(line, sizeof(line), f) == NULL)
             break;
-        line_num++;
+        config->line_num++;
         p = line;
         while (av_isspace(*p))
             p++;
@@ -879,7 +1202,7 @@
             if (opening && (stream || feed || redirect)) {
                 ERROR("Already in a tag\n");
             } else {
-                if ((ret = ffserver_parse_config_feed(config, cmd, &p, line_num, &feed)) < 0)
+                if ((ret = ffserver_parse_config_feed(config, cmd, &p, &feed)) < 0)
                     break;
                 if (opening) {
                     /* add in stream list */
@@ -895,7 +1218,7 @@
             if (opening && (stream || feed || redirect)) {
                 ERROR("Already in a tag\n");
             } else {
-                if ((ret = ffserver_parse_config_stream(config, cmd, &p, line_num, &stream)) < 0)
+                if ((ret = ffserver_parse_config_stream(config, cmd, &p, &stream)) < 0)
                     break;
                 if (opening) {
                     /* add in stream list */
@@ -908,7 +1231,7 @@
             if (opening && (stream || feed || redirect))
                 ERROR("Already in a tag\n");
             else {
-                if ((ret = ffserver_parse_config_redirect(config, cmd, &p, line_num, &redirect)) < 0)
+                if ((ret = ffserver_parse_config_redirect(config, cmd, &p, &redirect)) < 0)
                     break;
                 if (opening) {
                     /* add in stream list */
@@ -917,9 +1240,11 @@
                 }
             }
         } else {
-            ffserver_parse_config_global(config, cmd, &p, line_num);
+            ffserver_parse_config_global(config, cmd, &p);
         }
     }
+    if (stream || feed || redirect)
+        ERROR("Not closed tag %s\n", stream ? "<Stream>" : (feed ? "<Feed>" : "<Redirect>"));
 
     fclose(f);
     if (ret < 0)
@@ -932,3 +1257,17 @@
 
 #undef ERROR
 #undef WARNING
+
+void ffserver_free_child_args(void *argsp)
+{
+    int i;
+    char **args;
+    if (!argsp)
+        return;
+    args = *(char ***)argsp;
+    if (!args)
+        return;
+    for (i = 0; i < MAX_CHILD_ARGS; i++)
+        av_free(args[i]);
+    av_freep(argsp);
+}
diff --git a/ffserver_config.h b/ffserver_config.h
index 36d61d0..bdeb3c9 100644
--- a/ffserver_config.h
+++ b/ffserver_config.h
@@ -106,12 +106,18 @@
     struct sockaddr_in rtsp_addr;
     int errors;
     int warnings;
+    int use_defaults;
     // Following variables MUST NOT be used outside configuration parsing code.
-    AVCodecContext audio_enc;
-    AVCodecContext video_enc;
-    enum AVCodecID audio_id;
-    enum AVCodecID video_id;
-
+    enum AVCodecID guessed_audio_codec_id;
+    enum AVCodecID guessed_video_codec_id;
+    AVDictionary *video_opts;     /* AVOptions for video encoder */
+    AVDictionary *audio_opts;     /* AVOptions for audio encoder */
+    AVCodecContext *dummy_actx;   /* Used internally to test audio AVOptions. */
+    AVCodecContext *dummy_vctx;   /* Used internally to test video AVOptions. */
+    int no_audio;
+    int no_video;
+    int line_num;
+    int stream_use_defaults;
 } FFServerConfig;
 
 void ffserver_get_arg(char *buf, int buf_size, const char **pp);
@@ -122,4 +128,6 @@
 
 int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config);
 
+void ffserver_free_child_args(void *argsp);
+
 #endif /* FFSERVER_CONFIG_H */
diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c
index ff10082..3a25622 100644
--- a/libavcodec/4xm.c
+++ b/libavcodec/4xm.c
@@ -342,18 +342,22 @@
 static int decode_p_block(FourXContext *f, uint16_t *dst, const uint16_t *src,
                           int log2w, int log2h, int stride)
 {
-    const int index = size2index[log2h][log2w];
-    const int h     = 1 << log2h;
-    int code        = get_vlc2(&f->gb,
-                               block_type_vlc[1 - (f->version > 1)][index].table,
-                               BLOCK_TYPE_VLC_BITS, 1);
-    uint16_t *start = f->last_frame_buffer;
-    uint16_t *end   = start + stride * (f->avctx->height - h + 1) - (1 << log2w);
-    int ret;
-    int scale   = 1;
+    int index, h, code, ret, scale = 1;
+    uint16_t *start, *end;
     unsigned dc = 0;
 
-    av_assert0(code >= 0 && code <= 6 && log2w >= 0);
+    av_assert0(log2w >= 0 && log2h >= 0);
+
+    index = size2index[log2h][log2w];
+    av_assert0(index >= 0);
+
+    h     = 1 << log2h;
+    code  = get_vlc2(&f->gb, block_type_vlc[1 - (f->version > 1)][index].table,
+                     BLOCK_TYPE_VLC_BITS, 1);
+    av_assert0(code >= 0 && code <= 6);
+
+    start = f->last_frame_buffer;
+    end   = start + stride * (f->avctx->height - h + 1) - (1 << log2w);
 
     if (code == 1) {
         log2h--;
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 1a0072a..fa0f53d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -11,6 +11,7 @@
           vda.h                                                         \
           vdpau.h                                                       \
           version.h                                                     \
+          vorbis_parser.h                                               \
           xvmc.h                                                        \
 
 OBJS = allcodecs.o                                                      \
@@ -31,6 +32,8 @@
        resample.o                                                       \
        resample2.o                                                      \
        utils.o                                                          \
+       vorbis_parser.o                                                  \
+       xiph.o                                                           \
 
 # subsystems
 OBJS-$(CONFIG_AANDCTTABLES)            += aandcttab.o
@@ -133,6 +136,7 @@
 OBJS-$(CONFIG_ANM_DECODER)             += anm.o
 OBJS-$(CONFIG_ANSI_DECODER)            += ansi.o cga_data.o
 OBJS-$(CONFIG_APE_DECODER)             += apedec.o
+OBJS-$(CONFIG_APNG_DECODER)            += png.o pngdec.o pngdsp.o
 OBJS-$(CONFIG_SSA_DECODER)             += assdec.o ass.o ass_split.o
 OBJS-$(CONFIG_SSA_ENCODER)             += assenc.o ass.o
 OBJS-$(CONFIG_ASS_DECODER)             += assdec.o ass.o ass_split.o
@@ -445,7 +449,6 @@
 OBJS-$(CONFIG_TARGA_DECODER)           += targa.o
 OBJS-$(CONFIG_TARGA_ENCODER)           += targaenc.o rle.o
 OBJS-$(CONFIG_TARGA_Y216_DECODER)      += targa_y216dec.o
-OBJS-$(CONFIG_THEORA_DECODER)          += xiph.o
 OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o
 OBJS-$(CONFIG_TIFF_DECODER)            += tiff.o lzw.o faxcompr.o tiff_data.o tiff_common.o
 OBJS-$(CONFIG_TIFF_ENCODER)            += tiffenc.o rle.o lzwenc.o tiff_data.o
@@ -484,7 +487,7 @@
 OBJS-$(CONFIG_VMDVIDEO_DECODER)        += vmdvideo.o
 OBJS-$(CONFIG_VMNC_DECODER)            += vmnc.o
 OBJS-$(CONFIG_VORBIS_DECODER)          += vorbisdec.o vorbisdsp.o vorbis.o \
-                                          vorbis_data.o xiph.o
+                                          vorbis_data.o
 OBJS-$(CONFIG_VORBIS_ENCODER)          += vorbisenc.o vorbis.o \
                                           vorbis_data.o
 OBJS-$(CONFIG_VP3_DECODER)             += vp3.o
@@ -676,20 +679,18 @@
 OBJS-$(CONFIG_ADTS_MUXER)              += mpeg4audio.o
 OBJS-$(CONFIG_CAF_DEMUXER)             += mpeg4audio.o mpegaudiodata.o  \
                                           ac3tab.o
-OBJS-$(CONFIG_FLAC_DEMUXER)            += flac.o flacdata.o vorbis_data.o \
-                                          vorbis_parser.o xiph.o
+OBJS-$(CONFIG_FLAC_DEMUXER)            += flac.o flacdata.o vorbis_data.o
 OBJS-$(CONFIG_FLAC_MUXER)              += flac.o flacdata.o vorbis_data.o
 OBJS-$(CONFIG_FLV_DEMUXER)             += mpeg4audio.o
 OBJS-$(CONFIG_GXF_DEMUXER)             += mpeg12data.o
 OBJS-$(CONFIG_IFF_DEMUXER)             += iff.o
 OBJS-$(CONFIG_ISMV_MUXER)              += mpeg4audio.o mpegaudiodata.o
 OBJS-$(CONFIG_LATM_MUXER)              += mpeg4audio.o
-OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER)    += xiph.o mpeg4audio.o vorbis_data.o \
+OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER)    += mpeg4audio.o vorbis_data.o    \
                                           flac.o flacdata.o
-OBJS-$(CONFIG_MATROSKA_DEMUXER)        += mpeg4audio.o mpegaudiodata.o  \
-                                          vorbis_parser.o xiph.o
+OBJS-$(CONFIG_MATROSKA_DEMUXER)        += mpeg4audio.o mpegaudiodata.o
 OBJS-$(CONFIG_MATROSKA_MUXER)          += mpeg4audio.o mpegaudiodata.o  \
-                                          flac.o flacdata.o vorbis_data.o xiph.o
+                                          flac.o flacdata.o vorbis_data.o
 OBJS-$(CONFIG_MP2_MUXER)               += mpegaudiodata.o mpegaudiodecheader.o
 OBJS-$(CONFIG_MP3_MUXER)               += mpegaudiodata.o mpegaudiodecheader.o
 OBJS-$(CONFIG_MOV_DEMUXER)             += mpeg4audio.o mpegaudiodata.o ac3tab.o
@@ -698,21 +699,19 @@
 OBJS-$(CONFIG_MPEGTS_DEMUXER)          += mpeg4audio.o mpegaudiodata.o
 OBJS-$(CONFIG_MXF_MUXER)               += dnxhddata.o
 OBJS-$(CONFIG_NUT_MUXER)               += mpegaudiodata.o
-OBJS-$(CONFIG_OGA_MUXER)               += xiph.o flac.o flacdata.o
-OBJS-$(CONFIG_OGG_DEMUXER)             += xiph.o flac.o flacdata.o     \
-                                          mpeg12data.o vorbis_parser.o \
+OBJS-$(CONFIG_OGA_MUXER)               += flac.o flacdata.o
+OBJS-$(CONFIG_OGG_DEMUXER)             += mpeg12data.o \
                                           dirac.o vorbis_data.o
-OBJS-$(CONFIG_OGG_MUXER)               += xiph.o flac.o flacdata.o \
+OBJS-$(CONFIG_OGG_MUXER)               += flac.o flacdata.o \
                                           vorbis_data.o
-OBJS-$(CONFIG_RTP_MUXER)               += mpeg4audio.o xiph.o
+OBJS-$(CONFIG_RTP_MUXER)               += mpeg4audio.o
 OBJS-$(CONFIG_RTPDEC)                  += mjpeg.o
 OBJS-$(CONFIG_SPDIF_DEMUXER)           += aacadtsdec.o mpeg4audio.o
 OBJS-$(CONFIG_SPDIF_MUXER)             += dca.o
 OBJS-$(CONFIG_TAK_DEMUXER)             += tak.o
 OBJS-$(CONFIG_WEBM_MUXER)              += mpeg4audio.o mpegaudiodata.o  \
-                                          xiph.o flac.o flacdata.o \
+                                          flac.o flacdata.o \
                                           vorbis_data.o
-OBJS-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += vorbis_parser.o xiph.o
 OBJS-$(CONFIG_WTV_DEMUXER)             += mpeg4audio.o mpegaudiodata.o
 
 # libavfilter dependencies
@@ -756,7 +755,7 @@
 OBJS-$(CONFIG_LIBVO_AMRWBENC_ENCODER)     += libvo-amrwbenc.o
 OBJS-$(CONFIG_LIBVORBIS_DECODER)          += libvorbisdec.o
 OBJS-$(CONFIG_LIBVORBIS_ENCODER)          += libvorbisenc.o \
-                                             vorbis_data.o vorbis_parser.o xiph.o
+                                             vorbis_data.o
 OBJS-$(CONFIG_LIBVPX_VP8_DECODER)         += libvpxdec.o
 OBJS-$(CONFIG_LIBVPX_VP8_ENCODER)         += libvpxenc.o
 OBJS-$(CONFIG_LIBVPX_VP9_DECODER)         += libvpxdec.o libvpx.o
@@ -812,7 +811,6 @@
 OBJS-$(CONFIG_VC1_PARSER)              += vc1_parser.o vc1.o vc1data.o vc1dsp.o \
                                           msmpeg4.o msmpeg4data.o mpeg4video.o \
                                           h263.o
-OBJS-$(CONFIG_VORBIS_PARSER)           += vorbis_parser.o xiph.o
 OBJS-$(CONFIG_VP3_PARSER)              += vp3_parser.o
 OBJS-$(CONFIG_VP8_PARSER)              += vp8_parser.o
 OBJS-$(CONFIG_VP9_PARSER)              += vp9_parser.o
diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 387e103..e8de1e8 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -245,6 +245,7 @@
  * channel element - generic struct for SCE/CPE/CCE/LFE
  */
 typedef struct ChannelElement {
+    int present;
     // CPE specific
     int common_window;        ///< Set if channels share a common 'IndividualChannelStream' in bitstream.
     int     ms_mode;          ///< Signals mid/side stereo flags coding mode (used by encoder)
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 66464344..2793881 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -703,6 +703,7 @@
             syn_ele = TYPE_LFE;
             break;
         default:
+            // AAC_CHANNEL_OFF has no channel map
             av_assert0(0);
         }
         layout_map[0][0] = syn_ele;
@@ -2290,7 +2291,12 @@
 {
     int crc_flag = 0;
     int res = cnt;
-    switch (get_bits(gb, 4)) { // extension type
+    int type = get_bits(gb, 4);
+
+    if (ac->avctx->debug & FF_DEBUG_STARTCODE)
+        av_log(ac->avctx, AV_LOG_DEBUG, "extension type: %d len:%d\n", type, cnt);
+
+    switch (type) { // extension type
     case EXT_SBR_DATA_CRC:
         crc_flag++;
     case EXT_SBR_DATA:
@@ -2738,7 +2744,7 @@
     for (type = 3; type >= 0; type--) {
         for (i = 0; i < MAX_ELEM_ID; i++) {
             ChannelElement *che = ac->che[type][i];
-            if (che) {
+            if (che && che->present) {
                 if (type <= TYPE_CPE)
                     apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling);
                 if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
@@ -2770,6 +2776,9 @@
                 }
                 if (type <= TYPE_CCE)
                     apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, apply_independent_coupling);
+                che->present = 0;
+            } else if (che) {
+                av_log(ac->avctx, AV_LOG_WARNING, "ChannelElement %d.%d missing \n", type, i);
             }
         }
     }
@@ -2874,6 +2883,7 @@
                    elem_type, elem_id);
             return AVERROR_INVALIDDATA;
         }
+        che->present = 1;
         if (aot != AOT_ER_AAC_ELD)
             skip_bits(gb, 4);
         switch (elem_type) {
@@ -2948,6 +2958,7 @@
                 goto fail;
             }
             samples = 1024;
+            che->present = 1;
         }
 
         switch (elem_type) {
@@ -3465,6 +3476,18 @@
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
+static const AVProfile profiles[] = {
+    { FF_PROFILE_AAC_MAIN,  "Main"     },
+    { FF_PROFILE_AAC_LOW,   "LC"       },
+    { FF_PROFILE_AAC_SSR,   "SSR"      },
+    { FF_PROFILE_AAC_LTP,   "LTP"      },
+    { FF_PROFILE_AAC_HE,    "HE-AAC"   },
+    { FF_PROFILE_AAC_HE_V2, "HE-AACv2" },
+    { FF_PROFILE_AAC_LD,    "LD"       },
+    { FF_PROFILE_AAC_ELD,   "ELD"      },
+    { FF_PROFILE_UNKNOWN },
+};
+
 AVCodec ff_aac_decoder = {
     .name            = "aac",
     .long_name       = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"),
@@ -3481,6 +3504,7 @@
     .channel_layouts = aac_channel_layout,
     .flush = flush,
     .priv_class      = &aac_decoder_class,
+    .profiles        = profiles,
 };
 
 /*
@@ -3503,4 +3527,5 @@
     .capabilities    = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
     .channel_layouts = aac_channel_layout,
     .flush = flush,
+    .profiles        = profiles,
 };
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 464e4dc..d9c7215 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -252,7 +252,7 @@
     int i;
     float *output = sce->ret_buf;
 
-    apply_window[sce->ics.window_sequence[0]](&s->fdsp, sce, audio);
+    apply_window[sce->ics.window_sequence[0]](s->fdsp, sce, audio);
 
     if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE)
         s->mdct1024.mdct_calc(&s->mdct1024, sce->coeffs, output);
@@ -567,6 +567,10 @@
                 ics->group_len[w] = wi[ch].grouping[w];
 
             apply_window_and_mdct(s, &cpe->ch[ch], overlap);
+            if (isnan(cpe->ch->coeffs[0])) {
+                av_log(avctx, AV_LOG_ERROR, "Input contains NaN\n");
+                return AVERROR(EINVAL);
+            }
         }
         start_ch += chans;
     }
@@ -678,6 +682,7 @@
         ff_psy_preprocess_end(s->psypp);
     av_freep(&s->buffer.samples);
     av_freep(&s->cpe);
+    av_freep(&s->fdsp);
     ff_af_queue_close(&s->afq);
     return 0;
 }
@@ -686,7 +691,9 @@
 {
     int ret = 0;
 
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
 
     // window init
     ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024);
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index ecd6811..0decb1d 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -67,7 +67,7 @@
     PutBitContext pb;
     FFTContext mdct1024;                         ///< long (1024 samples) frame transform context
     FFTContext mdct128;                          ///< short (128 samples) frame transform context
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     float *planar_samples[6];                    ///< saved preprocessed input
 
     int samplerate_index;                        ///< MPEG-4 samplerate index
diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c
index f550ead..f8ae424 100644
--- a/libavcodec/aacsbr.c
+++ b/libavcodec/aacsbr.c
@@ -326,7 +326,7 @@
 static int sbr_make_f_master(AACContext *ac, SpectralBandReplication *sbr,
                              SpectrumParameters *spectrum)
 {
-    unsigned int temp, max_qmf_subbands;
+    unsigned int temp, max_qmf_subbands = 0;
     unsigned int start_min, stop_min;
     int k;
     const int8_t *sbr_offset_ptr;
@@ -556,7 +556,8 @@
             k = sbr->n_master;
     } while (sb != sbr->kx[1] + sbr->m[1]);
 
-    if (sbr->num_patches > 1 && sbr->patch_num_subbands[sbr->num_patches-1] < 3)
+    if (sbr->num_patches > 1 &&
+        sbr->patch_num_subbands[sbr->num_patches - 1] < 3)
         sbr->num_patches--;
 
     return 0;
@@ -1611,8 +1612,14 @@
             memcpy(q_temp[i + 2*ch_data->t_env[0]], sbr->q_m[0],  m_max * sizeof(sbr->q_m[0][0]));
         }
     } else if (h_SL) {
-        memcpy(g_temp[2*ch_data->t_env[0]], g_temp[2*ch_data->t_env_num_env_old], 4*sizeof(g_temp[0]));
-        memcpy(q_temp[2*ch_data->t_env[0]], q_temp[2*ch_data->t_env_num_env_old], 4*sizeof(q_temp[0]));
+        for (i = 0; i < 4; i++) {
+            memcpy(g_temp[i + 2 * ch_data->t_env[0]],
+                   g_temp[i + 2 * ch_data->t_env_num_env_old],
+                   sizeof(g_temp[0]));
+            memcpy(q_temp[i + 2 * ch_data->t_env[0]],
+                   q_temp[i + 2 * ch_data->t_env_num_env_old],
+                   sizeof(q_temp[0]));
+        }
     }
 
     for (e = 0; e < ch_data->bs_num_env; e++) {
diff --git a/libavcodec/aarch64/fft_neon.S b/libavcodec/aarch64/fft_neon.S
index 54c13a4..30f24dd 100644
--- a/libavcodec/aarch64/fft_neon.S
+++ b/libavcodec/aarch64/fft_neon.S
@@ -376,7 +376,8 @@
         ld1             {v30.16b}, [x10]
         mov             x7,  #-8
         movrel          x12, pmmp
-        ldr             x3,  [x3, x2, lsl #3]
+        ldr             x4,  [x3, x2, lsl #3]
+        add             x3,  x3,  x4
         movrel          x13, mppm
         movrel          x14, X(ff_cos_16)
         ld1             {v31.16b}, [x11]
@@ -416,21 +417,21 @@
 endfunc
 
 const   fft_tab_neon
-        .quad fft4_neon
-        .quad fft8_neon
-        .quad fft16_neon
-        .quad fft32_neon
-        .quad fft64_neon
-        .quad fft128_neon
-        .quad fft256_neon
-        .quad fft512_neon
-        .quad fft1024_neon
-        .quad fft2048_neon
-        .quad fft4096_neon
-        .quad fft8192_neon
-        .quad fft16384_neon
-        .quad fft32768_neon
-        .quad fft65536_neon
+        .quad fft4_neon     - fft_tab_neon
+        .quad fft8_neon     - fft_tab_neon
+        .quad fft16_neon    - fft_tab_neon
+        .quad fft32_neon    - fft_tab_neon
+        .quad fft64_neon    - fft_tab_neon
+        .quad fft128_neon   - fft_tab_neon
+        .quad fft256_neon   - fft_tab_neon
+        .quad fft512_neon   - fft_tab_neon
+        .quad fft1024_neon  - fft_tab_neon
+        .quad fft2048_neon  - fft_tab_neon
+        .quad fft4096_neon  - fft_tab_neon
+        .quad fft8192_neon  - fft_tab_neon
+        .quad fft16384_neon - fft_tab_neon
+        .quad fft32768_neon - fft_tab_neon
+        .quad fft65536_neon - fft_tab_neon
 endconst
 
 const   pmmp, align=4
diff --git a/libavcodec/aarch64/opus_imdct_neon.S b/libavcodec/aarch64/opus_imdct_neon.S
index 6234309..c242261 100644
--- a/libavcodec/aarch64/opus_imdct_neon.S
+++ b/libavcodec/aarch64/opus_imdct_neon.S
@@ -438,8 +438,8 @@
         uzp1            v12.4s, v4.4s,  v5.4s   // exp[11 - 14].re
         uzp2            v13.4s, v4.4s,  v5.4s   // exp[11 - 14].im
         zip1            v14.4s, v6.4s,  v7.4s   // exp[5,10].re/exp[5,10].im
-        add             x5,  x5,  x3,  lsl #3
-        ldr             x5,  [x5]
+        ldr             x6,  [x5, x3, lsl #3]
+        add             x5,  x5,  x6
         mov             x10, x0
         blr             x5
         ldp             x20, x30, [sp]
@@ -452,13 +452,13 @@
 endfunc
 
 const   fft_tab_neon
-        .quad fft15_neon
-        .quad fft30_neon
-        .quad fft60_neon
-        .quad fft120_neon
-        .quad fft240_neon
-        .quad fft480_neon
-        .quad fft960_neon
+        .quad fft15_neon  - fft_tab_neon
+        .quad fft30_neon  - fft_tab_neon
+        .quad fft60_neon  - fft_tab_neon
+        .quad fft120_neon - fft_tab_neon
+        .quad fft240_neon - fft_tab_neon
+        .quad fft480_neon - fft_tab_neon
+        .quad fft960_neon - fft_tab_neon
 endconst
 
 function ff_celt_imdct_half_neon, export=1
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 969e37f..d3e8713 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -195,7 +195,7 @@
 #if (USE_FIXED)
     s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & CODEC_FLAG_BITEXACT);
 #else
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
 #endif
 
     ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT);
@@ -688,7 +688,7 @@
             s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
                                        s->tmp_output, s->window, 128, 8);
 #else
-            s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
+            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
                                        s->tmp_output, s->window, 128);
 #endif
             for (i = 0; i < 128; i++)
@@ -700,7 +700,7 @@
             s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
                                        s->tmp_output, s->window, 128, 8);
 #else
-            s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
+            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
                                        s->tmp_output, s->window, 128);
 #endif
             memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample));
@@ -1635,9 +1635,7 @@
     AC3DecodeContext *s = avctx->priv_data;
     ff_mdct_end(&s->imdct_512);
     ff_mdct_end(&s->imdct_256);
-#if (USE_FIXED)
     av_freep(&s->fdsp);
-#endif
 
     return 0;
 }
diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h
index a213bc0..be29f00 100644
--- a/libavcodec/ac3dec.h
+++ b/libavcodec/ac3dec.h
@@ -218,7 +218,7 @@
 #if USE_FIXED
     AVFixedDSPContext *fdsp;
 #else
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
 #endif
     AC3DSPContext ac3dsp;
     FmtConvertContext fmt_conv;             ///< optimized conversion functions
diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c
index 8fc9952..dc52908 100644
--- a/libavcodec/ac3enc.c
+++ b/libavcodec/ac3enc.c
@@ -2035,6 +2035,7 @@
     av_freep(&s->qmant_buffer);
     av_freep(&s->cpl_coord_exp_buffer);
     av_freep(&s->cpl_coord_mant_buffer);
+    av_freep(&s->fdsp);
     for (blk = 0; blk < s->num_blocks; blk++) {
         AC3Block *block = &s->blocks[blk];
         av_freep(&block->mdct_coef);
diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h
index 74da612..a2442d0 100644
--- a/libavcodec/ac3enc.h
+++ b/libavcodec/ac3enc.h
@@ -165,7 +165,7 @@
     AVCodecContext *avctx;                  ///< parent AVCodecContext
     PutBitContext pb;                       ///< bitstream writer context
     AudioDSPContext adsp;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     MECmpContext mecc;
     AC3DSPContext ac3dsp;                   ///< AC-3 optimized functions
     FFTContext mdct;                        ///< FFT context for MDCT calculation
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index fa6e509..766b14e 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -139,7 +139,9 @@
 av_cold int ff_ac3_float_encode_init(AVCodecContext *avctx)
 {
     AC3EncodeContext *s = avctx->priv_data;
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
     return ff_ac3_encode_init(avctx);
 }
 
diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c
index 3e02408..c3ad76f 100644
--- a/libavcodec/ac3enc_template.c
+++ b/libavcodec/ac3enc_template.c
@@ -108,7 +108,7 @@
             const SampleType *input_samples = &s->planar_samples[ch][blk * AC3_BLOCK_SIZE];
 
 #if CONFIG_AC3ENC_FLOAT
-            s->fdsp.vector_fmul(s->windowed_samples, input_samples,
+            s->fdsp->vector_fmul(s->windowed_samples, input_samples,
                                 s->mdct_window, AC3_WINDOW_SIZE);
 #else
             s->ac3dsp.apply_window_int16(s->windowed_samples, input_samples,
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index 05e3245..4387ffb 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -43,14 +43,12 @@
     int s0, s1, s2, d;
     int max = 0;
     int min = 0;
-    int data[BLOCK_SAMPLES];
 
     s1 = prev->s1;
     s2 = prev->s2;
     for (i = 0, j = 0; j < 32; i += channels, j++) {
         s0 = wav[i];
         d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;
-        data[j] = d;
         if (max < d)
             max = d;
         if (min > d)
@@ -58,10 +56,10 @@
         s2 = s1;
         s1 = s0;
     }
-    prev->s1 = s1;
-    prev->s2 = s2;
 
     if (max == 0 && min == 0) {
+        prev->s1 = s1;
+        prev->s2 = s2;
         memset(adx, 0, BLOCK_SIZE);
         return;
     }
@@ -77,8 +75,23 @@
     AV_WB16(adx, scale);
 
     init_put_bits(&pb, adx + 2, 16);
-    for (i = 0; i < BLOCK_SAMPLES; i++)
-        put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7));
+
+    s1 = prev->s1;
+    s2 = prev->s2;
+    for (i = 0, j = 0; j < 32; i += channels, j++) {
+        d = ((wav[i] << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS;
+
+        d = av_clip(ROUNDED_DIV(d, scale), -8, 7);
+
+        put_sbits(&pb, 4, d);
+
+        s0 = ((d << COEFF_BITS) * scale + c->coeff[0] * s1 + c->coeff[1] * s2) >> COEFF_BITS;
+        s2 = s1;
+        s1 = s0;
+    }
+    prev->s1 = s1;
+    prev->s2 = s2;
+
     flush_put_bits(&pb);
 }
 
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index d08abd8..0d39d33 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -105,6 +105,7 @@
     REGISTER_ENCDEC (AMV,               amv);
     REGISTER_DECODER(ANM,               anm);
     REGISTER_DECODER(ANSI,              ansi);
+    REGISTER_DECODER(APNG,              apng);
     REGISTER_ENCDEC (ASV1,              asv1);
     REGISTER_ENCDEC (ASV2,              asv2);
     REGISTER_DECODER(AURA,              aura);
diff --git a/libavcodec/anm.c b/libavcodec/anm.c
index 79a87dd..3727534 100644
--- a/libavcodec/anm.c
+++ b/libavcodec/anm.c
@@ -47,8 +47,10 @@
         return AVERROR(ENOMEM);
 
     bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size);
-    if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256)
+    if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256) {
+        av_frame_free(&s->frame);
         return AVERROR_INVALIDDATA;
+    }
 
     bytestream2_skipu(&s->gb, 16 * 8);
     for (i = 0; i < 256; i++)
diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c
index 45c307f..92981cc 100644
--- a/libavcodec/ansi.c
+++ b/libavcodec/ansi.c
@@ -90,9 +90,11 @@
     s->fg          = DEFAULT_FG_COLOR;
     s->bg          = DEFAULT_BG_COLOR;
 
-    if (!avctx->width || !avctx->height)
-        ff_set_dimensions(avctx, 80 << 3, 25 << 4);
-
+    if (!avctx->width || !avctx->height) {
+        int ret = ff_set_dimensions(avctx, 80 << 3, 25 << 4);
+        if (ret < 0)
+            return ret;
+    }
     return 0;
 }
 
diff --git a/libavcodec/arm/flacdsp_init_arm.c b/libavcodec/arm/flacdsp_init_arm.c
index 9ddb268..df1b19c 100644
--- a/libavcodec/arm/flacdsp_init_arm.c
+++ b/libavcodec/arm/flacdsp_init_arm.c
@@ -24,7 +24,7 @@
 void ff_flac_lpc_16_arm(int32_t *samples, const int coeffs[32], int order,
                         int qlevel, int len);
 
-av_cold void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt,
+av_cold void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
                                  int bps)
 {
     if (bps <= 16 && CONFIG_FLAC_DECODER)
diff --git a/libavcodec/arm/me_cmp_init_arm.c b/libavcodec/arm/me_cmp_init_arm.c
index eb48b38..03870a2 100644
--- a/libavcodec/arm/me_cmp_init_arm.c
+++ b/libavcodec/arm/me_cmp_init_arm.c
@@ -26,17 +26,17 @@
 #include "libavcodec/mpegvideo.h"
 
 int ff_pix_abs16_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
-                       int line_size, int h);
+                       ptrdiff_t stride, int h);
 int ff_pix_abs16_x2_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
-                          int line_size, int h);
+                          ptrdiff_t stride, int h);
 int ff_pix_abs16_y2_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
-                          int line_size, int h);
+                          ptrdiff_t stride, int h);
 
 int ff_pix_abs8_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
-                      int line_size, int h);
+                      ptrdiff_t stride, int h);
 
 int ff_sse16_armv6(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
-                   int line_size, int h);
+                   ptrdiff_t stride, int h);
 
 av_cold void ff_me_cmp_init_arm(MECmpContext *c, AVCodecContext *avctx)
 {
diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c
index d059d75..aeb068c 100644
--- a/libavcodec/atrac1.c
+++ b/libavcodec/atrac1.c
@@ -80,7 +80,7 @@
     DECLARE_ALIGNED(32, float, high)[512];
     float*              bands[3];
     FFTContext          mdct_ctx[3];
-    AVFloatDSPContext   fdsp;
+    AVFloatDSPContext   *fdsp;
 } AT1Ctx;
 
 /** size of the transform in samples in the long mode for each QMF band */
@@ -140,7 +140,7 @@
             at1_imdct(q, &q->spec[pos], &su->spectrum[0][ref_pos + start_pos], nbits, band_num);
 
             /* overlap and window */
-            q->fdsp.vector_fmul_window(&q->bands[band_num][start_pos], prev_buf,
+            q->fdsp->vector_fmul_window(&q->bands[band_num][start_pos], prev_buf,
                                        &su->spectrum[0][ref_pos + start_pos], ff_sine_32, 16);
 
             prev_buf = &su->spectrum[0][ref_pos+start_pos + 16];
@@ -324,6 +324,8 @@
     ff_mdct_end(&q->mdct_ctx[1]);
     ff_mdct_end(&q->mdct_ctx[2]);
 
+    av_freep(&q->fdsp);
+
     return 0;
 }
 
@@ -359,7 +361,7 @@
 
     ff_atrac_generate_tables();
 
-    avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    q->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
 
     q->bands[0] = q->low;
     q->bands[1] = q->mid;
diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c
index d9f1348..9dc0811 100644
--- a/libavcodec/atrac3.c
+++ b/libavcodec/atrac3.c
@@ -109,7 +109,7 @@
     AtracGCContext    gainc_ctx;
     FFTContext        mdct_ctx;
     FmtConvertContext fmt_conv;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
 } ATRAC3Context;
 
 static DECLARE_ALIGNED(32, float, mdct_window)[MDCT_SIZE];
@@ -142,7 +142,7 @@
     q->mdct_ctx.imdct_calc(&q->mdct_ctx, output, input);
 
     /* Perform windowing on the output. */
-    q->fdsp.vector_fmul(output, output, mdct_window, MDCT_SIZE);
+    q->fdsp->vector_fmul(output, output, mdct_window, MDCT_SIZE);
 }
 
 /*
@@ -192,6 +192,7 @@
 
     av_freep(&q->units);
     av_freep(&q->decoded_bytes_buffer);
+    av_freep(&q->fdsp);
 
     ff_mdct_end(&q->mdct_ctx);
 
@@ -915,11 +916,11 @@
     }
 
     ff_atrac_init_gain_compensation(&q->gainc_ctx, 4, 3);
-    avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    q->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
     ff_fmt_convert_init(&q->fmt_conv, avctx);
 
     q->units = av_mallocz_array(avctx->channels, sizeof(*q->units));
-    if (!q->units) {
+    if (!q->units || !q->fdsp) {
         atrac3_decode_close(avctx);
         return AVERROR(ENOMEM);
     }
diff --git a/libavcodec/atrac3plus.c b/libavcodec/atrac3plus.c
index f7a42cc..575a493 100644
--- a/libavcodec/atrac3plus.c
+++ b/libavcodec/atrac3plus.c
@@ -1575,7 +1575,7 @@
 {
     int mode, sb, j, i, diff, maxdiff, fi, delta, pred;
     Atrac3pWaveParam *wsrc, *wref;
-    int refwaves[48];
+    int refwaves[48] = { 0 };
     Atrac3pWavesData *dst = ctx->channels[ch_num].tones_info;
     Atrac3pWavesData *ref = ctx->channels[0].tones_info;
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 1eec224..080ec5a 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -320,6 +320,7 @@
     AV_CODEC_ID_HEVC       = MKBETAG('H','2','6','5'),
 #define AV_CODEC_ID_H265 AV_CODEC_ID_HEVC
     AV_CODEC_ID_VP7        = MKBETAG('V','P','7','0'),
+    AV_CODEC_ID_APNG       = MKBETAG('A','P','N','G'),
 
     /* various PCM "codecs" */
     AV_CODEC_ID_FIRST_AUDIO = 0x10000,     ///< A dummy id pointing at the start of audio codecs
@@ -3115,7 +3116,7 @@
     uint8_t *dump_separator;
 
     /**
-     * ',' seperated list of allowed decoders.
+     * ',' separated list of allowed decoders.
      * If NULL then all are allowed
      * - encoding: unused
      * - decoding: set by user through AVOPtions (NO direct access)
diff --git a/libavcodec/avs.c b/libavcodec/avs.c
index c4eaf20..976d325 100644
--- a/libavcodec/avs.c
+++ b/libavcodec/avs.c
@@ -165,9 +165,8 @@
         return AVERROR(ENOMEM);
 
     avctx->pix_fmt = AV_PIX_FMT_PAL8;
-    ff_set_dimensions(avctx, 318, 198);
 
-    return 0;
+    return ff_set_dimensions(avctx, 318, 198);
 }
 
 static av_cold int avs_decode_end(AVCodecContext *avctx)
diff --git a/libavcodec/avuienc.c b/libavcodec/avuienc.c
index 700b8cb..db640bb 100644
--- a/libavcodec/avuienc.c
+++ b/libavcodec/avuienc.c
@@ -25,16 +25,10 @@
 
 static av_cold int avui_encode_init(AVCodecContext *avctx)
 {
-    avctx->coded_frame = av_frame_alloc();
-
     if (avctx->width != 720 || avctx->height != 486 && avctx->height != 576) {
         av_log(avctx, AV_LOG_ERROR, "Only 720x486 and 720x576 are supported.\n");
         return AVERROR(EINVAL);
     }
-    if (!avctx->coded_frame) {
-        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-        return AVERROR(ENOMEM);
-    }
     if (!(avctx->extradata = av_mallocz(24 + FF_INPUT_BUFFER_PADDING_SIZE)))
         return AVERROR(ENOMEM);
     avctx->extradata_size = 24;
@@ -45,6 +39,11 @@
         avctx->extradata[19] = 1;
     }
 
+    avctx->coded_frame = av_frame_alloc();
+    if (!avctx->coded_frame) {
+        av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
+        return AVERROR(ENOMEM);
+    }
 
     return 0;
 }
diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c
index 45d815a..c0880e0 100644
--- a/libavcodec/cavs.c
+++ b/libavcodec/cavs.c
@@ -30,6 +30,7 @@
 #include "golomb.h"
 #include "h264chroma.h"
 #include "idctdsp.h"
+#include "internal.h"
 #include "mathops.h"
 #include "qpeldsp.h"
 #include "cavs.h"
@@ -539,8 +540,8 @@
 {
     int den = h->scale_den[FFMAX(src->ref, 0)];
 
-    *d_x = (src->x * distp * den + 256 + (src->x >> 31)) >> 9;
-    *d_y = (src->y * distp * den + 256 + (src->y >> 31)) >> 9;
+    *d_x = (src->x * distp * den + 256 + FF_SIGNBIT(src->x)) >> 9;
+    *d_y = (src->y * distp * den + 256 + FF_SIGNBIT(src->y)) >> 9;
 }
 
 static inline void mv_pred_median(AVSContext *h,
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c
index 42306cc..b5304ea 100644
--- a/libavcodec/cavsdec.c
+++ b/libavcodec/cavsdec.c
@@ -467,7 +467,7 @@
 {
     cavs_vector *pmv_bw = pmv_fw + MV_BWD_OFFS;
     int den = h->direct_den[col_mv->ref];
-    int m = col_mv->x >> 31;
+    int m = FF_SIGNBIT(col_mv->x);
 
     pmv_fw->dist = h->dist[1];
     pmv_bw->dist = h->dist[0];
@@ -476,7 +476,7 @@
     /* scale the co-located motion vector according to its temporal span */
     pmv_fw->x =     (((den + (den * col_mv->x * pmv_fw->dist ^ m) - m - 1) >> 14) ^ m) - m;
     pmv_bw->x = m - (((den + (den * col_mv->x * pmv_bw->dist ^ m) - m - 1) >> 14) ^ m);
-    m = col_mv->y >> 31;
+    m = FF_SIGNBIT(col_mv->y);
     pmv_fw->y =     (((den + (den * col_mv->y * pmv_fw->dist ^ m) - m - 1) >> 14) ^ m) - m;
     pmv_bw->y = m - (((den + (den * col_mv->y * pmv_bw->dist ^ m) - m - 1) >> 14) ^ m);
 }
diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c
index 855baaa..c49e903 100644
--- a/libavcodec/cngdec.c
+++ b/libavcodec/cngdec.c
@@ -41,11 +41,11 @@
 static av_cold int cng_decode_close(AVCodecContext *avctx)
 {
     CNGContext *p = avctx->priv_data;
-    av_free(p->refl_coef);
-    av_free(p->target_refl_coef);
-    av_free(p->lpc_coef);
-    av_free(p->filter_out);
-    av_free(p->excitation);
+    av_freep(&p->refl_coef);
+    av_freep(&p->target_refl_coef);
+    av_freep(&p->lpc_coef);
+    av_freep(&p->filter_out);
+    av_freep(&p->excitation);
     return 0;
 }
 
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index eeb4505..0af66f4 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1440,6 +1440,14 @@
         .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS,
         .mime_types= MT("image/x-xwindowdump"),
     },
+    {
+        .id        = AV_CODEC_ID_APNG,
+        .type      = AVMEDIA_TYPE_VIDEO,
+        .name      = "apng",
+        .long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"),
+        .props     = AV_CODEC_PROP_LOSSLESS,
+        .mime_types= MT("image/png"),
+    },
 
     /* various PCM "codecs" */
     {
diff --git a/libavcodec/cook.c b/libavcodec/cook.c
index eb2654e..cfbce2a 100644
--- a/libavcodec/cook.c
+++ b/libavcodec/cook.c
@@ -1058,7 +1058,7 @@
     q->avctx = avctx;
 
     /* Take care of the codec specific extradata. */
-    if (extradata_size <= 0) {
+    if (extradata_size < 8) {
         av_log(avctx, AV_LOG_ERROR, "Necessary extradata missing!\n");
         return AVERROR_INVALIDDATA;
     }
@@ -1215,8 +1215,8 @@
 
         q->num_subpackets++;
         s++;
-        if (s > MAX_SUBPACKETS) {
-            avpriv_request_sample(avctx, "subpackets > %d", MAX_SUBPACKETS);
+        if (s > FFMIN(MAX_SUBPACKETS, avctx->block_align)) {
+            avpriv_request_sample(avctx, "subpackets > %d", FFMIN(MAX_SUBPACKETS, avctx->block_align));
             return AVERROR_PATCHWELCOME;
         }
     }
diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c
index 45b2d46..001afa4 100644
--- a/libavcodec/crystalhd.c
+++ b/libavcodec/crystalhd.c
@@ -362,7 +362,7 @@
         av_bitstream_filter_close(priv->bsfc);
     }
 
-    av_free(priv->sps_pps_buf);
+    av_freep(&priv->sps_pps_buf);
 
     av_frame_free (&priv->pic);
 
diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c
index 8774510..a36f69b 100644
--- a/libavcodec/dcadec.c
+++ b/libavcodec/dcadec.c
@@ -472,7 +472,7 @@
     int profile;
 
     int debug_flag;             ///< used for suppressing repeated error messages output
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FFTContext imdct;
     SynthFilterContext synth;
     DCADSPContext dcadsp;
@@ -1637,7 +1637,7 @@
     int embedded_stereo = 0;
     int embedded_6ch    = 0;
     int drc_code_present;
-    int av_uninit(extensions_mask);
+    int extensions_mask = 0;
     int i, j;
 
     if (get_bits_left(&s->gb) < 16)
@@ -2519,8 +2519,8 @@
             float *back_chan = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel]];
             float *lt_chan   = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 2]];
             float *rt_chan   = s->samples_chanptr[s->channel_order_tab[s->xch_base_channel - 1]];
-            s->fdsp.vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256);
-            s->fdsp.vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256);
+            s->fdsp->vector_fmac_scalar(lt_chan, back_chan, -M_SQRT1_2, 256);
+            s->fdsp->vector_fmac_scalar(rt_chan, back_chan, -M_SQRT1_2, 256);
         }
 
         /* If stream contains XXCH, we might need to undo an embedded downmix */
@@ -2540,7 +2540,7 @@
                             scale = s->xxch_dmix_coeff[j][k];
                             if (scale != 0.0) {
                                 dst_chan = s->samples_chanptr[achan];
-                                s->fdsp.vector_fmac_scalar(dst_chan, src_chan,
+                                s->fdsp->vector_fmac_scalar(dst_chan, src_chan,
                                                            -scale, 256);
                             }
                         }
@@ -2603,7 +2603,10 @@
     s->avctx = avctx;
     dca_init_vlcs();
 
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
+
     ff_mdct_init(&s->imdct, 6, 1, 1.0);
     ff_synth_filter_init(&s->synth);
     ff_dcadsp_init(&s->dcadsp);
@@ -2630,6 +2633,7 @@
     DCAContext *s = avctx->priv_data;
     ff_mdct_end(&s->imdct);
     av_freep(&s->extra_channels_buffer);
+    av_freep(&s->fdsp);
     return 0;
 }
 
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index d438fbb..d7105a1 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -117,7 +117,7 @@
 
     for (i = 1; i < 64; ++i) {
         int j = scantable[i];
-        int sign = block[j] >> 31;
+        int sign = FF_SIGNBIT(block[j]);
         int level = (block[j] ^ sign) - sign;
         level = level * qmat[j] >> DNX10BIT_QMAT_SHIFT;
         block[j] = (level ^ sign) - sign;
@@ -314,6 +314,7 @@
 
     index = ff_dnxhd_get_cid_table(ctx->cid);
     av_assert0(index >= 0);
+
     ctx->cid_table = &ff_dnxhd_cid_table[index];
 
     ctx->m.avctx    = avctx;
diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c
index 097597e..261e161 100644
--- a/libavcodec/dvbsubdec.c
+++ b/libavcodec/dvbsubdec.c
@@ -306,64 +306,58 @@
                     obj2 = *obj2_ptr;
 
                     while (obj2 != object) {
-                        assert(obj2);
+                        av_assert0(obj2);
                         obj2_ptr = &obj2->next;
                         obj2 = *obj2_ptr;
                     }
 
                     *obj2_ptr = obj2->next;
 
-                    av_free(obj2);
+                    av_freep(&obj2);
                 }
             }
         }
 
         region->display_list = display->region_list_next;
 
-        av_free(display);
+        av_freep(&display);
     }
 
 }
 
 static void delete_cluts(DVBSubContext *ctx)
 {
-    DVBSubCLUT *clut;
-
     while (ctx->clut_list) {
-        clut = ctx->clut_list;
+        DVBSubCLUT *clut = ctx->clut_list;
 
         ctx->clut_list = clut->next;
 
-        av_free(clut);
+        av_freep(&clut);
     }
 }
 
 static void delete_objects(DVBSubContext *ctx)
 {
-    DVBSubObject *object;
-
     while (ctx->object_list) {
-        object = ctx->object_list;
+        DVBSubObject *object = ctx->object_list;
 
         ctx->object_list = object->next;
 
-        av_free(object);
+        av_freep(&object);
     }
 }
 
 static void delete_regions(DVBSubContext *ctx)
 {
-    DVBSubRegion *region;
-
     while (ctx->region_list) {
-        region = ctx->region_list;
+        DVBSubRegion *region = ctx->region_list;
 
         ctx->region_list = region->next;
 
         delete_region_display_list(ctx, region);
 
-        av_free(region->pbuf);
-        av_free(region);
+        av_freep(&region->pbuf);
+        av_freep(&region);
     }
 }
 
@@ -468,7 +462,7 @@
         display = ctx->display_list;
         ctx->display_list = display->next;
 
-        av_free(display);
+        av_freep(&display);
     }
 
     return 0;
@@ -734,22 +728,16 @@
                     return pixels_read;
                 }
 
-                if (map_table)
-                    bits = map_table[0];
-                else
-                    bits = 0;
-                while (run_length-- > 0 && pixels_read < dbuf_len) {
-                    *destbuf++ = bits;
-                    pixels_read++;
-                }
+                bits = 0;
             } else {
                 bits = *(*srcbuf)++;
-
-                if (non_mod == 1 && bits == 1)
-                    pixels_read += run_length;
+            }
+            if (non_mod == 1 && bits == 1)
+                pixels_read += run_length;
+            else {
                 if (map_table)
                     bits = map_table[bits];
-                else while (run_length-- > 0 && pixels_read < dbuf_len) {
+                while (run_length-- > 0 && pixels_read < dbuf_len) {
                     *destbuf++ = bits;
                     pixels_read++;
                 }
@@ -763,7 +751,7 @@
     return pixels_read;
 }
 
-static void save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_output)
+static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_output)
 {
     DVBSubContext *ctx = avctx->priv_data;
     DVBSubRegionDisplay *display;
@@ -774,6 +762,7 @@
     uint32_t *clut_table;
     int i;
     int offset_x=0, offset_y=0;
+    int ret = 0;
 
 
     if (display_def) {
@@ -784,7 +773,7 @@
     /* Not touching AVSubtitles again*/
     if(sub->num_rects) {
         avpriv_request_sample(ctx, "Different Version of Segment asked Twice\n");
-        return;
+        return AVERROR_PATCHWELCOME;
     }
     for (display = ctx->display_list; display; display = display->next) {
         region = get_region(ctx, display->region_id);
@@ -802,6 +791,11 @@
     if (sub->num_rects > 0) {
 
         sub->rects = av_mallocz_array(sizeof(*sub->rects), sub->num_rects);
+        if (!sub->rects) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
         for(i=0; i<sub->num_rects; i++)
             sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
 
@@ -844,14 +838,39 @@
             }
 
             rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
+            if (!rect->pict.data[1]) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
             memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t));
 
             rect->pict.data[0] = av_malloc(region->buf_size);
+            if (!rect->pict.data[0]) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+
             memcpy(rect->pict.data[0], region->pbuf, region->buf_size);
 
             i++;
         }
     }
+
+    return 0;
+fail:
+    if (sub->rects) {
+        for(i=0; i<sub->num_rects; i++) {
+            rect = sub->rects[i];
+            if (rect) {
+                av_freep(&rect->pict.data[0]);
+                av_freep(&rect->pict.data[1]);
+            }
+            av_freep(&sub->rects[i]);
+        }
+        av_freep(&sub->rects);
+    }
+    sub->num_rects = 0;
+    return ret;
 }
 
 static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display,
@@ -1318,7 +1337,7 @@
 
         tmp_display_list = display->next;
 
-        av_free(display);
+        av_freep(&display);
     }
 
 }
@@ -1412,7 +1431,7 @@
 
         png_save2(filename, pbuf, width, height);
 
-        av_free(pbuf);
+        av_freep(&pbuf);
     }
 
     fileno_index++;
diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c
index 4f0d0f6..99fe1f4 100644
--- a/libavcodec/dvdec.c
+++ b/libavcodec/dvdec.c
@@ -505,7 +505,7 @@
     if (*vsc_pack == dv_video_control) {
         apt    = buf[4] & 0x07;
         is16_9 = (vsc_pack[2] & 0x07) == 0x02 ||
-                               (!apt && (vsc_pack[2] & 0x07) == 0x07);
+                 (!apt && (vsc_pack[2] & 0x07) == 0x07);
         ff_set_sar(avctx, s->sys->sar[is16_9]);
     }
 
diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c
index bb28d9e..39604f3 100644
--- a/libavcodec/dvdsubdec.c
+++ b/libavcodec/dvdsubdec.c
@@ -28,12 +28,14 @@
 #include "libavutil/opt.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/avstring.h"
+#include "libavutil/bswap.h"
 
 typedef struct DVDSubContext
 {
   AVClass *class;
   uint32_t palette[16];
   char    *palette_str;
+  char    *ifo_str;
   int      has_palette;
   uint8_t  colormap[4];
   uint8_t  alpha[256];
@@ -583,10 +585,71 @@
     }
 }
 
+static int parse_ifo_palette(DVDSubContext *ctx, char *p)
+{
+    FILE *ifo;
+    char ifostr[12];
+    uint32_t sp_pgci, pgci, off_pgc, pgc;
+    uint8_t r, g, b, yuv[65], *buf;
+    int i, y, cb, cr, r_add, g_add, b_add;
+    int ret = 0;
+    const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
+
+    ctx->has_palette = 0;
+    if ((ifo = fopen(p, "r")) == NULL) {
+        av_log(ctx, AV_LOG_WARNING, "Unable to open IFO file \"%s\": %s\n", p, strerror(errno));
+        return AVERROR_EOF;
+    }
+    if (fread(ifostr, 12, 1, ifo) != 1 || memcmp(ifostr, "DVDVIDEO-VTS", 12)) {
+        av_log(ctx, AV_LOG_WARNING, "\"%s\" is not a proper IFO file\n", p);
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+    if (fseek(ifo, 0xCC, SEEK_SET) == -1) {
+        ret = AVERROR(errno);
+        goto end;
+    }
+    if (fread(&sp_pgci, 4, 1, ifo) == 1) {
+        pgci = av_be2ne32(sp_pgci) * 2048;
+        if (fseek(ifo, pgci + 0x0C, SEEK_SET) == -1) {
+            ret = AVERROR(errno);
+            goto end;
+        }
+        if (fread(&off_pgc, 4, 1, ifo) == 1) {
+            pgc = pgci + av_be2ne32(off_pgc);
+            if (fseek(ifo, pgc + 0xA4, SEEK_SET) == -1) {
+                ret = AVERROR(errno);
+                goto end;
+            }
+            if (fread(yuv, 64, 1, ifo) == 1) {
+                buf = yuv;
+                for(i=0; i<16; i++) {
+                    y  = *++buf;
+                    cr = *++buf;
+                    cb = *++buf;
+                    YUV_TO_RGB1_CCIR(cb, cr);
+                    YUV_TO_RGB2_CCIR(r, g, b, y);
+                    ctx->palette[i] = (r << 16) + (g << 8) + b;
+                    buf++;
+                }
+                ctx->has_palette = 1;
+            }
+        }
+    }
+    if (ctx->has_palette == 0) {
+        av_log(ctx, AV_LOG_WARNING, "Failed to read palette from IFO file \"%s\"\n", p);
+        ret = AVERROR_INVALIDDATA;
+    }
+end:
+    fclose(ifo);
+    return ret;
+}
+
 static int dvdsub_parse_extradata(AVCodecContext *avctx)
 {
     DVDSubContext *ctx = (DVDSubContext*) avctx->priv_data;
     char *dataorig, *data;
+    int ret = 1;
 
     if (!avctx->extradata || !avctx->extradata_size)
         return 1;
@@ -607,11 +670,9 @@
         } else if (strncmp("size:", data, 5) == 0) {
             int w, h;
             if (sscanf(data + 5, "%dx%d", &w, &h) == 2) {
-               int ret = ff_set_dimensions(avctx, w, h);
-               if (ret < 0) {
-                   av_free(dataorig);
-                   return ret;
-               }
+               ret = ff_set_dimensions(avctx, w, h);
+               if (ret < 0)
+                   goto fail;
             }
         }
 
@@ -619,8 +680,9 @@
         data += strspn(data, "\n\r");
     }
 
+fail:
     av_free(dataorig);
-    return 1;
+    return ret;
 }
 
 static av_cold int dvdsub_init(AVCodecContext *avctx)
@@ -631,6 +693,8 @@
     if ((ret = dvdsub_parse_extradata(avctx)) < 0)
         return ret;
 
+    if (ctx->ifo_str)
+        parse_ifo_palette(ctx, ctx->ifo_str);
     if (ctx->palette_str)
         parse_palette(ctx, ctx->palette_str);
     if (ctx->has_palette) {
@@ -656,6 +720,7 @@
 #define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
 static const AVOption options[] = {
     { "palette", "set the global palette", OFFSET(palette_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
+    { "ifo_palette", "obtain the global palette from .IFO file", OFFSET(ifo_str), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, SD },
     { "forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD},
     { NULL }
 };
diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c
index ee5d731..4d8b7b2 100644
--- a/libavcodec/dxtory.c
+++ b/libavcodec/dxtory.c
@@ -82,10 +82,10 @@
     V  = pic->data[2];
     for (h = 0; h < avctx->height; h += 4) {
         for (w = 0; w < avctx->width; w += 4) {
-            AV_COPY32(Y1 + w, src);
-            AV_COPY32(Y2 + w, src + 4);
-            AV_COPY32(Y3 + w, src + 8);
-            AV_COPY32(Y4 + w, src + 12);
+            AV_COPY32U(Y1 + w, src);
+            AV_COPY32U(Y2 + w, src + 4);
+            AV_COPY32U(Y3 + w, src + 8);
+            AV_COPY32U(Y4 + w, src + 12);
             U[w >> 2] = src[16] + 0x80;
             V[w >> 2] = src[17] + 0x80;
             src += 18;
diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c
index 2611780..c72c562 100644
--- a/libavcodec/error_resilience.c
+++ b/libavcodec/error_resilience.c
@@ -448,7 +448,7 @@
                     int best_score         = 256 * 256 * 256 * 64;
                     int best_pred          = 0;
                     const int mot_index    = (mb_x + mb_y * mot_stride) * mot_step;
-                    int prev_x, prev_y, prev_ref;
+                    int prev_x = 0, prev_y = 0, prev_ref = 0;
 
                     if ((mb_x ^ mb_y ^ pass) & 1)
                         continue;
diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c
index c7ccf22..2816741 100644
--- a/libavcodec/escape124.c
+++ b/libavcodec/escape124.c
@@ -143,10 +143,11 @@
     // This function reads a maximum of 22 bits; the callers
     // guard this function appropriately
     unsigned block_index, depth;
-
-    if (get_bits1(gb)) {
+    int value = get_bits1(gb);
+    if (value) {
         static const char transitions[3][2] = { {2, 1}, {0, 2}, {1, 0} };
-        *codebook_index = transitions[*codebook_index][get_bits1(gb)];
+        value = get_bits1(gb);
+        *codebook_index = transitions[*codebook_index][value];
     }
 
     depth = s->codebooks[*codebook_index].depth;
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 62e8521..b56fe2e 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -382,8 +382,9 @@
                                 int32_t im, int32_t iM, uint64_t *hcode)
 {
     GetBitContext gbit;
-
-    init_get_bits8(&gbit, gb->buffer, bytestream2_get_bytes_left(gb));
+    int ret = init_get_bits8(&gbit, gb->buffer, bytestream2_get_bytes_left(gb));
+    if (ret < 0)
+        return ret;
 
     for (; im <= iM; im++) {
         uint64_t l = hcode[im] = get_bits(&gbit, 6);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index c408f16..5fbe51c 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -1051,12 +1051,17 @@
         return 0;
 
     {
-        FFV1Context bak = *fdst;
+        ThreadFrame picture = fdst->picture, last_picture = fdst->last_picture;
+        uint8_t (*initial_states[MAX_QUANT_TABLES])[32];
+        struct FFV1Context *slice_context[MAX_SLICES];
+        memcpy(initial_states, fdst->initial_states, sizeof(fdst->initial_states));
+        memcpy(slice_context,  fdst->slice_context , sizeof(fdst->slice_context));
+
         memcpy(fdst, fsrc, sizeof(*fdst));
-        memcpy(fdst->initial_states, bak.initial_states, sizeof(fdst->initial_states));
-        memcpy(fdst->slice_context,  bak.slice_context , sizeof(fdst->slice_context));
-        fdst->picture      = bak.picture;
-        fdst->last_picture = bak.last_picture;
+        memcpy(fdst->initial_states, initial_states, sizeof(fdst->initial_states));
+        memcpy(fdst->slice_context,  slice_context , sizeof(fdst->slice_context));
+        fdst->picture      = picture;
+        fdst->last_picture = last_picture;
         for (i = 0; i<fdst->num_h_slices * fdst->num_v_slices; i++) {
             FFV1Context *fssrc = fsrc->slice_context[i];
             FFV1Context *fsdst = fdst->slice_context[i];
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index e2d3707..cf2a13d 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -166,7 +166,7 @@
                     best_len[k]      = len;
                     best_state[i][k] = j;
                 }
-                for (m = 0; m < 256; m++)
+                for (m = 1; m < 256; m++)
                     if (occ[m]) {
                         newocc[      one_state[      m]] += occ[m] * p;
                         newocc[256 - one_state[256 - m]] += occ[m] * (1 - p);
diff --git a/libavcodec/fic.c b/libavcodec/fic.c
index 5615e69..adc8a25 100644
--- a/libavcodec/fic.c
+++ b/libavcodec/fic.c
@@ -308,7 +308,10 @@
         return AVERROR_INVALIDDATA;
     }
 
-    if (tsize < 32) {
+    if (!tsize)
+        skip_cursor = 1;
+
+    if (!skip_cursor && tsize < 32) {
         av_log(avctx, AV_LOG_WARNING,
                "Cursor data too small. Skipping cursor.\n");
         skip_cursor = 1;
@@ -317,14 +320,14 @@
     /* Cursor position. */
     cur_x = AV_RL16(src + 33);
     cur_y = AV_RL16(src + 35);
-    if (cur_x > avctx->width || cur_y > avctx->height) {
+    if (!skip_cursor && (cur_x > avctx->width || cur_y > avctx->height)) {
         av_log(avctx, AV_LOG_WARNING,
                "Invalid cursor position: (%d,%d). Skipping cusor.\n",
                cur_x, cur_y);
         skip_cursor = 1;
     }
 
-    if (AV_RL16(src + 37) != 32 || AV_RL16(src + 39) != 32) {
+    if (!skip_cursor && (AV_RL16(src + 37) != 32 || AV_RL16(src + 39) != 32)) {
         av_log(avctx, AV_LOG_WARNING,
                "Invalid cursor size. Skipping cursor.\n");
         skip_cursor = 1;
diff --git a/libavcodec/flac.c b/libavcodec/flac.c
index 1053491..5ff004e 100644
--- a/libavcodec/flac.c
+++ b/libavcodec/flac.c
@@ -166,7 +166,7 @@
     return count;
 }
 
-int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
+int ff_flac_is_extradata_valid(AVCodecContext *avctx,
                                enum FLACExtradataFormat *format,
                                uint8_t **streaminfo_start)
 {
@@ -201,7 +201,7 @@
         avctx->channel_layout = 0;
 }
 
-void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
+void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
                               const uint8_t *buffer)
 {
     GetBitContext gb;
@@ -235,3 +235,18 @@
     skip_bits_long(&gb, 64); /* md5 sum */
     skip_bits_long(&gb, 64); /* md5 sum */
 }
+
+#if LIBAVCODEC_VERSION_MAJOR < 57
+void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
+                              const uint8_t *buffer)
+{
+    ff_flac_parse_streaminfo(avctx, s, buffer);
+}
+
+int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
+                               enum FLACExtradataFormat *format,
+                               uint8_t **streaminfo_start)
+{
+    return ff_flac_is_extradata_valid(avctx, format, streaminfo_start);
+}
+#endif
diff --git a/libavcodec/flac.h b/libavcodec/flac.h
index d85195f..f1307c7 100644
--- a/libavcodec/flac.h
+++ b/libavcodec/flac.h
@@ -96,8 +96,16 @@
  * @param[out] s       where parsed information is stored
  * @param[in]  buffer  pointer to start of 34-byte streaminfo data
  */
+void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
+                              const uint8_t *buffer);
+
+#if LIBAVCODEC_VERSION_MAJOR < 57
 void avpriv_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
                                   const uint8_t *buffer);
+int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
+                                   enum FLACExtradataFormat *format,
+                                   uint8_t **streaminfo_start);
+#endif
 
 /**
  * Validate the FLAC extradata.
@@ -106,9 +114,9 @@
  * @param[out] streaminfo_start pointer to start of 34-byte STREAMINFO data.
  * @return 1 if valid, 0 if not valid.
  */
-int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
-                                   enum FLACExtradataFormat *format,
-                                   uint8_t **streaminfo_start);
+int ff_flac_is_extradata_valid(AVCodecContext *avctx,
+                               enum FLACExtradataFormat *format,
+                               uint8_t **streaminfo_start);
 
 /**
  * Calculate an estimate for the maximum frame size based on verbatim mode.
diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index 1333972..34a0a70 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -102,16 +102,16 @@
     if (!avctx->extradata)
         return 0;
 
-    if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo))
+    if (!ff_flac_is_extradata_valid(avctx, &format, &streaminfo))
         return AVERROR_INVALIDDATA;
 
     /* initialize based on the demuxer-supplied streamdata header */
-    avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
+    ff_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
     ret = allocate_buffers(s);
     if (ret < 0)
         return ret;
     flac_set_bps(s);
-    ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps);
+    ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->channels, s->bps);
     s->got_streaminfo = 1;
 
     return 0;
@@ -168,12 +168,12 @@
         metadata_size != FLAC_STREAMINFO_SIZE) {
         return AVERROR_INVALIDDATA;
     }
-    avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
+    ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
     ret = allocate_buffers(s);
     if (ret < 0)
         return ret;
     flac_set_bps(s);
-    ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
+    ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->channels, s->bps);
     s->got_streaminfo = 1;
 
     return 0;
@@ -366,7 +366,7 @@
 
     if (get_bits1(&s->gb)) {
         int left = get_bits_left(&s->gb);
-        if ( left < 0 ||
+        if ( left <= 0 ||
             (left < bps && !show_bits_long(&s->gb, left)) ||
                            !show_bits_long(&s->gb, bps)) {
             av_log(s->avctx, AV_LOG_ERROR,
@@ -472,10 +472,10 @@
         ret = allocate_buffers(s);
         if (ret < 0)
             return ret;
-        ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
         s->got_streaminfo = 1;
         dump_headers(s->avctx, (FLACStreaminfo *)s);
     }
+    ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->channels, s->bps);
 
 //    dump_headers(s->avctx, (FLACStreaminfo *)s);
 
diff --git a/libavcodec/flacdsp.c b/libavcodec/flacdsp.c
index b15bc74..a83eb83 100644
--- a/libavcodec/flacdsp.c
+++ b/libavcodec/flacdsp.c
@@ -85,7 +85,7 @@
 
 }
 
-av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt,
+av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
                              int bps)
 {
     if (bps > 16) {
@@ -127,7 +127,7 @@
     }
 
     if (ARCH_ARM)
-        ff_flacdsp_init_arm(c, fmt, bps);
+        ff_flacdsp_init_arm(c, fmt, channels, bps);
     if (ARCH_X86)
-        ff_flacdsp_init_x86(c, fmt, bps);
+        ff_flacdsp_init_x86(c, fmt, channels, bps);
 }
diff --git a/libavcodec/flacdsp.h b/libavcodec/flacdsp.h
index 14f3466..417381c 100644
--- a/libavcodec/flacdsp.h
+++ b/libavcodec/flacdsp.h
@@ -31,8 +31,8 @@
                        const int32_t coefs[32], int shift);
 } FLACDSPContext;
 
-void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int bps);
-void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int bps);
-void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int bps);
+void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
+void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
+void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
 
 #endif /* AVCODEC_FLACDSP_H */
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index 3b72888..e66ef3d 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -428,7 +428,7 @@
                       s->options.max_prediction_order, FF_LPC_TYPE_LEVINSON);
 
     ff_bswapdsp_init(&s->bdsp);
-    ff_flacdsp_init(&s->flac_dsp, avctx->sample_fmt,
+    ff_flacdsp_init(&s->flac_dsp, avctx->sample_fmt, channels,
                     avctx->bits_per_raw_sample);
 
     dprint_compression_options(s);
diff --git a/libavcodec/flashsv2enc.c b/libavcodec/flashsv2enc.c
index 9735a13..1c016f2 100644
--- a/libavcodec/flashsv2enc.c
+++ b/libavcodec/flashsv2enc.c
@@ -192,7 +192,7 @@
 
     if ((avctx->width > 4095) || (avctx->height > 4095)) {
         av_log(avctx, AV_LOG_ERROR,
-               "Input dimensions too large, input must be max 4096x4096 !\n");
+               "Input dimensions too large, input must be max 4095x4095 !\n");
         return -1;
     }
     if ((avctx->width < 16) || (avctx->height < 16)) {
diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c
index 41ad943..0cd502b 100644
--- a/libavcodec/g2meet.c
+++ b/libavcodec/g2meet.c
@@ -736,8 +736,10 @@
             }
             c->tile_width  = bytestream2_get_be32(&bc);
             c->tile_height = bytestream2_get_be32(&bc);
-            if (!c->tile_width || !c->tile_height ||
-                ((c->tile_width | c->tile_height) & 0xF)) {
+            if (c->tile_width <= 0 || c->tile_height <= 0 ||
+                ((c->tile_width | c->tile_height) & 0xF) ||
+                c->tile_width * 4LL * c->tile_height >= INT_MAX
+            ) {
                 av_log(avctx, AV_LOG_ERROR,
                        "Invalid tile dimensions %dx%d\n",
                        c->tile_width, c->tile_height);
diff --git a/libavcodec/h263.h b/libavcodec/h263.h
index 54ce2a5..29798ba 100644
--- a/libavcodec/h263.h
+++ b/libavcodec/h263.h
@@ -29,6 +29,7 @@
 #if !FF_API_ASPECT_EXTENDED
 #define FF_ASPECT_EXTENDED 15
 #endif
+#define INT_BIT (CHAR_BIT * sizeof(int))
 
 // The defines below define the number of bits that are read at once for
 // reading vlc values. Changing these may improve speed and data cache needs
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index fd2e5a0..33bdd67 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -875,7 +875,7 @@
         if (rotation) {
             av_display_rotation_set((int32_t *)rotation->data, angle);
             av_display_matrix_flip((int32_t *)rotation->data,
-                                   h->sei_vflip, h->sei_hflip);
+                                   h->sei_hflip, h->sei_vflip);
         }
     }
 
diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c
index 6baeedf..1d5f143 100644
--- a/libavcodec/h264_cabac.c
+++ b/libavcodec/h264_cabac.c
@@ -26,6 +26,7 @@
  */
 
 #define CABAC(h) 1
+#define INT_BIT (CHAR_BIT * sizeof(int))
 
 #include "libavutil/attributes.h"
 #include "libavutil/avassert.h"
diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c
index 7feae57..dd406c7 100644
--- a/libavcodec/h264_mb.c
+++ b/libavcodec/h264_mb.c
@@ -49,7 +49,7 @@
     return FFMAX(0, bottom);
 }
 
-static inline void get_lowest_part_y(H264Context *h, int refs[2][48], int n,
+static inline void get_lowest_part_y(H264Context *h, int16_t refs[2][48], int n,
                                      int height, int y_offset, int list0,
                                      int list1, int *nrefs)
 {
@@ -96,7 +96,7 @@
 {
     const int mb_xy   = h->mb_xy;
     const int mb_type = h->cur_pic.mb_type[mb_xy];
-    int refs[2][48];
+    int16_t refs[2][48];
     int nrefs[2] = { 0 };
     int ref, list;
 
diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index fc11409..3e4fb35 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -517,17 +517,22 @@
     int i;
     uint32_t state = -1;
     int has_sps    = 0;
+    int has_pps    = 0;
 
     for (i = 0; i <= buf_size; i++) {
         if ((state & 0xFFFFFF1F) == 0x107)
             has_sps = 1;
+        if ((state & 0xFFFFFF1F) == 0x108)
+            has_pps = 1;
         /*  if ((state&0xFFFFFF1F) == 0x101 ||
          *     (state&0xFFFFFF1F) == 0x102 ||
          *     (state&0xFFFFFF1F) == 0x105) {
          *  }
          */
-        if ((state & 0xFFFFFF00) == 0x100 && (state & 0xFFFFFF1F) != 0x107 &&
-            (state & 0xFFFFFF1F) != 0x108 && (state & 0xFFFFFF1F) != 0x109) {
+        if ((state & 0xFFFFFF00) == 0x100 && ((state & 0xFFFFFF1F) != 0x106 || has_pps) &&
+            (state & 0xFFFFFF1F) != 0x107 && (state & 0xFFFFFF1F) != 0x108 &&
+            (state & 0xFFFFFF1F) != 0x109 && (state & 0xFFFFFF1F) != 0x10d &&
+            (state & 0xFFFFFF1F) != 0x10f) {
             if (has_sps) {
                 while (i > 4 && buf[i - 5] == 0)
                     i--;
@@ -545,7 +550,7 @@
     H264Context *h   = s->priv_data;
     ParseContext *pc = &h->parse_context;
 
-    av_free(pc->buffer);
+    av_freep(&pc->buffer);
     ff_h264_free_context(h);
 }
 
diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c
index 2013670..4070490 100644
--- a/libavcodec/h264_ps.c
+++ b/libavcodec/h264_ps.c
@@ -31,32 +31,12 @@
 #include "internal.h"
 #include "avcodec.h"
 #include "h264.h"
-#include "h264data.h" //FIXME FIXME FIXME (just for zigzag_scan)
+#include "h264data.h"
 #include "golomb.h"
 
 #define MAX_LOG2_MAX_FRAME_NUM    (12 + 4)
 #define MIN_LOG2_MAX_FRAME_NUM    4
 
-static const AVRational pixel_aspect[17] = {
-    {   0,  1 },
-    {   1,  1 },
-    {  12, 11 },
-    {  10, 11 },
-    {  16, 11 },
-    {  40, 33 },
-    {  24, 11 },
-    {  20, 11 },
-    {  32, 11 },
-    {  80, 33 },
-    {  18, 11 },
-    {  15, 11 },
-    {  64, 33 },
-    { 160, 99 },
-    {   4,  3 },
-    {   3,  2 },
-    {   2,  1 },
-};
-
 #define QP(qP, depth) ((qP) + 6 * ((depth) - 8))
 
 #define CHROMA_QP_TABLE_END(d)                                          \
@@ -164,8 +144,8 @@
         if (aspect_ratio_idc == EXTENDED_SAR) {
             sps->sar.num = get_bits(&h->gb, 16);
             sps->sar.den = get_bits(&h->gb, 16);
-        } else if (aspect_ratio_idc < FF_ARRAY_ELEMS(pixel_aspect)) {
-            sps->sar = pixel_aspect[aspect_ratio_idc];
+        } else if (aspect_ratio_idc < FF_ARRAY_ELEMS(ff_h264_pixel_aspect)) {
+            sps->sar = ff_h264_pixel_aspect[aspect_ratio_idc];
         } else {
             av_log(h->avctx, AV_LOG_ERROR, "illegal aspect ratio\n");
             return AVERROR_INVALIDDATA;
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 7867766..25f7726 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -585,6 +585,17 @@
         h->mb_type_pool      = NULL;
         h->ref_index_pool    = NULL;
         h->motion_val_pool   = NULL;
+        h->intra4x4_pred_mode= NULL;
+        h->non_zero_count    = NULL;
+        h->slice_table_base  = NULL;
+        h->slice_table       = NULL;
+        h->cbp_table         = NULL;
+        h->chroma_pred_mode_table = NULL;
+        memset(h->mvd_table, 0, sizeof(h->mvd_table));
+        h->direct_table      = NULL;
+        h->list_counts       = NULL;
+        h->mb2b_xy           = NULL;
+        h->mb2br_xy          = NULL;
         for (i = 0; i < 2; i++) {
             h->rbsp_buffer[i] = NULL;
             h->rbsp_buffer_size[i] = 0;
diff --git a/libavcodec/h264data.h b/libavcodec/h264data.h
index 38f3258..95ea385 100644
--- a/libavcodec/h264data.h
+++ b/libavcodec/h264data.h
@@ -167,4 +167,23 @@
     { MB_TYPE_8x8   | MB_TYPE_P0L0 | MB_TYPE_P0L1 | MB_TYPE_P1L0 | MB_TYPE_P1L1, 4, },
 };
 
+static const AVRational ff_h264_pixel_aspect[17] = {
+    {   0,  1 },
+    {   1,  1 },
+    {  12, 11 },
+    {  10, 11 },
+    {  16, 11 },
+    {  40, 33 },
+    {  24, 11 },
+    {  20, 11 },
+    {  32, 11 },
+    {  80, 33 },
+    {  18, 11 },
+    {  15, 11 },
+    {  64, 33 },
+    { 160, 99 },
+    {   4,  3 },
+    {   3,  2 },
+    {   2,  1 },
+};
 #endif /* AVCODEC_H264DATA_H */
diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c
index 36f147a..d4dc52c 100644
--- a/libavcodec/hevc.c
+++ b/libavcodec/hevc.c
@@ -865,8 +865,7 @@
 static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                               int xBase, int yBase, int cb_xBase, int cb_yBase,
                               int log2_cb_size, int log2_trafo_size,
-                              int trafo_depth, int blk_idx,
-                              int cbf_luma, int *cbf_cb, int *cbf_cr)
+                              int blk_idx, int cbf_luma, int *cbf_cb, int *cbf_cr)
 {
     HEVCLocalContext *lc = s->HEVClc;
     const int log2_trafo_size_c = log2_trafo_size - s->sps->hshift[1];
@@ -1183,7 +1182,7 @@
         }
 
         ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase,
-                                 log2_cb_size, log2_trafo_size, trafo_depth,
+                                 log2_cb_size, log2_trafo_size,
                                  blk_idx, cbf_luma, cbf_cb, cbf_cr);
         if (ret < 0)
             return ret;
@@ -1571,12 +1570,57 @@
 static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref,
                                 const Mv *mv, int y0, int height)
 {
-    int y = (mv->y >> 2) + y0 + height + 9;
+    int y = FFMAX(0, (mv->y >> 2) + y0 + height + 9);
 
     if (s->threads_type == FF_THREAD_FRAME )
         ff_thread_await_progress(&ref->tf, y, 0);
 }
 
+static void hevc_luma_mv_mpv_mode(HEVCContext *s, int x0, int y0, int nPbW,
+                                  int nPbH, int log2_cb_size, int part_idx,
+                                  int merge_idx, MvField *mv)
+{
+    HEVCLocalContext *lc = s->HEVClc;
+    enum InterPredIdc inter_pred_idc = PRED_L0;
+    int mvp_flag;
+
+    ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH);
+    mv->pred_flag = 0;
+    if (s->sh.slice_type == B_SLICE)
+        inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH);
+
+    if (inter_pred_idc != PRED_L1) {
+        if (s->sh.nb_refs[L0])
+            mv->ref_idx[0]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]);
+
+        mv->pred_flag = PF_L0;
+        ff_hevc_hls_mvd_coding(s, x0, y0, 0);
+        mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
+        ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+                                 part_idx, merge_idx, mv, mvp_flag, 0);
+        mv->mv[0].x += lc->pu.mvd.x;
+        mv->mv[0].y += lc->pu.mvd.y;
+    }
+
+    if (inter_pred_idc != PRED_L0) {
+        if (s->sh.nb_refs[L1])
+            mv->ref_idx[1]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]);
+
+        if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) {
+            AV_ZERO32(&lc->pu.mvd);
+        } else {
+            ff_hevc_hls_mvd_coding(s, x0, y0, 1);
+        }
+
+        mv->pred_flag += PF_L1;
+        mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
+        ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+                                 part_idx, merge_idx, mv, mvp_flag, 1);
+        mv->mv[1].x += lc->pu.mvd.x;
+        mv->mv[1].y += lc->pu.mvd.y;
+    }
+}
+
 static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
                                 int nPbW, int nPbH,
                                 int log2_cb_size, int partIdx, int idx)
@@ -1600,96 +1644,34 @@
     int min_cb_width     = s->sps->min_cb_width;
     int x_cb             = x0 >> log2_min_cb_size;
     int y_cb             = y0 >> log2_min_cb_size;
-    int ref_idx[2];
-    int mvp_flag[2];
     int x_pu, y_pu;
     int i, j;
 
-    if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) {
+    int skip_flag = SAMPLE_CTB(s->skip_flag, x_cb, y_cb);
+
+    if (!skip_flag)
+        lc->pu.merge_flag = ff_hevc_merge_flag_decode(s);
+
+    if (skip_flag || lc->pu.merge_flag) {
         if (s->sh.max_num_merge_cand > 1)
             merge_idx = ff_hevc_merge_idx_decode(s);
         else
             merge_idx = 0;
 
-        ff_hevc_luma_mv_merge_mode(s, x0, y0,
-                                   1 << log2_cb_size,
-                                   1 << log2_cb_size,
-                                   log2_cb_size, partIdx,
-                                   merge_idx, &current_mv);
-        x_pu = x0 >> s->sps->log2_min_pu_size;
-        y_pu = y0 >> s->sps->log2_min_pu_size;
-
-        for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++)
-            for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++)
-                tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv;
-    } else { /* MODE_INTER */
-        lc->pu.merge_flag = ff_hevc_merge_flag_decode(s);
-        if (lc->pu.merge_flag) {
-            if (s->sh.max_num_merge_cand > 1)
-                merge_idx = ff_hevc_merge_idx_decode(s);
-            else
-                merge_idx = 0;
-
-            ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
-                                       partIdx, merge_idx, &current_mv);
-            x_pu = x0 >> s->sps->log2_min_pu_size;
-            y_pu = y0 >> s->sps->log2_min_pu_size;
-
-            for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++)
-                for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++)
-                    tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv;
-        } else {
-            enum InterPredIdc inter_pred_idc = PRED_L0;
-            ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH);
-            current_mv.pred_flag = 0;
-            if (s->sh.slice_type == B_SLICE)
-                inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH);
-
-            if (inter_pred_idc != PRED_L1) {
-                if (s->sh.nb_refs[L0]) {
-                    ref_idx[0] = ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]);
-                    current_mv.ref_idx[0] = ref_idx[0];
-                }
-                current_mv.pred_flag = PF_L0;
-                ff_hevc_hls_mvd_coding(s, x0, y0, 0);
-                mvp_flag[0] = ff_hevc_mvp_lx_flag_decode(s);
-                ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
-                                         partIdx, merge_idx, &current_mv,
-                                         mvp_flag[0], 0);
-                current_mv.mv[0].x += lc->pu.mvd.x;
-                current_mv.mv[0].y += lc->pu.mvd.y;
-            }
-
-            if (inter_pred_idc != PRED_L0) {
-                if (s->sh.nb_refs[L1]) {
-                    ref_idx[1] = ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]);
-                    current_mv.ref_idx[1] = ref_idx[1];
-                }
-
-                if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) {
-                    AV_ZERO32(&lc->pu.mvd);
-                } else {
-                    ff_hevc_hls_mvd_coding(s, x0, y0, 1);
-                }
-
-                current_mv.pred_flag += PF_L1;
-                mvp_flag[1] = ff_hevc_mvp_lx_flag_decode(s);
-                ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
-                                         partIdx, merge_idx, &current_mv,
-                                         mvp_flag[1], 1);
-                current_mv.mv[1].x += lc->pu.mvd.x;
-                current_mv.mv[1].y += lc->pu.mvd.y;
-            }
-
-            x_pu = x0 >> s->sps->log2_min_pu_size;
-            y_pu = y0 >> s->sps->log2_min_pu_size;
-
-            for(j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++)
-                for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++)
-                    tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv;
-        }
+        ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+                                   partIdx, merge_idx, &current_mv);
+    } else {
+        hevc_luma_mv_mpv_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+                              partIdx, merge_idx, &current_mv);
     }
 
+    x_pu = x0 >> s->sps->log2_min_pu_size;
+    y_pu = y0 >> s->sps->log2_min_pu_size;
+
+    for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++)
+        for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++)
+            tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv;
+
     if (current_mv.pred_flag & PF_L0) {
         ref0 = refPicList[0].ref[current_mv.ref_idx[0]];
         if (!ref0)
@@ -1962,11 +1944,9 @@
 
     lc->cu.x                = x0;
     lc->cu.y                = y0;
-    lc->cu.rqt_root_cbf     = 1;
     lc->cu.pred_mode        = MODE_INTRA;
     lc->cu.part_mode        = PART_2Nx2N;
     lc->cu.intra_split_flag = 0;
-    lc->cu.pcm_flag         = 0;
 
     SAMPLE_CTB(s->skip_flag, x_cb, y_cb) = 0;
     for (x = 0; x < 4; x++)
@@ -2002,6 +1982,8 @@
         if (!s->sh.disable_deblocking_filter_flag)
             ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
     } else {
+        int pcm_flag = 0;
+
         if (s->sh.slice_type != I_SLICE)
             lc->cu.pred_mode = ff_hevc_pred_mode_decode(s);
         if (lc->cu.pred_mode != MODE_INTRA ||
@@ -2015,9 +1997,9 @@
             if (lc->cu.part_mode == PART_2Nx2N && s->sps->pcm_enabled_flag &&
                 log2_cb_size >= s->sps->pcm.log2_min_pcm_cb_size &&
                 log2_cb_size <= s->sps->pcm.log2_max_pcm_cb_size) {
-                lc->cu.pcm_flag = ff_hevc_pcm_flag_decode(s);
+                pcm_flag = ff_hevc_pcm_flag_decode(s);
             }
-            if (lc->cu.pcm_flag) {
+            if (pcm_flag) {
                 intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
                 ret = hls_pcm_sample(s, x0, y0, log2_cb_size);
                 if (s->sps->pcm.loop_filter_disable_flag)
@@ -2067,12 +2049,14 @@
             }
         }
 
-        if (!lc->cu.pcm_flag) {
+        if (!pcm_flag) {
+            int rqt_root_cbf = 1;
+
             if (lc->cu.pred_mode != MODE_INTRA &&
                 !(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) {
-                lc->cu.rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s);
+                rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s);
             }
-            if (lc->cu.rqt_root_cbf) {
+            if (rqt_root_cbf) {
                 const static int cbf[2] = { 0 };
                 lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ?
                                          s->sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag :
@@ -2530,7 +2514,7 @@
 
         av_display_rotation_set((int32_t *)rotation->data, angle);
         av_display_matrix_flip((int32_t *)rotation->data,
-                               s->sei_vflip, s->sei_hflip);
+                               s->sei_hflip, s->sei_vflip);
     }
 
     return 0;
diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h
index 7205a78..8fdefbb 100644
--- a/libavcodec/hevc.h
+++ b/libavcodec/hevc.h
@@ -638,10 +638,6 @@
     enum PredMode pred_mode;    ///< PredMode
     enum PartMode part_mode;    ///< PartMode
 
-    uint8_t rqt_root_cbf;
-
-    uint8_t pcm_flag;
-
     // Inferred parameters
     uint8_t intra_split_flag;   ///< IntraSplitFlag
     uint8_t max_trafo_depth;    ///< MaxTrafoDepth
diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c
index 826d084..318e7a2 100644
--- a/libavcodec/hevc_mvs.c
+++ b/libavcodec/hevc_mvs.c
@@ -408,7 +408,7 @@
     // temporal motion vector candidate
     if (s->sh.slice_temporal_mvp_enabled_flag &&
         nb_merge_cand < s->sh.max_num_merge_cand) {
-        Mv mv_l0_col, mv_l1_col;
+        Mv mv_l0_col = { 0 }, mv_l1_col = { 0 };
         int available_l0 = temporal_luma_motion_vector(s, x0, y0, nPbW, nPbH,
                                                        0, &mv_l0_col, 0);
         int available_l1 = (s->sh.slice_type == B_SLICE) ?
diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c
index 4e1c561..6b5e13f 100644
--- a/libavcodec/hevc_ps.c
+++ b/libavcodec/hevc_ps.c
@@ -951,6 +951,11 @@
     sps->long_term_ref_pics_present_flag = get_bits1(gb);
     if (sps->long_term_ref_pics_present_flag) {
         sps->num_long_term_ref_pics_sps = get_ue_golomb_long(gb);
+        if (sps->num_long_term_ref_pics_sps > 31U) {
+            av_log(0, AV_LOG_ERROR, "num_long_term_ref_pics_sps %d is out of range.\n",
+                   sps->num_long_term_ref_pics_sps);
+            goto err;
+        }
         for (i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
             sps->lt_ref_pic_poc_lsb_sps[i]       = get_bits(gb, sps->log2_max_poc_lsb);
             sps->used_by_curr_pic_lt_sps_flag[i] = get_bits1(gb);
@@ -1025,10 +1030,8 @@
         }
         av_log(s->avctx, AV_LOG_WARNING,
                "Displaying the whole video surface.\n");
-        sps->pic_conf_win.left_offset   =
-        sps->pic_conf_win.right_offset  =
-        sps->pic_conf_win.top_offset    =
-        sps->pic_conf_win.bottom_offset = 0;
+        memset(&sps->pic_conf_win, 0, sizeof(sps->pic_conf_win));
+        memset(&sps->output_window, 0, sizeof(sps->output_window));
         sps->output_width               = sps->width;
         sps->output_height              = sps->height;
     }
@@ -1375,7 +1378,8 @@
         int pps_range_extensions_flag = get_bits1(gb);
         /* int pps_extension_7bits = */ get_bits(gb, 7);
         if (sps->ptl.general_ptl.profile_idc == FF_PROFILE_HEVC_REXT && pps_range_extensions_flag) {
-            pps_range_extensions(s, pps, sps);
+            if ((ret = pps_range_extensions(s, pps, sps)) < 0)
+                goto err;
         }
     }
 
diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c
index 8a843f5..360a509 100644
--- a/libavcodec/hevcdsp_template.c
+++ b/libavcodec/hevcdsp_template.c
@@ -42,16 +42,16 @@
     }
 }
 
-static void FUNC(transform_add4x4)(uint8_t *_dst, int16_t *coeffs,
-                                       ptrdiff_t stride)
+static av_always_inline void FUNC(transquant_bypass)(uint8_t *_dst, int16_t *coeffs,
+                                                     ptrdiff_t stride, int size)
 {
     int x, y;
     pixel *dst = (pixel *)_dst;
 
     stride /= sizeof(pixel);
 
-    for (y = 0; y < 4; y++) {
-        for (x = 0; x < 4; x++) {
+    for (y = 0; y < size; y++) {
+        for (x = 0; x < size; x++) {
             dst[x] = av_clip_pixel(dst[x] + *coeffs);
             coeffs++;
         }
@@ -59,55 +59,28 @@
     }
 }
 
+static void FUNC(transform_add4x4)(uint8_t *_dst, int16_t *coeffs,
+                                       ptrdiff_t stride)
+{
+    FUNC(transquant_bypass)(_dst, coeffs, stride, 4);
+}
+
 static void FUNC(transform_add8x8)(uint8_t *_dst, int16_t *coeffs,
                                        ptrdiff_t stride)
 {
-    int x, y;
-    pixel *dst = (pixel *)_dst;
-
-    stride /= sizeof(pixel);
-
-    for (y = 0; y < 8; y++) {
-        for (x = 0; x < 8; x++) {
-            dst[x] = av_clip_pixel(dst[x] + *coeffs);
-            coeffs++;
-        }
-        dst += stride;
-    }
+    FUNC(transquant_bypass)(_dst, coeffs, stride, 8);
 }
 
 static void FUNC(transform_add16x16)(uint8_t *_dst, int16_t *coeffs,
                                          ptrdiff_t stride)
 {
-    int x, y;
-    pixel *dst = (pixel *)_dst;
-
-    stride /= sizeof(pixel);
-
-    for (y = 0; y < 16; y++) {
-        for (x = 0; x < 16; x++) {
-            dst[x] = av_clip_pixel(dst[x] + *coeffs);
-            coeffs++;
-        }
-        dst += stride;
-    }
+    FUNC(transquant_bypass)(_dst, coeffs, stride, 16);
 }
 
 static void FUNC(transform_add32x32)(uint8_t *_dst, int16_t *coeffs,
                                          ptrdiff_t stride)
 {
-    int x, y;
-    pixel *dst = (pixel *)_dst;
-
-    stride /= sizeof(pixel);
-
-    for (y = 0; y < 32; y++) {
-        for (x = 0; x < 32; x++) {
-            dst[x] = av_clip_pixel(dst[x] + *coeffs);
-            coeffs++;
-        }
-        dst += stride;
-    }
+    FUNC(transquant_bypass)(_dst, coeffs, stride, 32);
 }
 
 
diff --git a/libavcodec/hnm4video.c b/libavcodec/hnm4video.c
index d8c51d0..31995bc 100644
--- a/libavcodec/hnm4video.c
+++ b/libavcodec/hnm4video.c
@@ -22,6 +22,7 @@
 
 #include <string.h>
 
+#include "libavutil/imgutils.h"
 #include "libavutil/internal.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
@@ -453,6 +454,7 @@
 static av_cold int hnm_decode_init(AVCodecContext *avctx)
 {
     Hnm4VideoContext *hnm = avctx->priv_data;
+    int ret;
 
     if (avctx->extradata_size < 1) {
         av_log(avctx, AV_LOG_ERROR,
@@ -460,6 +462,10 @@
         return AVERROR_INVALIDDATA;
     }
 
+    ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
+    if (ret < 0)
+        return ret;
+
     hnm->version   = avctx->extradata[0];
     avctx->pix_fmt = AV_PIX_FMT_PAL8;
     hnm->width     = avctx->width;
diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c
index 3b2b0f7..98c6128 100644
--- a/libavcodec/huffyuvdec.c
+++ b/libavcodec/huffyuvdec.c
@@ -272,6 +272,20 @@
     return 0;
 }
 
+static av_cold int decode_end(AVCodecContext *avctx)
+{
+    HYuvContext *s = avctx->priv_data;
+    int i;
+
+    ff_huffyuv_common_end(s);
+    av_freep(&s->bitstream_buffer);
+
+    for (i = 0; i < 8; i++)
+        ff_free_vlc(&s->vlc[i]);
+
+    return 0;
+}
+
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     HYuvContext *s = avctx->priv_data;
@@ -327,7 +341,7 @@
 
         if ((ret = read_huffman_tables(s, avctx->extradata + 4,
                                        avctx->extradata_size - 4)) < 0)
-            return ret;
+            goto error;
     } else {
         switch (avctx->bits_per_coded_sample & 7) {
         case 1:
@@ -355,7 +369,7 @@
         s->context       = 0;
 
         if ((ret = read_old_huffman_tables(s)) < 0)
-            return ret;
+            goto error;
     }
 
     if (s->version <= 2) {
@@ -383,7 +397,8 @@
             s->alpha = 1;
             break;
         default:
-            return AVERROR_INVALIDDATA;
+            ret = AVERROR_INVALIDDATA;
+            goto error;
         }
         av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt,
                                          &s->chroma_h_shift,
@@ -520,7 +535,8 @@
             avctx->pix_fmt = AV_PIX_FMT_YUVA420P16;
             break;
         default:
-            return AVERROR_INVALIDDATA;
+            ret = AVERROR_INVALIDDATA;
+            goto error;
         }
     }
 
@@ -528,21 +544,26 @@
 
     if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUV420P) && avctx->width & 1) {
         av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n");
-        return AVERROR_INVALIDDATA;
+        ret = AVERROR_INVALIDDATA;
+        goto error;
     }
     if (s->predictor == MEDIAN && avctx->pix_fmt == AV_PIX_FMT_YUV422P &&
         avctx->width % 4) {
         av_log(avctx, AV_LOG_ERROR, "width must be a multiple of 4 "
                "for this combination of colorspace and predictor type.\n");
-        return AVERROR_INVALIDDATA;
+        ret = AVERROR_INVALIDDATA;
+        goto error;
     }
 
     if ((ret = ff_huffyuv_alloc_temp(s)) < 0) {
         ff_huffyuv_common_end(s);
-        return ret;
+        goto error;
     }
 
     return 0;
+  error:
+    decode_end(avctx);
+    return ret;
 }
 
 static av_cold int decode_init_thread_copy(AVCodecContext *avctx)
@@ -1181,11 +1202,10 @@
                     if (s->predictor == PLANE) {
                         if (s->bitstream_bpp != 32)
                             left[A] = 0;
-                        if ((y & s->interlaced) == 0 &&
-                            y < s->height - 1 - s->interlaced) {
+                        if (y < s->height - 1 - s->interlaced) {
                             s->hdsp.add_bytes(p->data[0] + p->linesize[0] * y,
                                               p->data[0] + p->linesize[0] * y +
-                                              fake_ystride, fake_ystride);
+                                              fake_ystride, 4 * width);
                         }
                     }
                 }
@@ -1209,20 +1229,6 @@
     return (get_bits_count(&s->gb) + 31) / 32 * 4 + table_size;
 }
 
-static av_cold int decode_end(AVCodecContext *avctx)
-{
-    HYuvContext *s = avctx->priv_data;
-    int i;
-
-    ff_huffyuv_common_end(s);
-    av_freep(&s->bitstream_buffer);
-
-    for (i = 0; i < 8; i++)
-        ff_free_vlc(&s->vlc[i]);
-
-    return 0;
-}
-
 AVCodec ff_huffyuv_decoder = {
     .name             = "huffyuv",
     .long_name        = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"),
diff --git a/libavcodec/huffyuvdsp.h b/libavcodec/huffyuvdsp.h
index 78b2bca..db37728 100644
--- a/libavcodec/huffyuvdsp.h
+++ b/libavcodec/huffyuvdsp.h
@@ -20,6 +20,7 @@
 #define AVCODEC_HUFFYUVDSP_H
 
 #include <stdint.h>
+#include "config.h"
 
 #if HAVE_BIGENDIAN
 #define B 3
diff --git a/libavcodec/imc.c b/libavcodec/imc.c
index dcedbd6..6c9ffd7 100644
--- a/libavcodec/imc.c
+++ b/libavcodec/imc.c
@@ -96,7 +96,7 @@
     GetBitContext gb;
 
     BswapDSPContext bdsp;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FFTContext fft;
     DECLARE_ALIGNED(32, FFTComplex, samples)[COEFFS / 2];
     float *out_samples;
@@ -256,7 +256,13 @@
         return ret;
     }
     ff_bswapdsp_init(&q->bdsp);
-    avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    q->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!q->fdsp) {
+        ff_fft_end(&q->fft);
+
+        return AVERROR(ENOMEM);
+    }
+
     avctx->sample_fmt     = AV_SAMPLE_FMT_FLTP;
     avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO
                                                  : AV_CH_LAYOUT_STEREO;
@@ -1044,7 +1050,7 @@
     }
 
     if (avctx->channels == 2) {
-        q->fdsp.butterflies_float((float *)frame->extended_data[0],
+        q->fdsp->butterflies_float((float *)frame->extended_data[0],
                                   (float *)frame->extended_data[1], COEFFS);
     }
 
@@ -1053,12 +1059,12 @@
     return IMC_BLOCK_SIZE * avctx->channels;
 }
 
-
 static av_cold int imc_decode_close(AVCodecContext * avctx)
 {
     IMCContext *q = avctx->priv_data;
 
     ff_fft_end(&q->fft);
+    av_freep(&q->fdsp);
 
     return 0;
 }
diff --git a/libavcodec/indeo2.c b/libavcodec/indeo2.c
index cccac44..39735c2 100644
--- a/libavcodec/indeo2.c
+++ b/libavcodec/indeo2.c
@@ -54,15 +54,13 @@
     int i;
     int j;
     int out = 0;
-    int c;
-    int t;
 
     if (width & 1)
         return AVERROR_INVALIDDATA;
 
     /* first line contain absolute values, other lines contain deltas */
     while (out < width) {
-        c = ir2_get_code(&ctx->gb);
+        int c = ir2_get_code(&ctx->gb);
         if (c >= 0x80) { /* we have a run */
             c -= 0x7F;
             if (out + c*2 > width)
@@ -79,7 +77,7 @@
     for (j = 1; j < height; j++) {
         out = 0;
         while (out < width) {
-            c = ir2_get_code(&ctx->gb);
+            int c = ir2_get_code(&ctx->gb);
             if (c >= 0x80) { /* we have a skip */
                 c -= 0x7F;
                 if (out + c*2 > width)
@@ -89,7 +87,7 @@
                     out++;
                 }
             } else { /* add two deltas from table */
-                t        = dst[out - pitch] + (table[c * 2] - 128);
+                int t    = dst[out - pitch] + (table[c * 2] - 128);
                 t        = av_clip_uint8(t);
                 dst[out] = t;
                 out++;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index dcb2113..f4e12e8 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -35,6 +35,8 @@
 
 #define FF_SANE_NB_CHANNELS 63U
 
+#define FF_SIGNBIT(x) ((x) >> CHAR_BIT * sizeof(x) - 1)
+
 #if HAVE_AVX
 #   define STRIDE_ALIGN 32
 #elif HAVE_SIMD_ALIGN_16
diff --git a/libavcodec/jacosubdec.c b/libavcodec/jacosubdec.c
index ef999ca..2f94956 100644
--- a/libavcodec/jacosubdec.c
+++ b/libavcodec/jacosubdec.c
@@ -29,6 +29,7 @@
 #include "jacosub.h"
 #include "libavutil/avstring.h"
 #include "libavutil/bprint.h"
+#include "libavutil/time_internal.h"
 
 #undef time
 
@@ -44,11 +45,7 @@
     time_t now = time(0);
     struct tm ltime;
 
-#if HAVE_LOCALTIME_R
     localtime_r(&now, &ltime);
-#else
-    ltime = *localtime(&now);
-#endif
     strftime(buf, sizeof(buf), arg, &ltime);
     av_bprintf(dst, "%s", buf);
     return 0;
diff --git a/libavcodec/jpeg2000.c b/libavcodec/jpeg2000.c
index ede1a79..644e25d 100644
--- a/libavcodec/jpeg2000.c
+++ b/libavcodec/jpeg2000.c
@@ -369,16 +369,18 @@
             for (j = 0; j < 2; j++)
                 band->coord[1][j] = ff_jpeg2000_ceildiv(band->coord[1][j], dy);
 
-            band->prec = av_mallocz_array(reslevel->num_precincts_x *
-                                          (uint64_t)reslevel->num_precincts_y,
-                                          sizeof(*band->prec));
+            if (reslevel->num_precincts_x * (uint64_t)reslevel->num_precincts_y > INT_MAX) {
+                band->prec = NULL;
+                return AVERROR(ENOMEM);
+            }
+            nb_precincts = reslevel->num_precincts_x * reslevel->num_precincts_y;
+            band->prec = av_mallocz_array(nb_precincts, sizeof(*band->prec));
             if (!band->prec)
                 return AVERROR(ENOMEM);
 
-            nb_precincts = reslevel->num_precincts_x * reslevel->num_precincts_y;
-
             for (precno = 0; precno < nb_precincts; precno++) {
                 Jpeg2000Prec *prec = band->prec + precno;
+                int nb_codeblocks;
 
                 /* TODO: Explain formula for JPEG200 DCINEMA. */
                 /* TODO: Verify with previous count of codeblocks per band */
@@ -425,12 +427,15 @@
                 if (!prec->zerobits)
                     return AVERROR(ENOMEM);
 
-                prec->cblk = av_mallocz_array(prec->nb_codeblocks_width *
-                                              (uint64_t)prec->nb_codeblocks_height,
-                                              sizeof(*prec->cblk));
+                if (prec->nb_codeblocks_width * (uint64_t)prec->nb_codeblocks_height > INT_MAX) {
+                    prec->cblk = NULL;
+                    return AVERROR(ENOMEM);
+                }
+                nb_codeblocks = prec->nb_codeblocks_width * prec->nb_codeblocks_height;
+                prec->cblk = av_mallocz_array(nb_codeblocks, sizeof(*prec->cblk));
                 if (!prec->cblk)
                     return AVERROR(ENOMEM);
-                for (cblkno = 0; cblkno < prec->nb_codeblocks_width * prec->nb_codeblocks_height; cblkno++) {
+                for (cblkno = 0; cblkno < nb_codeblocks; cblkno++) {
                     Jpeg2000Cblk *cblk = prec->cblk + cblkno;
                     uint16_t Cx0, Cy0;
 
diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c
index a08d7fd..2c6d70c 100644
--- a/libavcodec/lagarith.c
+++ b/libavcodec/lagarith.c
@@ -128,7 +128,7 @@
     }
 
     val  = get_bits_long(gb, bits);
-    val |= 1 << bits;
+    val |= 1U << bits;
 
     *value = val - 1;
 
@@ -675,10 +675,10 @@
         lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height,
                                p->linesize[0], buf + offset_ry,
                                buf_size - offset_ry);
-        lag_decode_arith_plane(l, p->data[1], avctx->width / 2,
+        lag_decode_arith_plane(l, p->data[1], (avctx->width + 1) / 2,
                                avctx->height, p->linesize[1],
                                buf + offset_gu, buf_size - offset_gu);
-        lag_decode_arith_plane(l, p->data[2], avctx->width / 2,
+        lag_decode_arith_plane(l, p->data[2], (avctx->width + 1) / 2,
                                avctx->height, p->linesize[2],
                                buf + offset_bv, buf_size - offset_bv);
         break;
@@ -702,11 +702,11 @@
         lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height,
                                p->linesize[0], buf + offset_ry,
                                buf_size - offset_ry);
-        lag_decode_arith_plane(l, p->data[2], avctx->width / 2,
-                               avctx->height / 2, p->linesize[2],
+        lag_decode_arith_plane(l, p->data[2], (avctx->width + 1) / 2,
+                               (avctx->height + 1) / 2, p->linesize[2],
                                buf + offset_gu, buf_size - offset_gu);
-        lag_decode_arith_plane(l, p->data[1], avctx->width / 2,
-                               avctx->height / 2, p->linesize[1],
+        lag_decode_arith_plane(l, p->data[1], (avctx->width + 1) / 2,
+                               (avctx->height + 1) / 2, p->linesize[1],
                                buf + offset_bv, buf_size - offset_bv);
         break;
     default:
diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c
index ca62b42..1d94041 100644
--- a/libavcodec/lcldec.c
+++ b/libavcodec/lcldec.c
@@ -180,6 +180,7 @@
     int uqvq, ret;
     unsigned int mthread_inlen, mthread_outlen;
     unsigned int len = buf_size;
+    int linesize;
 
     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
         return ret;
@@ -191,7 +192,7 @@
     case AV_CODEC_ID_MSZH:
         switch (c->compression) {
         case COMP_MSZH:
-            if (c->imgtype == IMGTYPE_RGB24 && len == width * height * 3 ||
+            if (c->imgtype == IMGTYPE_RGB24 && len == FFALIGN(width * 3, 4) * height ||
                 c->imgtype == IMGTYPE_YUV111 && len == width * height * 3) {
                 ;
             } else if (c->flags & FLAG_MULTITHREAD) {
@@ -411,10 +412,11 @@
         }
         break;
     case IMGTYPE_RGB24:
+        linesize = len < FFALIGN(3 * width, 4) * height ? 3 * width : FFALIGN(3 * width, 4);
         for (row = height - 1; row >= 0; row--) {
             pixel_ptr = row * frame->linesize[0];
             memcpy(outptr + pixel_ptr, encoded, 3 * width);
-            encoded += 3 * width;
+            encoded += linesize;
         }
         break;
     case IMGTYPE_YUV411:
diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c
index e4bae1a..90cd956 100644
--- a/libavcodec/libfdk-aacdec.c
+++ b/libavcodec/libfdk-aacdec.c
@@ -25,6 +25,12 @@
 #include "avcodec.h"
 #include "internal.h"
 
+/* The version macro is introduced the same time as the setting enum was
+ * changed, so this check should suffice. */
+#ifndef AACDECODER_LIB_VL0
+#define AAC_PCM_MAX_OUTPUT_CHANNELS AAC_PCM_OUTPUT_CHANNELS
+#endif
+
 enum ConcealMethod {
     CONCEAL_METHOD_SPECTRAL_MUTING      =  0,
     CONCEAL_METHOD_NOISE_SUBSTITUTION   =  1,
@@ -76,7 +82,7 @@
 {
     FDKAACDecContext *s   = avctx->priv_data;
     CStreamInfo *info     = aacDecoder_GetStreamInfo(s->handle);
-    int channel_counts[9] = { 0 };
+    int channel_counts[0x24] = { 0 };
     int i, ch_error       = 0;
     uint64_t ch_layout    = 0;
 
@@ -94,7 +100,7 @@
 
     for (i = 0; i < info->numChannels; i++) {
         AUDIO_CHANNEL_TYPE ctype = info->pChannelType[i];
-        if (ctype <= ACT_NONE || ctype > ACT_TOP) {
+        if (ctype <= ACT_NONE || ctype > FF_ARRAY_ELEMS(channel_counts)) {
             av_log(avctx, AV_LOG_WARNING, "unknown channel type\n");
             break;
         }
@@ -239,7 +245,7 @@
         }
 
         if (downmix_channels != -1) {
-            if (aacDecoder_SetParam(s->handle, AAC_PCM_OUTPUT_CHANNELS,
+            if (aacDecoder_SetParam(s->handle, AAC_PCM_MAX_OUTPUT_CHANNELS,
                                     downmix_channels) != AAC_DEC_OK) {
                av_log(avctx, AV_LOG_WARNING, "Unable to set output channels in the decoder\n");
             } else {
diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c
index d8a444d..e33919b 100644
--- a/libavcodec/libmp3lame.c
+++ b/libavcodec/libmp3lame.c
@@ -52,7 +52,7 @@
     int abr;
     float *samples_flt[2];
     AudioFrameQueue afq;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
 } LAMEContext;
 
 
@@ -79,6 +79,7 @@
     av_freep(&s->samples_flt[0]);
     av_freep(&s->samples_flt[1]);
     av_freep(&s->buffer);
+    av_freep(&s->fdsp);
 
     ff_af_queue_close(&s->afq);
 
@@ -158,7 +159,12 @@
     if (ret < 0)
         goto error;
 
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp) {
+        ret = AVERROR(ENOMEM);
+        goto error;
+    }
+
 
     return 0;
 error:
@@ -197,7 +203,7 @@
                 return AVERROR(EINVAL);
             }
             for (ch = 0; ch < avctx->channels; ch++) {
-                s->fdsp.vector_fmul_scalar(s->samples_flt[ch],
+                s->fdsp->vector_fmul_scalar(s->samples_flt[ch],
                                            (const float *)frame->data[ch],
                                            32768.0f,
                                            FFALIGN(frame->nb_samples, 8));
diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c
index 5203729..6bb4862 100644
--- a/libavcodec/libopusenc.c
+++ b/libavcodec/libopusenc.c
@@ -170,10 +170,11 @@
 
     /* FIXME: Opus can handle up to 255 channels. However, the mapping for
      * anything greater than 8 is undefined. */
-    if (avctx->channels > 8)
-        av_log(avctx, AV_LOG_WARNING,
+    if (avctx->channels > 8) {
+        av_log(avctx, AV_LOG_ERROR,
                "Channel layout undefined for %d channels.\n", avctx->channels);
-
+        return AVERROR_PATCHWELCOME;
+    }
     if (!avctx->bit_rate) {
         /* Sane default copied from opusenc */
         avctx->bit_rate = 64000 * opus->stream_count +
@@ -316,7 +317,9 @@
     int discard_padding;
 
     if (frame) {
-        ff_af_queue_add(&opus->afq, frame);
+        ret = ff_af_queue_add(&opus->afq, frame);
+        if (ret < 0)
+            return ret;
         if (frame->nb_samples < opus->opts.packet_size) {
             audio = opus->samples;
             memcpy(audio, frame->data[0], frame->nb_samples * sample_size);
diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c
index 5e149a5..a5f52d1 100644
--- a/libavcodec/libspeexdec.c
+++ b/libavcodec/libspeexdec.c
@@ -33,6 +33,7 @@
     SpeexStereoState stereo;
     void *dec_state;
     int frame_size;
+    int pktsize;
 } LibSpeexContext;
 
 
@@ -50,14 +51,20 @@
             av_log(avctx, AV_LOG_WARNING, "Invalid Speex header\n");
     }
     if (avctx->codec_tag == MKTAG('S', 'P', 'X', 'N')) {
+        int quality;
         if (!avctx->extradata || avctx->extradata && avctx->extradata_size < 47) {
             av_log(avctx, AV_LOG_ERROR, "Missing or invalid extradata.\n");
             return AVERROR_INVALIDDATA;
         }
-        if (avctx->extradata[37] != 10) {
-            av_log(avctx, AV_LOG_ERROR, "Unsupported quality mode.\n");
+
+        quality = avctx->extradata[37];
+        if (quality > 10) {
+            av_log(avctx, AV_LOG_ERROR, "Unsupported quality mode %d.\n", quality);
             return AVERROR_PATCHWELCOME;
         }
+
+        s->pktsize = ((const int[]){5,10,15,20,20,28,28,38,38,46,62})[quality];
+
         spx_mode           = 0;
     } else if (header) {
         avctx->sample_rate = header->rate;
@@ -143,9 +150,11 @@
             *got_frame_ptr = 0;
             return buf_size;
         }
+        if (s->pktsize && buf_size == 62)
+            buf_size = s->pktsize;
         /* set new buffer */
         speex_bits_read_from(&s->bits, buf, buf_size);
-        consumed = buf_size;
+        consumed = avpkt->size;
     }
 
     /* decode a single frame */
diff --git a/libavcodec/libvorbisdec.c b/libavcodec/libvorbisdec.c
index b703b65..db00572 100644
--- a/libavcodec/libvorbisdec.c
+++ b/libavcodec/libvorbisdec.c
@@ -35,17 +35,17 @@
 static int oggvorbis_decode_init(AVCodecContext *avccontext) {
     OggVorbisDecContext *context = avccontext->priv_data ;
     uint8_t *p= avccontext->extradata;
-    int i, hsizes[3];
+    int i, hsizes[3], ret;
     unsigned char *headers[3], *extradata = avccontext->extradata;
 
-    vorbis_info_init(&context->vi) ;
-    vorbis_comment_init(&context->vc) ;
-
     if(! avccontext->extradata_size || ! p) {
         av_log(avccontext, AV_LOG_ERROR, "vorbis extradata absent\n");
-        return -1;
+        return AVERROR(EINVAL);
     }
 
+    vorbis_info_init(&context->vi) ;
+    vorbis_comment_init(&context->vc) ;
+
     if(p[0] == 0 && p[1] == 30) {
         for(i = 0; i < 3; i++){
             hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
@@ -65,7 +65,8 @@
             if(offset >= avccontext->extradata_size - 1) {
                 av_log(avccontext, AV_LOG_ERROR,
                        "vorbis header sizes damaged\n");
-                return -1;
+                ret = AVERROR_INVALIDDATA;
+                goto error;
             }
             hsizes[i] += *p;
             offset++;
@@ -83,7 +84,8 @@
     } else {
         av_log(avccontext, AV_LOG_ERROR,
                "vorbis initial header len is wrong: %d\n", *p);
-        return -1;
+        ret = AVERROR_INVALIDDATA;
+        goto error;
     }
 
     for(i=0; i<3; i++){
@@ -92,7 +94,8 @@
         context->op.packet = headers[i];
         if(vorbis_synthesis_headerin(&context->vi, &context->vc, &context->op)<0){
             av_log(avccontext, AV_LOG_ERROR, "%d. vorbis header damaged\n", i+1);
-            return -1;
+            ret = AVERROR_INVALIDDATA;
+            goto error;
         }
     }
 
@@ -105,6 +108,11 @@
     vorbis_block_init(&context->vd, &context->vb);
 
     return 0 ;
+
+  error:
+    vorbis_info_clear(&context->vi);
+    vorbis_comment_clear(&context->vc) ;
+    return ret;
 }
 
 
diff --git a/libavcodec/libvorbisenc.c b/libavcodec/libvorbisenc.c
index 96af536..231d1be 100644
--- a/libavcodec/libvorbisenc.c
+++ b/libavcodec/libvorbisenc.c
@@ -49,7 +49,7 @@
     int dsp_initialized;                /**< vd has been initialized        */
     vorbis_comment vc;                  /**< VorbisComment info             */
     double iblock;                      /**< impulse block bias option      */
-    VorbisParseContext vp;              /**< parse context to get durations */
+    AVVorbisParseContext *vp;           /**< parse context to get durations */
     AudioFrameQueue afq;                /**< frame queue for timestamps     */
 } LibvorbisEncContext;
 
@@ -187,6 +187,8 @@
     ff_af_queue_close(&s->afq);
     av_freep(&avctx->extradata);
 
+    av_vorbis_parse_free(&s->vp);
+
     return 0;
 }
 
@@ -246,7 +248,8 @@
     offset += header_code.bytes;
     av_assert0(offset == avctx->extradata_size);
 
-    if ((ret = avpriv_vorbis_parse_extradata(avctx, &s->vp)) < 0) {
+    s->vp = av_vorbis_parse_init(avctx->extradata, avctx->extradata_size);
+    if (!s->vp) {
         av_log(avctx, AV_LOG_ERROR, "invalid extradata\n");
         return ret;
     }
@@ -341,7 +344,7 @@
 
     avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos);
 
-    duration = avpriv_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size);
+    duration = av_vorbis_parse_frame(s->vp, avpkt->data, avpkt->size);
     if (duration > 0) {
         /* we do not know encoder delay until we get the first packet from
          * libvorbis, so we have to update the AudioFrameQueue counts */
@@ -369,7 +372,7 @@
     .init           = libvorbis_encode_init,
     .encode2        = libvorbis_encode_frame,
     .close          = libvorbis_encode_close,
-    .capabilities   = CODEC_CAP_DELAY,
+    .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_SMALL_LAST_FRAME,
     .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
                                                       AV_SAMPLE_FMT_NONE },
     .priv_class     = &vorbis_class,
diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c
index 30940a1..c69acc0 100644
--- a/libavcodec/libvpxenc.c
+++ b/libavcodec/libvpxenc.c
@@ -644,7 +644,7 @@
                     av_log(avctx, AV_LOG_ERROR,
                            "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n",
                            cx_frame->sz);
-                    av_free(cx_frame);
+                    av_freep(&cx_frame);
                     return AVERROR(ENOMEM);
                 }
                 memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz);
diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c
index 4cb8dc3..95d56ac 100644
--- a/libavcodec/libwebpenc.c
+++ b/libavcodec/libwebpenc.c
@@ -41,6 +41,9 @@
     int chroma_warning;     // chroma linesize mismatch warning has been printed
     int conversion_warning; // pixel format conversion warning has been printed
     WebPConfig config;      // libwebp configuration
+    AVFrame *ref;
+    int cr_size;
+    int cr_threshold;
 } LibWebPContext;
 
 static int libwebp_error_to_averror(int err)
@@ -62,10 +65,9 @@
     LibWebPContext *s = avctx->priv_data;
     int ret;
 
-    if (avctx->global_quality < 0)
-        avctx->global_quality = 75 * FF_QP2LAMBDA;
-    s->quality = av_clipf(avctx->global_quality / (float)FF_QP2LAMBDA,
-                          0.0f, 100.0f);
+    if (avctx->global_quality >= 0)
+        s->quality = av_clipf(avctx->global_quality / (float)FF_QP2LAMBDA,
+                              0.0f, 100.0f);
 
     if (avctx->compression_level < 0 || avctx->compression_level > 6) {
         av_log(avctx, AV_LOG_WARNING, "invalid compression level: %d\n",
@@ -144,8 +146,8 @@
         pic->argb        = (uint32_t *)frame->data[0];
         pic->argb_stride = frame->linesize[0] / 4;
     } else {
-        if (frame->linesize[1] != frame->linesize[2]) {
-            if (!s->chroma_warning) {
+        if (frame->linesize[1] != frame->linesize[2] || s->cr_threshold) {
+            if (!s->chroma_warning && !s->cr_threshold) {
                 av_log(avctx, AV_LOG_WARNING,
                        "Copying frame due to differing chroma linesizes.\n");
                 s->chroma_warning = 1;
@@ -158,22 +160,80 @@
             alt_frame->width  = frame->width;
             alt_frame->height = frame->height;
             alt_frame->format = frame->format;
+            if (s->cr_threshold)
+                alt_frame->format = AV_PIX_FMT_YUVA420P;
             ret = av_frame_get_buffer(alt_frame, 32);
             if (ret < 0)
                 goto end;
+            alt_frame->format = frame->format;
             av_frame_copy(alt_frame, frame);
             frame = alt_frame;
+            if (s->cr_threshold) {
+                int x,y, x2, y2, p;
+                int bs = s->cr_size;
+
+                if (!s->ref) {
+                    s->ref = av_frame_clone(frame);
+                    if (!s->ref) {
+                        ret = AVERROR(ENOMEM);
+                        goto end;
+                    }
+                }
+
+                alt_frame->format = AV_PIX_FMT_YUVA420P;
+                for (y = 0; y < frame->height; y+= bs) {
+                    for (x = 0; x < frame->width; x+= bs) {
+                        int skip;
+                        int sse = 0;
+                        for (p = 0; p < 3; p++) {
+                            int bs2 = bs >> !!p;
+                            int w = FF_CEIL_RSHIFT(frame->width , !!p);
+                            int h = FF_CEIL_RSHIFT(frame->height, !!p);
+                            int xs = x >> !!p;
+                            int ys = y >> !!p;
+                            for (y2 = ys; y2 < FFMIN(ys + bs2, h); y2++) {
+                                for (x2 = xs; x2 < FFMIN(xs + bs2, w); x2++) {
+                                    int diff =  frame->data[p][frame->linesize[p] * y2 + x2]
+                                              -s->ref->data[p][frame->linesize[p] * y2 + x2];
+                                    sse += diff*diff;
+                                }
+                            }
+                        }
+                        skip = sse < s->cr_threshold && frame->data[3] != s->ref->data[3];
+                        if (!skip)
+                            for (p = 0; p < 3; p++) {
+                                int bs2 = bs >> !!p;
+                                int w = FF_CEIL_RSHIFT(frame->width , !!p);
+                                int h = FF_CEIL_RSHIFT(frame->height, !!p);
+                                int xs = x >> !!p;
+                                int ys = y >> !!p;
+                                for (y2 = ys; y2 < FFMIN(ys + bs2, h); y2++) {
+                                    memcpy(&s->ref->data[p][frame->linesize[p] * y2 + xs],
+                                            & frame->data[p][frame->linesize[p] * y2 + xs], FFMIN(bs2, w-xs));
+                                }
+                            }
+                        for (y2 = y; y2 < FFMIN(y+bs, frame->height); y2++) {
+                            memset(&frame->data[3][frame->linesize[3] * y2 + x],
+                                    skip ? 0 : 255,
+                                    FFMIN(bs, frame->width-x));
+                        }
+                    }
+                }
+            }
         }
+
         pic->use_argb  = 0;
         pic->y         = frame->data[0];
         pic->u         = frame->data[1];
         pic->v         = frame->data[2];
         pic->y_stride  = frame->linesize[0];
         pic->uv_stride = frame->linesize[1];
-        if (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) {
+        if (frame->format == AV_PIX_FMT_YUVA420P) {
             pic->colorspace = WEBP_YUV420A;
             pic->a          = frame->data[3];
             pic->a_stride   = frame->linesize[3];
+            if (alt_frame)
+                WebPCleanupTransparentArea(pic);
         } else {
             pic->colorspace = WEBP_YUV420;
         }
@@ -243,6 +303,15 @@
     return ret;
 }
 
+static int libwebp_encode_close(AVCodecContext *avctx)
+{
+    LibWebPContext *s  = avctx->priv_data;
+
+    av_frame_free(&s->ref);
+
+    return 0;
+}
+
 #define OFFSET(x) offsetof(LibWebPContext, x)
 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
@@ -255,9 +324,13 @@
     { "drawing",    "hand or line drawing, with high-contrast details", 0, AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_DRAWING }, 0, 0, VE, "preset" },
     { "icon",       "small-sized colorful images",                      0, AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_ICON    }, 0, 0, VE, "preset" },
     { "text",       "text-like",                                        0, AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_TEXT    }, 0, 0, VE, "preset" },
+    { "cr_threshold","Conditional replenishment threshold",     OFFSET(cr_threshold), AV_OPT_TYPE_INT, { .i64 =  0  },  0, INT_MAX, VE           },
+    { "cr_size"     ,"Conditional replenishment block size",    OFFSET(cr_size)     , AV_OPT_TYPE_INT, { .i64 =  16 },  0, 256,     VE           },
+    { "quality"     ,"Quality",                OFFSET(quality),  AV_OPT_TYPE_FLOAT, { .dbl =  75 }, 0, 100,                         VE           },
     { NULL },
 };
 
+
 static const AVClass class = {
     .class_name = "libwebp",
     .item_name  = av_default_item_name,
@@ -279,6 +352,7 @@
     .priv_data_size = sizeof(LibWebPContext),
     .init           = libwebp_encode_init,
     .encode2        = libwebp_encode_frame,
+    .close          = libwebp_encode_close,
     .pix_fmts       = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB32,
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 5952a0d..4da0ee0 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -305,7 +305,7 @@
     X264Context *x4 = avctx->priv_data;
 
     av_freep(&avctx->extradata);
-    av_free(x4->sei);
+    av_freep(&x4->sei);
 
     if (x4->enc)
         x264_encoder_close(x4->enc);
diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c
index 92dcece..ed86b61 100644
--- a/libavcodec/libxavs.c
+++ b/libavcodec/libxavs.c
@@ -201,7 +201,7 @@
     XavsContext *x4 = avctx->priv_data;
 
     av_freep(&avctx->extradata);
-    av_free(x4->sei);
+    av_freep(&x4->sei);
     av_freep(&x4->pts_buffer);
 
     if (x4->enc)
diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c
index aee9dac..046d2f7 100644
--- a/libavcodec/libxvid.c
+++ b/libavcodec/libxvid.c
@@ -359,7 +359,7 @@
 
 static av_cold int xvid_encode_init(AVCodecContext *avctx)
 {
-    int xerr, i;
+    int xerr, i, ret = -1;
     int xvid_flags = avctx->flags;
     struct xvid_context *x = avctx->priv_data;
     uint16_t *intra, *inter;
@@ -488,6 +488,7 @@
         if (!x->twopassbuffer || !x->old_twopassbuffer) {
             av_log(avctx, AV_LOG_ERROR,
                    "Xvid: Cannot allocate 2-pass log buffers\n");
+            ret = AVERROR(ENOMEM);
             goto fail;
         }
         x->twopassbuffer[0]     =
@@ -501,8 +502,9 @@
         rc2pass2.bitrate = avctx->bit_rate;
 
         fd = av_tempfile("xvidff.", &x->twopassfile, 0, avctx);
-        if (fd == -1) {
+        if (fd < 0) {
             av_log(avctx, AV_LOG_ERROR, "Xvid: Cannot write 2-pass pipe\n");
+            ret = fd;
             goto fail;
         }
         x->twopassfd = fd;
@@ -510,14 +512,19 @@
         if (!avctx->stats_in) {
             av_log(avctx, AV_LOG_ERROR,
                    "Xvid: No 2-pass information loaded for second pass\n");
+            ret = AVERROR(EINVAL);
             goto fail;
         }
 
-        if (strlen(avctx->stats_in) >
-            write(fd, avctx->stats_in, strlen(avctx->stats_in))) {
+        ret = write(fd, avctx->stats_in, strlen(avctx->stats_in));
+        if (ret == -1)
+            ret = AVERROR(errno);
+        else if (strlen(avctx->stats_in) > ret) {
             av_log(avctx, AV_LOG_ERROR, "Xvid: Cannot write to 2-pass pipe\n");
-            goto fail;
+            ret = AVERROR(EIO);
         }
+        if (ret < 0)
+            goto fail;
 
         rc2pass2.filename                          = x->twopassfile;
         plugins[xvid_enc_create.num_plugins].func  = xvid_plugin_2pass2;
@@ -659,13 +666,15 @@
 
     x->encoder_handle  = xvid_enc_create.handle;
     avctx->coded_frame = av_frame_alloc();
-    if (!avctx->coded_frame)
-        return AVERROR(ENOMEM);
+    if (!avctx->coded_frame) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
 
     return 0;
 fail:
     xvid_encode_close(avctx);
-    return -1;
+    return ret;
 }
 
 static int xvid_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
@@ -812,6 +821,7 @@
     av_freep(&x->twopassfile);
     av_freep(&x->intra_matrix);
     av_freep(&x->inter_matrix);
+    av_frame_free(&avctx->coded_frame);
 
     return 0;
 }
diff --git a/libavcodec/lossless_audiodsp.h b/libavcodec/lossless_audiodsp.h
index 4c27502..c3ee2be 100644
--- a/libavcodec/lossless_audiodsp.h
+++ b/libavcodec/lossless_audiodsp.h
@@ -29,7 +29,7 @@
     /**
      * Calculate scalar product of v1 and v2,
      * and v1[i] += v3[i] * mul
-     * @param len length of vectors, should be multiple of 16
+     * @param len length of vectors, should be multiple of 8
      */
     int32_t (*scalarproduct_and_madd_int16)(int16_t *v1 /* align 16 */,
                                             const int16_t *v2,
diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c
index 1d52edf..deb02e7 100644
--- a/libavcodec/lpc.c
+++ b/libavcodec/lpc.c
@@ -175,7 +175,7 @@
                       int omethod, int max_shift, int zero_shift)
 {
     double autoc[MAX_LPC_ORDER+1];
-    double ref[MAX_LPC_ORDER];
+    double ref[MAX_LPC_ORDER] = { 0 };
     double lpc[MAX_LPC_ORDER][MAX_LPC_ORDER];
     int i, j, pass = 0;
     int opt_order;
@@ -208,7 +208,7 @@
     }
 
     if (lpc_type == FF_LPC_TYPE_CHOLESKY) {
-        LLSModel m[2];
+        LLSModel *m = s->lls_models;
         LOCAL_ALIGNED(32, double, var, [FFALIGN(MAX_LPC_ORDER+1,4)]);
         double av_uninit(weight);
         memset(var, 0, FFALIGN(MAX_LPC_ORDER+1,4)*sizeof(*var));
diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h
index c323230..96acb37 100644
--- a/libavcodec/lpc.h
+++ b/libavcodec/lpc.h
@@ -24,6 +24,7 @@
 
 #include <stdint.h>
 #include "libavutil/avassert.h"
+#include "libavutil/lls.h"
 
 #define ORDER_METHOD_EST     0
 #define ORDER_METHOD_2LEVEL  1
@@ -79,6 +80,9 @@
      */
     void (*lpc_compute_autocorr)(const double *data, int len, int lag,
                                  double *autoc);
+
+    // TODO: these should be allocated to reduce ABI compatibility issues
+    LLSModel lls_models[2];
 } LPCContext;
 
 
@@ -153,7 +157,7 @@
                                     int normalize)
 {
     int i, j;
-    LPC_TYPE err;
+    LPC_TYPE err = 0;
     LPC_TYPE *lpc_last = lpc;
 
     av_assert2(normalize || !fail);
diff --git a/libavcodec/me_cmp.c b/libavcodec/me_cmp.c
index 1355a23..cfd14ab 100644
--- a/libavcodec/me_cmp.c
+++ b/libavcodec/me_cmp.c
@@ -32,7 +32,7 @@
 uint32_t ff_square_tab[512] = { 0, };
 
 static int sse4_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                  int line_size, int h)
+                  ptrdiff_t stride, int h)
 {
     int s = 0, i;
     uint32_t *sq = ff_square_tab + 256;
@@ -42,14 +42,14 @@
         s    += sq[pix1[1] - pix2[1]];
         s    += sq[pix1[2] - pix2[2]];
         s    += sq[pix1[3] - pix2[3]];
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
 
 static int sse8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                  int line_size, int h)
+                  ptrdiff_t stride, int h)
 {
     int s = 0, i;
     uint32_t *sq = ff_square_tab + 256;
@@ -63,14 +63,14 @@
         s    += sq[pix1[5] - pix2[5]];
         s    += sq[pix1[6] - pix2[6]];
         s    += sq[pix1[7] - pix2[7]];
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
 
 static int sse16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                   int line_size, int h)
+                   ptrdiff_t stride, int h)
 {
     int s = 0, i;
     uint32_t *sq = ff_square_tab + 256;
@@ -93,8 +93,8 @@
         s += sq[pix1[14] - pix2[14]];
         s += sq[pix1[15] - pix2[15]];
 
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
@@ -112,7 +112,7 @@
 #define avg4(a, b, c, d) ((a + b + c + d + 2) >> 2)
 
 static inline int pix_abs16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                              int line_size, int h)
+                              ptrdiff_t stride, int h)
 {
     int s = 0, i;
 
@@ -133,14 +133,14 @@
         s    += abs(pix1[13] - pix2[13]);
         s    += abs(pix1[14] - pix2[14]);
         s    += abs(pix1[15] - pix2[15]);
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
 
 static int pix_abs16_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                          int line_size, int h)
+                          ptrdiff_t stride, int h)
 {
     int s = 0, i;
 
@@ -161,17 +161,17 @@
         s    += abs(pix1[13] - avg2(pix2[13], pix2[14]));
         s    += abs(pix1[14] - avg2(pix2[14], pix2[15]));
         s    += abs(pix1[15] - avg2(pix2[15], pix2[16]));
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
 
 static int pix_abs16_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                          int line_size, int h)
+                          ptrdiff_t stride, int h)
 {
     int s = 0, i;
-    uint8_t *pix3 = pix2 + line_size;
+    uint8_t *pix3 = pix2 + stride;
 
     for (i = 0; i < h; i++) {
         s    += abs(pix1[0]  - avg2(pix2[0],  pix3[0]));
@@ -190,18 +190,18 @@
         s    += abs(pix1[13] - avg2(pix2[13], pix3[13]));
         s    += abs(pix1[14] - avg2(pix2[14], pix3[14]));
         s    += abs(pix1[15] - avg2(pix2[15], pix3[15]));
-        pix1 += line_size;
-        pix2 += line_size;
-        pix3 += line_size;
+        pix1 += stride;
+        pix2 += stride;
+        pix3 += stride;
     }
     return s;
 }
 
 static int pix_abs16_xy2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                           int line_size, int h)
+                           ptrdiff_t stride, int h)
 {
     int s = 0, i;
-    uint8_t *pix3 = pix2 + line_size;
+    uint8_t *pix3 = pix2 + stride;
 
     for (i = 0; i < h; i++) {
         s    += abs(pix1[0]  - avg4(pix2[0],  pix2[1],  pix3[0],  pix3[1]));
@@ -220,15 +220,15 @@
         s    += abs(pix1[13] - avg4(pix2[13], pix2[14], pix3[13], pix3[14]));
         s    += abs(pix1[14] - avg4(pix2[14], pix2[15], pix3[14], pix3[15]));
         s    += abs(pix1[15] - avg4(pix2[15], pix2[16], pix3[15], pix3[16]));
-        pix1 += line_size;
-        pix2 += line_size;
-        pix3 += line_size;
+        pix1 += stride;
+        pix2 += stride;
+        pix3 += stride;
     }
     return s;
 }
 
 static inline int pix_abs8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                             int line_size, int h)
+                             ptrdiff_t stride, int h)
 {
     int s = 0, i;
 
@@ -241,14 +241,14 @@
         s    += abs(pix1[5] - pix2[5]);
         s    += abs(pix1[6] - pix2[6]);
         s    += abs(pix1[7] - pix2[7]);
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
 
 static int pix_abs8_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                         int line_size, int h)
+                         ptrdiff_t stride, int h)
 {
     int s = 0, i;
 
@@ -261,17 +261,17 @@
         s    += abs(pix1[5] - avg2(pix2[5], pix2[6]));
         s    += abs(pix1[6] - avg2(pix2[6], pix2[7]));
         s    += abs(pix1[7] - avg2(pix2[7], pix2[8]));
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     return s;
 }
 
 static int pix_abs8_y2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                         int line_size, int h)
+                         ptrdiff_t stride, int h)
 {
     int s = 0, i;
-    uint8_t *pix3 = pix2 + line_size;
+    uint8_t *pix3 = pix2 + stride;
 
     for (i = 0; i < h; i++) {
         s    += abs(pix1[0] - avg2(pix2[0], pix3[0]));
@@ -282,18 +282,18 @@
         s    += abs(pix1[5] - avg2(pix2[5], pix3[5]));
         s    += abs(pix1[6] - avg2(pix2[6], pix3[6]));
         s    += abs(pix1[7] - avg2(pix2[7], pix3[7]));
-        pix1 += line_size;
-        pix2 += line_size;
-        pix3 += line_size;
+        pix1 += stride;
+        pix2 += stride;
+        pix3 += stride;
     }
     return s;
 }
 
 static int pix_abs8_xy2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                          int line_size, int h)
+                          ptrdiff_t stride, int h)
 {
     int s = 0, i;
-    uint8_t *pix3 = pix2 + line_size;
+    uint8_t *pix3 = pix2 + stride;
 
     for (i = 0; i < h; i++) {
         s    += abs(pix1[0] - avg4(pix2[0], pix2[1], pix3[0], pix3[1]));
@@ -304,14 +304,15 @@
         s    += abs(pix1[5] - avg4(pix2[5], pix2[6], pix3[5], pix3[6]));
         s    += abs(pix1[6] - avg4(pix2[6], pix2[7], pix3[6], pix3[7]));
         s    += abs(pix1[7] - avg4(pix2[7], pix2[8], pix3[7], pix3[8]));
-        pix1 += line_size;
-        pix2 += line_size;
-        pix3 += line_size;
+        pix1 += stride;
+        pix2 += stride;
+        pix3 += stride;
     }
     return s;
 }
 
-static int nsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int h)
+static int nsse16_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2,
+                    ptrdiff_t stride, int h)
 {
     int score1 = 0, score2 = 0, x, y;
 
@@ -335,7 +336,8 @@
         return score1 + FFABS(score2) * 8;
 }
 
-static int nsse8_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2, int stride, int h)
+static int nsse8_c(MpegEncContext *c, uint8_t *s1, uint8_t *s2,
+                   ptrdiff_t stride, int h)
 {
     int score1 = 0, score2 = 0, x, y;
 
@@ -360,7 +362,7 @@
 }
 
 static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b,
-                    int stride, int h)
+                    ptrdiff_t stride, int h)
 {
     return 0;
 }
@@ -443,7 +445,7 @@
 #define BUTTERFLYA(x, y) (FFABS((x) + (y)) + FFABS((x) - (y)))
 
 static int hadamard8_diff8x8_c(MpegEncContext *s, uint8_t *dst,
-                               uint8_t *src, int stride, int h)
+                               uint8_t *src, ptrdiff_t stride, int h)
 {
     int i, temp[64], sum = 0;
 
@@ -495,7 +497,7 @@
 }
 
 static int hadamard8_intra8x8_c(MpegEncContext *s, uint8_t *src,
-                                uint8_t *dummy, int stride, int h)
+                                uint8_t *dummy, ptrdiff_t stride, int h)
 {
     int i, temp[64], sum = 0;
 
@@ -547,7 +549,7 @@
 }
 
 static int dct_sad8x8_c(MpegEncContext *s, uint8_t *src1,
-                        uint8_t *src2, int stride, int h)
+                        uint8_t *src2, ptrdiff_t stride, int h)
 {
     LOCAL_ALIGNED_16(int16_t, temp, [64]);
 
@@ -588,7 +590,7 @@
     }
 
 static int dct264_sad8x8_c(MpegEncContext *s, uint8_t *src1,
-                           uint8_t *src2, int stride, int h)
+                           uint8_t *src2, ptrdiff_t stride, int h)
 {
     int16_t dct[8][8];
     int i, sum = 0;
@@ -613,7 +615,7 @@
 #endif
 
 static int dct_max8x8_c(MpegEncContext *s, uint8_t *src1,
-                        uint8_t *src2, int stride, int h)
+                        uint8_t *src2, ptrdiff_t stride, int h)
 {
     LOCAL_ALIGNED_16(int16_t, temp, [64]);
     int sum = 0, i;
@@ -630,7 +632,7 @@
 }
 
 static int quant_psnr8x8_c(MpegEncContext *s, uint8_t *src1,
-                           uint8_t *src2, int stride, int h)
+                           uint8_t *src2, ptrdiff_t stride, int h)
 {
     LOCAL_ALIGNED_16(int16_t, temp, [64 * 2]);
     int16_t *const bak = temp + 64;
@@ -655,7 +657,7 @@
 }
 
 static int rd8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2,
-                   int stride, int h)
+                   ptrdiff_t stride, int h)
 {
     const uint8_t *scantable = s->intra_scantable.permutated;
     LOCAL_ALIGNED_16(int16_t, temp, [64]);
@@ -732,7 +734,7 @@
 }
 
 static int bit8x8_c(MpegEncContext *s, uint8_t *src1, uint8_t *src2,
-                    int stride, int h)
+                    ptrdiff_t stride, int h)
 {
     const uint8_t *scantable = s->intra_scantable.permutated;
     LOCAL_ALIGNED_16(int16_t, temp, [64]);
@@ -795,7 +797,7 @@
 #define VSAD_INTRA(size)                                                \
 static int vsad_intra ## size ## _c(MpegEncContext *c,                  \
                                     uint8_t *s, uint8_t *dummy,         \
-                                    int stride, int h)                  \
+                                    ptrdiff_t stride, int h)            \
 {                                                                       \
     int score = 0, x, y;                                                \
                                                                         \
@@ -817,7 +819,7 @@
 #define VSAD(size)                                                             \
 static int vsad ## size ## _c(MpegEncContext *c,                               \
                               uint8_t *s1, uint8_t *s2,                        \
-                              int stride, int h)                               \
+                              ptrdiff_t stride, int h)                               \
 {                                                                              \
     int score = 0, x, y;                                                       \
                                                                                \
@@ -837,7 +839,7 @@
 #define VSSE_INTRA(size)                                                \
 static int vsse_intra ## size ## _c(MpegEncContext *c,                  \
                                     uint8_t *s, uint8_t *dummy,         \
-                                    int stride, int h)                  \
+                                    ptrdiff_t stride, int h)            \
 {                                                                       \
     int score = 0, x, y;                                                \
                                                                         \
@@ -858,7 +860,7 @@
 
 #define VSSE(size)                                                             \
 static int vsse ## size ## _c(MpegEncContext *c, uint8_t *s1, uint8_t *s2,     \
-                    int stride, int h)                                         \
+                              ptrdiff_t stride, int h)                         \
 {                                                                              \
     int score = 0, x, y;                                                       \
                                                                                \
@@ -876,7 +878,7 @@
 
 #define WRAPPER8_16_SQ(name8, name16)                                   \
 static int name16(MpegEncContext *s, uint8_t *dst, uint8_t *src,        \
-                  int stride, int h)                                    \
+                  ptrdiff_t stride, int h)                              \
 {                                                                       \
     int score = 0;                                                      \
                                                                         \
diff --git a/libavcodec/me_cmp.h b/libavcodec/me_cmp.h
index 0e3b922..98ee53c 100644
--- a/libavcodec/me_cmp.h
+++ b/libavcodec/me_cmp.h
@@ -47,7 +47,8 @@
  * width < 8 are neither used nor implemented. */
 typedef int (*me_cmp_func)(struct MpegEncContext *c,
                            uint8_t *blk1 /* align width (8 or 16) */,
-                           uint8_t *blk2 /* align 1 */, int line_size, int h);
+                           uint8_t *blk2 /* align 1 */, ptrdiff_t stride,
+                           int h);
 
 typedef struct MECmpContext {
     int (*sum_abs_dctelem)(int16_t *block /* align 16 */);
diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c
index b20aac5..96034a0 100644
--- a/libavcodec/microdvddec.c
+++ b/libavcodec/microdvddec.c
@@ -66,8 +66,24 @@
 // italic, bold, underline, strike-through
 #define MICRODVD_STYLES "ibus"
 
+/* some samples have lines that start with a / indicating non persistent italic
+ * marker */
+static char *check_for_italic_slash_marker(struct microdvd_tag *tags, char *s)
+{
+    if (*s == '/') {
+        struct microdvd_tag tag = tags[indexof(MICRODVD_TAGS, 'y')];
+        tag.key = 'y';
+        tag.data1 |= 1 << 0 /* 'i' position in MICRODVD_STYLES */;
+        microdvd_set_tag(tags, tag);
+        s++;
+    }
+    return s;
+}
+
 static char *microdvd_load_tags(struct microdvd_tag *tags, char *s)
 {
+    s = check_for_italic_slash_marker(tags, s);
+
     while (*s == '{') {
         char *start = s;
         char tag_char = *(s + 1);
@@ -101,7 +117,7 @@
         case 'C':
             tag.persistent = MICRODVD_PERSISTENT_ON;
         case 'c':
-            if (*s == '$')
+            while (*s == '$' || *s == '#')
                 s++;
             tag.data1 = strtol(s, &s, 16) & 0x00ffffff;
             if (*s != '}')
@@ -178,7 +194,7 @@
         microdvd_set_tag(tags, tag);
         s++;
     }
-    return s;
+    return check_for_italic_slash_marker(tags, s);
 }
 
 static void microdvd_open_tags(AVBPrint *new_line, struct microdvd_tag *tags)
diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index cdb75af..a29a533 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -244,7 +244,8 @@
 
 int ff_mjpeg_decode_sof(MJpegDecodeContext *s)
 {
-    int len, nb_components, i, width, height, bits, pix_fmt_id, ret;
+    int len, nb_components, i, width, height, bits, ret;
+    unsigned pix_fmt_id;
     int h_count[MAX_COMPONENTS];
     int v_count[MAX_COMPONENTS];
 
@@ -383,7 +384,7 @@
         else if (!s->lossless)
             s->rgb = 0;
     /* XXX: not complete test ! */
-    pix_fmt_id = (s->h_count[0] << 28) | (s->v_count[0] << 24) |
+    pix_fmt_id = ((unsigned)s->h_count[0] << 28) | (s->v_count[0] << 24) |
                  (s->h_count[1] << 20) | (s->v_count[1] << 16) |
                  (s->h_count[2] << 12) | (s->v_count[2] <<  8) |
                  (s->h_count[3] <<  4) |  s->v_count[3];
@@ -440,14 +441,15 @@
         av_assert0(s->nb_components == 4);
         break;
     case 0x22111122:
+    case 0x22111111:
         if (s->adobe_transform == 0 && s->bits <= 8) {
             s->avctx->pix_fmt = AV_PIX_FMT_GBRAP;
-            s->upscale_v = 6;
-            s->upscale_h = 6;
+            s->upscale_v |= 6;
+            s->upscale_h |= 6;
         } else if (s->adobe_transform == 2 && s->bits <= 8) {
             s->avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
-            s->upscale_v = 6;
-            s->upscale_h = 6;
+            s->upscale_v |= 6;
+            s->upscale_h |= 6;
             s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
         } else {
             if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
@@ -489,17 +491,34 @@
         break;
     case 0x12111100:
     case 0x14121200:
+    case 0x14111100:
     case 0x22211100:
     case 0x22112100:
-        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P;
-        else
-            goto unk_pixfmt;
-        s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+        if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') {
+            if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GBRP;
+            else
+                goto unk_pixfmt;
+            s->upscale_v |= 3;
+        } else {
+            if (pix_fmt_id == 0x14111100)
+                s->upscale_v |= 6;
+            if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV440P : AV_PIX_FMT_YUVJ440P;
+            else
+                goto unk_pixfmt;
+            s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+        }
         break;
     case 0x21111100:
-        if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
-        else              s->avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
-        s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+        if (s->component_id[0] == 'Q' && s->component_id[1] == 'F' && s->component_id[2] == 'A') {
+            if (s->bits <= 8) s->avctx->pix_fmt = AV_PIX_FMT_GBRP;
+            else
+                goto unk_pixfmt;
+            s->upscale_h |= 3;
+        } else {
+            if (s->bits <= 8) s->avctx->pix_fmt = s->cs_itu601 ? AV_PIX_FMT_YUV422P : AV_PIX_FMT_YUVJ422P;
+            else              s->avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
+            s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
+        }
         break;
     case 0x22121100:
     case 0x22111200:
@@ -515,8 +534,12 @@
         else              s->avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
         s->avctx->color_range = s->cs_itu601 ? AVCOL_RANGE_MPEG : AVCOL_RANGE_JPEG;
         if (pix_fmt_id == 0x42111100) {
+            if (s->bits > 8)
+                goto unk_pixfmt;
             s->upscale_h = 6;
         } else if (pix_fmt_id == 0x24111100) {
+            if (s->bits > 8)
+                goto unk_pixfmt;
             s->upscale_v = 6;
         }
         break;
@@ -528,7 +551,7 @@
         break;
     default:
 unk_pixfmt:
-        av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x\n", pix_fmt_id);
+        av_log(s->avctx, AV_LOG_ERROR, "Unhandled pixel format 0x%x bits:%d\n", pix_fmt_id, s->bits);
         s->upscale_h = s->upscale_v = 0;
         return AVERROR_PATCHWELCOME;
     }
@@ -1295,6 +1318,8 @@
     }
 
     if (!Al) {
+        // s->coefs_finished is a bitmask for coefficients coded
+        // ss and se are parameters telling start and end coefficients
         s->coefs_finished[c] |= (2ULL << se) - (1ULL << ss);
         last_scan = !~s->coefs_finished[c];
     }
@@ -1596,6 +1621,8 @@
     }
 
     if (id == AV_RB32("LJIF")) {
+        int rgb = s->rgb;
+        int pegasus_rct = s->pegasus_rct;
         if (s->avctx->debug & FF_DEBUG_PICT_INFO)
             av_log(s->avctx, AV_LOG_INFO,
                    "Pegasus lossless jpeg header found\n");
@@ -1605,17 +1632,27 @@
         skip_bits(&s->gb, 16); /* unknown always 0? */
         switch (i=get_bits(&s->gb, 8)) {
         case 1:
-            s->rgb         = 1;
-            s->pegasus_rct = 0;
+            rgb         = 1;
+            pegasus_rct = 0;
             break;
         case 2:
-            s->rgb         = 1;
-            s->pegasus_rct = 1;
+            rgb         = 1;
+            pegasus_rct = 1;
             break;
         default:
             av_log(s->avctx, AV_LOG_ERROR, "unknown colorspace %d\n", i);
         }
+
         len -= 9;
+        if (s->got_picture)
+            if (rgb != s->rgb || pegasus_rct != s->pegasus_rct) {
+                av_log(s->avctx, AV_LOG_WARNING, "Mismatching LJIF tag\n");
+                goto out;
+            }
+
+        s->rgb = rgb;
+        s->pegasus_rct = pegasus_rct;
+
         goto out;
     }
     if (id == AV_RL32("colr") && len > 0) {
@@ -2091,6 +2128,9 @@
                    avctx->pix_fmt == AV_PIX_FMT_YUVJ420P ||
                    avctx->pix_fmt == AV_PIX_FMT_YUV420P  ||
                    avctx->pix_fmt == AV_PIX_FMT_YUV420P16||
+                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P  ||
+                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P16||
+                   avctx->pix_fmt == AV_PIX_FMT_GBRP     ||
                    avctx->pix_fmt == AV_PIX_FMT_GBRAP
                   );
         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
@@ -2128,7 +2168,12 @@
                    avctx->pix_fmt == AV_PIX_FMT_YUV422P  ||
                    avctx->pix_fmt == AV_PIX_FMT_YUVJ420P ||
                    avctx->pix_fmt == AV_PIX_FMT_YUV420P  ||
+                   avctx->pix_fmt == AV_PIX_FMT_YUV440P  ||
+                   avctx->pix_fmt == AV_PIX_FMT_YUVJ440P ||
                    avctx->pix_fmt == AV_PIX_FMT_YUVA444P ||
+                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P  ||
+                   avctx->pix_fmt == AV_PIX_FMT_YUVA420P16||
+                   avctx->pix_fmt == AV_PIX_FMT_GBRP     ||
                    avctx->pix_fmt == AV_PIX_FMT_GBRAP
                    );
         avcodec_get_chroma_sub_sample(s->avctx->pix_fmt, &hshift, &vshift);
diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
index 0fb3a17..14701e2 100644
--- a/libavcodec/mjpegenc.c
+++ b/libavcodec/mjpegenc.c
@@ -78,7 +78,7 @@
 
 void ff_mjpeg_encode_close(MpegEncContext *s)
 {
-    av_free(s->mjpeg_ctx);
+    av_freep(&s->mjpeg_ctx);
 }
 
 static void encode_block(MpegEncContext *s, int16_t *block, int n)
diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c
index d26c277..490d107 100644
--- a/libavcodec/mlpdec.c
+++ b/libavcodec/mlpdec.c
@@ -583,7 +583,7 @@
             ch_assign = av_get_channel_layout_channel_index(s->ch_layout,
                                                             channel);
         }
-        if ((unsigned)ch_assign > s->max_matrix_channel) {
+        if (ch_assign < 0 || ch_assign > s->max_matrix_channel) {
             avpriv_request_sample(m->avctx,
                                   "Assignment of matrix channel %d to invalid output channel %d",
                                   ch, ch_assign);
diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
index 81ee2bd..901fafd 100644
--- a/libavcodec/motion_est.c
+++ b/libavcodec/motion_est.c
@@ -193,7 +193,13 @@
         int uvdxy;              /* no, it might not be used uninitialized */
         if(dxy){
             if(qpel){
-                c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)
+                if (h << size == 16) {
+                    c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)
+                } else if (size == 0 && h == 8) {
+                    c->qpel_put[1][dxy](c->temp    , ref[0] + x + y*stride    , stride);
+                    c->qpel_put[1][dxy](c->temp + 8, ref[0] + x + y*stride + 8, stride);
+                } else
+                    av_assert2(0);
                 if(chroma){
                     int cx= hx/2;
                     int cy= hy/2;
@@ -290,7 +296,7 @@
 #include "motion_est_template.c"
 
 static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b,
-                    int stride, int h)
+                    ptrdiff_t stride, int h)
 {
     return 0;
 }
@@ -971,27 +977,7 @@
     pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
     c->mc_mb_var_sum_temp += (vard+128)>>8;
 
-    if(mb_type){
-        int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
-        int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
-        c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
-
-        if(mb_type == CANDIDATE_MB_TYPE_INTER){
-            c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
-            set_p_mv_tables(s, mx, my, 1);
-        }else{
-            mx <<=shift;
-            my <<=shift;
-        }
-        if(mb_type == CANDIDATE_MB_TYPE_INTER4V){
-            h263_mv4_search(s, mx, my, shift);
-
-            set_p_mv_tables(s, mx, my, 0);
-        }
-        if(mb_type == CANDIDATE_MB_TYPE_INTER_I){
-            interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 1);
-        }
-    }else if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
+    if (c->avctx->mb_decision > FF_MB_DECISION_SIMPLE) {
         int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
         int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
         c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 40962ac..78888c7 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -733,6 +733,7 @@
 {
     int i, j, k, cbp, val, mb_type, motion_type;
     const int mb_block_count = 4 + (1 << s->chroma_format);
+    int ret;
 
     av_dlog(s->avctx, "decode_mb: x=%d y=%d\n", s->mb_x, s->mb_y);
 
@@ -753,7 +754,7 @@
                 mb_type = s->current_picture.mb_type[s->mb_width + (s->mb_y - 1) * s->mb_stride - 1];
             if (IS_INTRA(mb_type)) {
                 av_log(s->avctx, AV_LOG_ERROR, "skip with previntra\n");
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
             s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride] =
                 mb_type | MB_TYPE_SKIP;
@@ -773,7 +774,7 @@
                 av_log(s->avctx, AV_LOG_ERROR,
                        "invalid mb type in I Frame at %d %d\n",
                        s->mb_x, s->mb_y);
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
             mb_type = MB_TYPE_QUANT | MB_TYPE_INTRA;
         } else {
@@ -785,7 +786,7 @@
         if (mb_type < 0) {
             av_log(s->avctx, AV_LOG_ERROR,
                    "invalid mb type in P Frame at %d %d\n", s->mb_x, s->mb_y);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         mb_type = ptype2mb_type[mb_type];
         break;
@@ -794,7 +795,7 @@
         if (mb_type < 0) {
             av_log(s->avctx, AV_LOG_ERROR,
                    "invalid mb type in B Frame at %d %d\n", s->mb_x, s->mb_y);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         mb_type = btype2mb_type[mb_type];
         break;
@@ -846,13 +847,13 @@
                     mpeg2_fast_decode_block_intra(s, *s->pblocks[i], i);
             } else {
                 for (i = 0; i < mb_block_count; i++)
-                    if (mpeg2_decode_block_intra(s, *s->pblocks[i], i) < 0)
-                        return -1;
+                    if ((ret = mpeg2_decode_block_intra(s, *s->pblocks[i], i)) < 0)
+                        return ret;
             }
         } else {
             for (i = 0; i < 6; i++)
-                if (mpeg1_decode_block_intra(s, *s->pblocks[i], i) < 0)
-                    return -1;
+                if ((ret = mpeg1_decode_block_intra(s, *s->pblocks[i], i)) < 0)
+                    return ret;
         }
     } else {
         if (mb_type & MB_TYPE_ZERO_MV) {
@@ -982,7 +983,7 @@
             case MT_DMV:
                 if (s->progressive_sequence){
                     av_log(s->avctx, AV_LOG_ERROR, "MT_DMV in progressive_sequence\n");
-                    return -1;
+                    return AVERROR_INVALIDDATA;
                 }
                 s->mv_type = MV_TYPE_DMV;
                 for (i = 0; i < 2; i++) {
@@ -1036,7 +1037,7 @@
             default:
                 av_log(s->avctx, AV_LOG_ERROR,
                        "00 motion_type at %d %d\n", s->mb_x, s->mb_y);
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
         }
 
@@ -1053,7 +1054,7 @@
             if (cbp <= 0) {
                 av_log(s->avctx, AV_LOG_ERROR,
                        "invalid cbp %d at %d %d\n", cbp, s->mb_x, s->mb_y);
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
 
             // if 1, we memcpy blocks in xvmcvideo
@@ -1074,8 +1075,8 @@
 
                     for (i = 0; i < mb_block_count; i++) {
                         if (cbp & (1 << 11)) {
-                            if (mpeg2_decode_block_non_intra(s, *s->pblocks[i], i) < 0)
-                                return -1;
+                            if ((ret = mpeg2_decode_block_non_intra(s, *s->pblocks[i], i)) < 0)
+                                return ret;
                         } else {
                             s->block_last_index[i] = -1;
                         }
@@ -1094,8 +1095,8 @@
                 } else {
                     for (i = 0; i < 6; i++) {
                         if (cbp & 32) {
-                            if (mpeg1_decode_block_inter(s, *s->pblocks[i], i) < 0)
-                                return -1;
+                            if ((ret = mpeg1_decode_block_inter(s, *s->pblocks[i], i)) < 0)
+                                return ret;
                         } else {
                             s->block_last_index[i] = -1;
                         }
@@ -1120,6 +1121,10 @@
     MpegEncContext *s2 = &s->mpeg_enc_ctx;
 
     ff_mpv_decode_defaults(s2);
+
+    if (   avctx->codec_tag != AV_RL32("VCR2")
+        && avctx->codec_tag != AV_RL32("BW10"))
+        avctx->coded_width = avctx->coded_height = 0; // do not trust dimensions from input
     ff_mpv_decode_init(s2, avctx);
 
     s->mpeg_enc_ctx.avctx  = avctx;
@@ -1393,7 +1398,7 @@
     ref = get_bits(&s->gb, 10); /* temporal ref */
     s->pict_type = get_bits(&s->gb, 3);
     if (s->pict_type == 0 || s->pict_type > 3)
-        return -1;
+        return AVERROR_INVALIDDATA;
 
     vbv_delay = get_bits(&s->gb, 16);
     s->vbv_delay = vbv_delay;
@@ -1402,7 +1407,7 @@
         s->full_pel[0] = get_bits1(&s->gb);
         f_code = get_bits(&s->gb, 3);
         if (f_code == 0 && (avctx->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT)))
-            return -1;
+            return AVERROR_INVALIDDATA;
         f_code += !f_code;
         s->mpeg_f_code[0][0] = f_code;
         s->mpeg_f_code[0][1] = f_code;
@@ -1411,7 +1416,7 @@
         s->full_pel[1] = get_bits1(&s->gb);
         f_code = get_bits(&s->gb, 3);
         if (f_code == 0 && (avctx->err_recognition & (AV_EF_BITSTREAM|AV_EF_COMPLIANT)))
-            return -1;
+            return AVERROR_INVALIDDATA;
         f_code += !f_code;
         s->mpeg_f_code[1][0] = f_code;
         s->mpeg_f_code[1][1] = f_code;
@@ -1533,7 +1538,7 @@
         int v = get_bits(&s->gb, 8);
         if (v == 0) {
             av_log(s->avctx, AV_LOG_ERROR, "matrix damaged\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         if (intra && i == 0 && v != 8) {
             av_log(s->avctx, AV_LOG_DEBUG, "intra matrix specifies invalid DC quantizer %d, ignoring\n", v);
@@ -1623,13 +1628,14 @@
 {
     AVCodecContext *avctx = s->avctx;
     Mpeg1Context *s1      = (Mpeg1Context *) s;
+    int ret;
 
     /* start frame decoding */
     if (s->first_field || s->picture_structure == PICT_FRAME) {
         AVFrameSideData *pan_scan;
 
-        if (ff_mpv_frame_start(s, avctx) < 0)
-            return -1;
+        if ((ret = ff_mpv_frame_start(s, avctx)) < 0)
+            return ret;
 
         ff_mpeg_er_frame_start(s);
 
@@ -1708,8 +1714,8 @@
     }
 
     if (avctx->hwaccel) {
-        if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0)
-            return -1;
+        if ((ret = avctx->hwaccel->start_frame(avctx, buf, buf_size)) < 0)
+            return ret;
     }
 
     return 0;
@@ -1730,6 +1736,7 @@
     AVCodecContext *avctx = s->avctx;
     const int lowres      = s->avctx->lowres;
     const int field_pic   = s->picture_structure != PICT_FRAME;
+    int ret;
 
     s->resync_mb_x =
     s->resync_mb_y = -1;
@@ -1747,7 +1754,7 @@
 
     if (s->qscale == 0) {
         av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
 
     /* extra slice info */
@@ -1764,7 +1771,7 @@
                                 MBINCR_VLC_BITS, 2);
             if (code < 0) {
                 av_log(s->avctx, AV_LOG_ERROR, "first mb_incr damaged\n");
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
             if (code >= 33) {
                 if (code == 33)
@@ -1779,7 +1786,7 @@
 
     if (s->mb_x >= (unsigned) s->mb_width) {
         av_log(s->avctx, AV_LOG_ERROR, "initial skip overflow\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
 
     if (avctx->hwaccel && avctx->hwaccel->decode_slice) {
@@ -1826,8 +1833,8 @@
         if ((CONFIG_MPEG1_XVMC_HWACCEL || CONFIG_MPEG2_XVMC_HWACCEL) && s->pack_pblocks)
             ff_xvmc_init_block(s); // set s->block
 
-        if (mpeg_decode_mb(s, s->block) < 0)
-            return -1;
+        if ((ret = mpeg_decode_mb(s, s->block)) < 0)
+            return ret;
 
         // Note motion_val is normally NULL unless we want to extract the MVs.
         if (s->current_picture.motion_val[0] && !s->encoding) {
@@ -1932,7 +1939,7 @@
                                     MBINCR_VLC_BITS, 2);
                 if (code < 0) {
                     av_log(s->avctx, AV_LOG_ERROR, "mb incr damaged\n");
-                    return -1;
+                    return AVERROR_INVALIDDATA;
                 }
                 if (code >= 33) {
                     if (code == 33) {
@@ -1955,7 +1962,7 @@
                 if (s->pict_type == AV_PICTURE_TYPE_I) {
                     av_log(s->avctx, AV_LOG_ERROR,
                            "skipped MB in I frame at %d %d\n", s->mb_x, s->mb_y);
-                    return -1;
+                    return AVERROR_INVALIDDATA;
                 }
 
                 /* skip mb */
@@ -2114,14 +2121,18 @@
     if (s->aspect_ratio_info == 0) {
         av_log(avctx, AV_LOG_ERROR, "aspect ratio has forbidden 0 value\n");
         if (avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_COMPLIANT))
-            return -1;
+            return AVERROR_INVALIDDATA;
     }
     s->frame_rate_index = get_bits(&s->gb, 4);
-    if (s->frame_rate_index == 0 || s->frame_rate_index > 13)
-        return -1;
+    if (s->frame_rate_index == 0 || s->frame_rate_index > 13) {
+        av_log(avctx, AV_LOG_WARNING, "frame_rate_index %d is invalid\n", s->frame_rate_index);
+        s->frame_rate_index = 1;
+    }
     s->bit_rate = get_bits(&s->gb, 18) * 400;
-    if (get_bits1(&s->gb) == 0) /* marker */
-        return -1;
+    if (get_bits1(&s->gb) == 0) { /* marker */
+        av_log(avctx, AV_LOG_ERROR, "Marker in sequence header missing\n");
+        return AVERROR_INVALIDDATA;
+    }
     s->width  = width;
     s->height = height;
 
@@ -2152,7 +2163,7 @@
 
     if (show_bits(&s->gb, 23) != 0) {
         av_log(s->avctx, AV_LOG_ERROR, "sequence header damaged\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
 
     /* We set MPEG-2 parameters so that it emulates MPEG-1. */
@@ -2181,6 +2192,7 @@
     Mpeg1Context *s1  = avctx->priv_data;
     MpegEncContext *s = &s1->mpeg_enc_ctx;
     int i, v;
+    int ret;
 
     /* start new MPEG-1 context decoding */
     s->out_format = FMT_MPEG1;
@@ -2197,8 +2209,8 @@
     setup_hwaccel_for_pixfmt(avctx);
 
     ff_mpv_idct_init(s);
-    if (ff_mpv_common_init(s) < 0)
-        return -1;
+    if ((ret = ff_mpv_common_init(s)) < 0)
+        return ret;
     s1->mpeg_enc_ctx_allocated = 1;
 
     for (i = 0; i < 64; i++) {
@@ -2604,7 +2616,7 @@
                 if (mb_y >= s2->mb_height) {
                     av_log(s2->avctx, AV_LOG_ERROR,
                            "slice below image (%d >= %d)\n", mb_y, s2->mb_height);
-                    return -1;
+                    return AVERROR_INVALIDDATA;
                 }
 
                 if (!s2->last_picture_ptr) {
@@ -2655,8 +2667,8 @@
                 if (s->first_slice) {
                     skip_frame     = 0;
                     s->first_slice = 0;
-                    if (mpeg_field_start(s2, buf, buf_size) < 0)
-                        return -1;
+                    if ((ret = mpeg_field_start(s2, buf, buf_size)) < 0)
+                        return ret;
                 }
                 if (!s2->current_picture_ptr) {
                     av_log(avctx, AV_LOG_ERROR,
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index 827812e..9795b7f 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -606,7 +606,8 @@
 
 static inline void encode_dc(MpegEncContext *s, int diff, int component)
 {
-    if (((unsigned) (diff + 255)) >= 511) {
+    unsigned int diff_u = diff + 255;
+    if (diff_u >= 511) {
         int index;
 
         if (diff < 0) {
diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c
index acf7313..db0305c 100644
--- a/libavcodec/mpeg4video_parser.c
+++ b/libavcodec/mpeg4video_parser.c
@@ -86,7 +86,7 @@
     if (avctx->extradata_size && pc->first_picture) {
         init_get_bits(gb, avctx->extradata, avctx->extradata_size * 8);
         ret = ff_mpeg4_decode_picture_header(dec_ctx, gb);
-        if (ret < 0)
+        if (ret < -1)
             av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n");
     }
 
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index d8d0f44..fd023a1 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -1761,7 +1761,7 @@
     s->avctx->framerate.num = get_bits(gb, 16);
     if (!s->avctx->framerate.num) {
         av_log(s->avctx, AV_LOG_ERROR, "framerate==0\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
 
     ctx->time_increment_bits = av_log2(s->avctx->framerate.num - 1) + 1;
@@ -1827,7 +1827,7 @@
                        "%d sprite_warping_points\n",
                        ctx->num_sprite_warping_points);
                 ctx->num_sprite_warping_points = 0;
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
             s->sprite_warping_accuracy  = get_bits(gb, 2);
             ctx->sprite_brightness_change = get_bits1(gb);
@@ -2372,7 +2372,7 @@
 
         if (get_bits_left(gb) < 3) {
             av_log(s->avctx, AV_LOG_ERROR, "Header truncated\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         ctx->intra_dc_threshold = ff_mpeg4_dc_threshold[get_bits(gb, 3)];
         if (!s->progressive_sequence) {
@@ -2411,7 +2411,7 @@
         if (s->qscale == 0) {
             av_log(s->avctx, AV_LOG_ERROR,
                    "Error, header damaged or not MPEG4 header (qscale=0)\n");
-            return -1;  // makes no sense to continue, as there is nothing left from the image then
+            return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then
         }
 
         if (s->pict_type != AV_PICTURE_TYPE_I) {
@@ -2420,7 +2420,7 @@
                 av_log(s->avctx, AV_LOG_ERROR,
                        "Error, header damaged or not MPEG4 header (f_code=0)\n");
                 s->f_code = 1;
-                return -1;  // makes no sense to continue, as there is nothing left from the image then
+                return AVERROR_INVALIDDATA;  // makes no sense to continue, as there is nothing left from the image then
             }
         } else
             s->f_code = 1;
@@ -2431,7 +2431,7 @@
                 av_log(s->avctx, AV_LOG_ERROR,
                        "Error, header damaged or not MPEG4 header (b_code=0)\n");
                 s->b_code=1;
-                return -1; // makes no sense to continue, as the MV decoding will break very quickly
+                return AVERROR_INVALIDDATA; // makes no sense to continue, as the MV decoding will break very quickly
             }
         } else
             s->b_code = 1;
@@ -2500,6 +2500,7 @@
 {
     MpegEncContext *s = &ctx->m;
     unsigned startcode, v;
+    int ret;
 
     /* search next start code */
     align_get_bits(gb);
@@ -2588,8 +2589,8 @@
         }
 
         if (startcode >= 0x120 && startcode <= 0x12F) {
-            if (decode_vol_header(ctx, gb) < 0)
-                return -1;
+            if ((ret = decode_vol_header(ctx, gb)) < 0)
+                return ret;
         } else if (startcode == USER_DATA_STARTCODE) {
             decode_user_data(ctx, gb);
         } else if (startcode == GOP_STARTCODE) {
@@ -2793,7 +2794,7 @@
     .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 (VDPAU)"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_MPEG4,
-    .priv_data_size = sizeof(MpegEncContext),
+    .priv_data_size = sizeof(Mpeg4DecContext),
     .init           = decode_init,
     .close          = ff_h263_decode_end,
     .decode         = ff_h263_decode_frame,
diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c
index 3d9e946..79dbf63 100644
--- a/libavcodec/mpegaudio_parser.c
+++ b/libavcodec/mpegaudio_parser.c
@@ -73,20 +73,21 @@
                     if (i > 4)
                         s->header_count = -2;
                 } else {
+                    int header_threshold = avctx->codec_id != AV_CODEC_ID_NONE && avctx->codec_id != codec_id;
                     if((state&SAME_HEADER_MASK) != (s->header&SAME_HEADER_MASK) && s->header)
                         s->header_count= -3;
                     s->header= state;
                     s->header_count++;
                     s->frame_size = ret-4;
 
-                    if (s->header_count > 0 + (avctx->codec_id != AV_CODEC_ID_NONE && avctx->codec_id != codec_id)) {
+                    if (s->header_count > header_threshold) {
                         avctx->sample_rate= sr;
                         avctx->channels   = channels;
                         s1->duration      = frame_size;
                         avctx->codec_id   = codec_id;
                         if (s->no_bitrate || !avctx->bit_rate) {
                             s->no_bitrate = 1;
-                            avctx->bit_rate += (bit_rate - avctx->bit_rate) / s->header_count;
+                            avctx->bit_rate += (bit_rate - avctx->bit_rate) / (s->header_count - header_threshold);
                         }
                     }
                     break;
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index f043bbd..f84557b 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -956,6 +956,7 @@
     // FIXME can parameters change on I-frames?
     // in that case dst may need a reinit
     if (!s->context_initialized) {
+        int err;
         memcpy(s, s1, sizeof(MpegEncContext));
 
         s->avctx                 = dst;
@@ -966,10 +967,10 @@
 //             s->picture_range_start  += MAX_PICTURE_COUNT;
 //             s->picture_range_end    += MAX_PICTURE_COUNT;
             ff_mpv_idct_init(s);
-            if((ret = ff_mpv_common_init(s)) < 0){
+            if((err = ff_mpv_common_init(s)) < 0){
                 memset(s, 0, sizeof(MpegEncContext));
                 s->avctx = dst;
-                return ret;
+                return err;
             }
         }
     }
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 6946c60..cadf6f2 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -874,7 +874,7 @@
 
 void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number);
 void ff_mpeg1_encode_mb(MpegEncContext *s,
-                        int16_t block[6][64],
+                        int16_t block[8][64],
                         int motion_x, int motion_y);
 void ff_mpeg1_encode_init(MpegEncContext *s);
 void ff_mpeg1_encode_slice_header(MpegEncContext *s);
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index f059ec0..27153cf 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -96,41 +96,40 @@
             fdsp->fdct == ff_jpeg_fdct_islow_10) {
             for (i = 0; i < 64; i++) {
                 const int j = s->idsp.idct_permutation[i];
+                int64_t den = (int64_t) qscale * quant_matrix[j];
                 /* 16 <= qscale * quant_matrix[i] <= 7905
                  * Assume x = ff_aanscales[i] * qscale * quant_matrix[i]
                  *             19952 <=              x  <= 249205026
                  * (1 << 36) / 19952 >= (1 << 36) / (x) >= (1 << 36) / 249205026
                  *           3444240 >= (1 << 36) / (x) >= 275 */
 
-                qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) /
-                                        (qscale * quant_matrix[j]));
+                qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / den);
             }
         } else if (fdsp->fdct == ff_fdct_ifast) {
             for (i = 0; i < 64; i++) {
                 const int j = s->idsp.idct_permutation[i];
+                int64_t den = ff_aanscales[i] * (int64_t) qscale * quant_matrix[j];
                 /* 16 <= qscale * quant_matrix[i] <= 7905
                  * Assume x = ff_aanscales[i] * qscale * quant_matrix[i]
                  *             19952 <=              x  <= 249205026
                  * (1 << 36) / 19952 >= (1 << 36) / (x) >= (1 << 36) / 249205026
                  *           3444240 >= (1 << 36) / (x) >= 275 */
 
-                qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 14)) /
-                                        (ff_aanscales[i] * (int64_t)qscale * quant_matrix[j]));
+                qmat[qscale][i] = (int)((UINT64_C(1) << (QMAT_SHIFT + 14)) / den);
             }
         } else {
             for (i = 0; i < 64; i++) {
                 const int j = s->idsp.idct_permutation[i];
+                int64_t den = (int64_t) qscale * quant_matrix[j];
                 /* We can safely suppose that 16 <= quant_matrix[i] <= 255
                  * Assume x = qscale * quant_matrix[i]
                  * So             16 <=              x  <= 7905
                  * so (1 << 19) / 16 >= (1 << 19) / (x) >= (1 << 19) / 7905
                  * so          32768 >= (1 << 19) / (x) >= 67 */
-                qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) /
-                                        (qscale * quant_matrix[j]));
+                qmat[qscale][i] = (int)((UINT64_C(1) << QMAT_SHIFT) / den);
                 //qmat  [qscale][i] = (1 << QMAT_SHIFT_MMX) /
                 //                    (qscale * quant_matrix[i]);
-                qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) /
-                                       (qscale * quant_matrix[j]);
+                qmat16[qscale][0][i] = (1 << QMAT_SHIFT_MMX) / den;
 
                 if (qmat16[qscale][0][i] == 0 ||
                     qmat16[qscale][0][i] == 128 * 256)
@@ -1116,13 +1115,10 @@
     }
 
     if (pic_arg) {
-        if (!pic_arg->buf[0])
-            direct = 0;
-        if (pic_arg->linesize[0] != s->linesize)
-            direct = 0;
-        if (pic_arg->linesize[1] != s->uvlinesize)
-            direct = 0;
-        if (pic_arg->linesize[2] != s->uvlinesize)
+        if (!pic_arg->buf[0] ||
+            pic_arg->linesize[0] != s->linesize ||
+            pic_arg->linesize[1] != s->uvlinesize ||
+            pic_arg->linesize[2] != s->uvlinesize)
             direct = 0;
         if ((s->width & 15) || (s->height & 15))
             direct = 0;
@@ -1134,27 +1130,20 @@
         av_dlog(s->avctx, "%d %d %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"\n", pic_arg->linesize[0],
                 pic_arg->linesize[1], s->linesize, s->uvlinesize);
 
+        i = ff_find_unused_picture(s, direct);
+        if (i < 0)
+            return i;
+
+        pic = &s->picture[i];
+        pic->reference = 3;
+
         if (direct) {
-            i = ff_find_unused_picture(s, 1);
-            if (i < 0)
-                return i;
-
-            pic = &s->picture[i];
-            pic->reference = 3;
-
             if ((ret = av_frame_ref(pic->f, pic_arg)) < 0)
                 return ret;
             if (ff_alloc_picture(s, pic, 1) < 0) {
                 return -1;
             }
         } else {
-            i = ff_find_unused_picture(s, 0);
-            if (i < 0)
-                return i;
-
-            pic = &s->picture[i];
-            pic->reference = 3;
-
             if (ff_alloc_picture(s, pic, 0) < 0) {
                 return -1;
             }
diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c
index 6bb524b..2eb67df 100644
--- a/libavcodec/mss1.c
+++ b/libavcodec/mss1.c
@@ -197,6 +197,8 @@
         return AVERROR(ENOMEM);
 
     ret = ff_mss12_decode_init(&c->ctx, 0, &c->sc, NULL);
+    if (ret < 0)
+        av_frame_free(&c->pic);
 
     avctx->pix_fmt = AV_PIX_FMT_PAL8;
 
diff --git a/libavcodec/nellymoserdec.c b/libavcodec/nellymoserdec.c
index ef16fd6..2d8a594 100644
--- a/libavcodec/nellymoserdec.c
+++ b/libavcodec/nellymoserdec.c
@@ -51,7 +51,7 @@
     AVLFG           random_state;
     GetBitContext   gb;
     float           scale_bias;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FFTContext      imdct_ctx;
     DECLARE_ALIGNED(32, float, imdct_buf)[2][NELLY_BUF_LEN];
     float          *imdct_out;
@@ -106,7 +106,7 @@
                (NELLY_BUF_LEN - NELLY_FILL_LEN) * sizeof(float));
 
         s->imdct_ctx.imdct_half(&s->imdct_ctx, s->imdct_out, aptr);
-        s->fdsp.vector_fmul_window(aptr, s->imdct_prev + NELLY_BUF_LEN / 2,
+        s->fdsp->vector_fmul_window(aptr, s->imdct_prev + NELLY_BUF_LEN / 2,
                                    s->imdct_out, ff_sine_128,
                                    NELLY_BUF_LEN / 2);
         FFSWAP(float *, s->imdct_out, s->imdct_prev);
@@ -122,7 +122,9 @@
     av_lfg_init(&s->random_state, 0);
     ff_mdct_init(&s->imdct_ctx, 8, 1, 1.0);
 
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
 
     s->scale_bias = 1.0/(32768*8);
     avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
@@ -190,6 +192,7 @@
     NellyMoserDecodeContext *s = avctx->priv_data;
 
     ff_mdct_end(&s->imdct_ctx);
+    av_freep(&s->fdsp);
 
     return 0;
 }
diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c
index 9bbdd52..48caba2 100644
--- a/libavcodec/nellymoserenc.c
+++ b/libavcodec/nellymoserenc.c
@@ -56,7 +56,7 @@
 typedef struct NellyMoserEncodeContext {
     AVCodecContext  *avctx;
     int             last_frame;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FFTContext      mdct_ctx;
     AudioFrameQueue afq;
     DECLARE_ALIGNED(32, float, mdct_out)[NELLY_SAMPLES];
@@ -66,7 +66,7 @@
     uint8_t         (*path)[OPT_SIZE];
 } NellyMoserEncodeContext;
 
-static float pow_table[POW_TABLE_SIZE];     ///< -pow(2, -i / 2048.0 - 3.0);
+static float pow_table[POW_TABLE_SIZE];     ///< pow(2, -i / 2048.0 - 3.0);
 
 static const uint8_t sf_lut[96] = {
      0,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  4,  4,
@@ -122,12 +122,12 @@
     float *in1 = s->buf + NELLY_BUF_LEN;
     float *in2 = s->buf + 2 * NELLY_BUF_LEN;
 
-    s->fdsp.vector_fmul        (s->in_buff,                 in0, ff_sine_128, NELLY_BUF_LEN);
-    s->fdsp.vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in1, ff_sine_128, NELLY_BUF_LEN);
+    s->fdsp->vector_fmul        (s->in_buff,                 in0, ff_sine_128, NELLY_BUF_LEN);
+    s->fdsp->vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in1, ff_sine_128, NELLY_BUF_LEN);
     s->mdct_ctx.mdct_calc(&s->mdct_ctx, s->mdct_out, s->in_buff);
 
-    s->fdsp.vector_fmul        (s->in_buff,                 in1, ff_sine_128, NELLY_BUF_LEN);
-    s->fdsp.vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in2, ff_sine_128, NELLY_BUF_LEN);
+    s->fdsp->vector_fmul        (s->in_buff,                 in1, ff_sine_128, NELLY_BUF_LEN);
+    s->fdsp->vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in2, ff_sine_128, NELLY_BUF_LEN);
     s->mdct_ctx.mdct_calc(&s->mdct_ctx, s->mdct_out + NELLY_BUF_LEN, s->in_buff);
 }
 
@@ -142,6 +142,7 @@
         av_freep(&s->path);
     }
     ff_af_queue_close(&s->afq);
+    av_freep(&s->fdsp);
 
     return 0;
 }
@@ -170,12 +171,16 @@
     s->avctx = avctx;
     if ((ret = ff_mdct_init(&s->mdct_ctx, 8, 0, 32768.0)) < 0)
         goto error;
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp) {
+        ret = AVERROR(ENOMEM);
+        goto error;
+    }
 
     /* Generate overlap window */
     ff_init_ff_sine_windows(7);
     for (i = 0; i < POW_TABLE_SIZE; i++)
-        pow_table[i] = -pow(2, -i / 2048.0 - 3.0 + POW_TABLE_OFFSET);
+        pow_table[i] = pow(2, -i / 2048.0 - 3.0 + POW_TABLE_OFFSET);
 
     if (s->avctx->trellis) {
         s->opt  = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(float  ));
diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c
index e5e7cc3..01977e5 100644
--- a/libavcodec/on2avc.c
+++ b/libavcodec/on2avc.c
@@ -47,7 +47,7 @@
 
 typedef struct On2AVCContext {
     AVCodecContext *avctx;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FFTContext mdct, mdct_half, mdct_small;
     FFTContext fft128, fft256, fft512, fft1024;
     void (*wtf)(struct On2AVCContext *ctx, float *out, float *in, int size);
@@ -714,7 +714,7 @@
         }
 
         memcpy(out, saved, 448 * sizeof(float));
-        c->fdsp.vector_fmul_window(wout, saved + 448, buf, c->short_win, 64);
+        c->fdsp->vector_fmul_window(wout, saved + 448, buf, c->short_win, 64);
         memcpy(wout + 128,  buf + 64,         448 * sizeof(float));
         memcpy(saved,       buf + 512,        448 * sizeof(float));
         memcpy(saved + 448, buf + 7*128 + 64,  64 * sizeof(float));
@@ -750,20 +750,20 @@
          c->prev_window_type == WINDOW_TYPE_LONG_STOP) &&
         (c->window_type == WINDOW_TYPE_LONG ||
          c->window_type == WINDOW_TYPE_LONG_START)) {
-        c->fdsp.vector_fmul_window(out, saved, buf, c->long_win, 512);
+        c->fdsp->vector_fmul_window(out, saved, buf, c->long_win, 512);
     } else {
         float *wout = out + 448;
         memcpy(out, saved, 448 * sizeof(float));
 
         if (c->window_type == WINDOW_TYPE_8SHORT) {
-            c->fdsp.vector_fmul_window(wout + 0*128, saved + 448,      buf + 0*128, c->short_win, 64);
-            c->fdsp.vector_fmul_window(wout + 1*128, buf + 0*128 + 64, buf + 1*128, c->short_win, 64);
-            c->fdsp.vector_fmul_window(wout + 2*128, buf + 1*128 + 64, buf + 2*128, c->short_win, 64);
-            c->fdsp.vector_fmul_window(wout + 3*128, buf + 2*128 + 64, buf + 3*128, c->short_win, 64);
-            c->fdsp.vector_fmul_window(temp,         buf + 3*128 + 64, buf + 4*128, c->short_win, 64);
+            c->fdsp->vector_fmul_window(wout + 0*128, saved + 448,      buf + 0*128, c->short_win, 64);
+            c->fdsp->vector_fmul_window(wout + 1*128, buf + 0*128 + 64, buf + 1*128, c->short_win, 64);
+            c->fdsp->vector_fmul_window(wout + 2*128, buf + 1*128 + 64, buf + 2*128, c->short_win, 64);
+            c->fdsp->vector_fmul_window(wout + 3*128, buf + 2*128 + 64, buf + 3*128, c->short_win, 64);
+            c->fdsp->vector_fmul_window(temp,         buf + 3*128 + 64, buf + 4*128, c->short_win, 64);
             memcpy(wout + 4*128, temp, 64 * sizeof(float));
         } else {
-            c->fdsp.vector_fmul_window(wout, saved + 448, buf, c->short_win, 64);
+            c->fdsp->vector_fmul_window(wout, saved + 448, buf, c->short_win, 64);
             memcpy(wout + 128, buf + 64, 448 * sizeof(float));
         }
     }
@@ -772,9 +772,9 @@
     switch (c->window_type) {
     case WINDOW_TYPE_8SHORT:
         memcpy(saved,       temp + 64,         64 * sizeof(float));
-        c->fdsp.vector_fmul_window(saved + 64,  buf + 4*128 + 64, buf + 5*128, c->short_win, 64);
-        c->fdsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, c->short_win, 64);
-        c->fdsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, c->short_win, 64);
+        c->fdsp->vector_fmul_window(saved + 64,  buf + 4*128 + 64, buf + 5*128, c->short_win, 64);
+        c->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, c->short_win, 64);
+        c->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, c->short_win, 64);
         memcpy(saved + 448, buf + 7*128 + 64,  64 * sizeof(float));
         break;
     case WINDOW_TYPE_LONG_START:
@@ -952,13 +952,14 @@
     ff_fft_init(&c->fft256,  7, 0);
     ff_fft_init(&c->fft512,  8, 1);
     ff_fft_init(&c->fft1024, 9, 1);
-    avpriv_float_dsp_init(&c->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    c->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!c->fdsp)
+        return AVERROR(ENOMEM);
 
     if (init_vlc(&c->scale_diff, 9, ON2AVC_SCALE_DIFFS,
                  ff_on2avc_scale_diff_bits,  1, 1,
                  ff_on2avc_scale_diff_codes, 4, 4, 0)) {
-        av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n");
-        return AVERROR(ENOMEM);
+        goto vlc_fail;
     }
     for (i = 1; i < 9; i++) {
         int idx = i - 1;
@@ -966,9 +967,7 @@
                                ff_on2avc_quad_cb_bits[idx],  1, 1,
                                ff_on2avc_quad_cb_codes[idx], 4, 4,
                                ff_on2avc_quad_cb_syms[idx],  2, 2, 0)) {
-            av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n");
-            on2avc_free_vlcs(c);
-            return AVERROR(ENOMEM);
+            goto vlc_fail;
         }
     }
     for (i = 9; i < 16; i++) {
@@ -977,13 +976,16 @@
                                ff_on2avc_pair_cb_bits[idx],  1, 1,
                                ff_on2avc_pair_cb_codes[idx], 2, 2,
                                ff_on2avc_pair_cb_syms[idx],  2, 2, 0)) {
-            av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n");
-            on2avc_free_vlcs(c);
-            return AVERROR(ENOMEM);
+            goto vlc_fail;
         }
     }
 
     return 0;
+vlc_fail:
+    av_log(avctx, AV_LOG_ERROR, "Cannot init VLC\n");
+    on2avc_free_vlcs(c);
+    av_freep(&c->fdsp);
+    return AVERROR(ENOMEM);
 }
 
 static av_cold int on2avc_decode_close(AVCodecContext *avctx)
@@ -998,6 +1000,8 @@
     ff_fft_end(&c->fft512);
     ff_fft_end(&c->fft1024);
 
+    av_freep(&c->fdsp);
+
     on2avc_free_vlcs(c);
 
     return 0;
diff --git a/libavcodec/options.c b/libavcodec/options.c
index c4ee234..7f9fb07 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -95,8 +95,10 @@
     s->av_class = &av_codec_context_class;
 
     s->codec_type = codec ? codec->type : AVMEDIA_TYPE_UNKNOWN;
-    if (codec)
+    if (codec) {
+        s->codec = codec;
         s->codec_id = codec->id;
+    }
 
     if(s->codec_type == AVMEDIA_TYPE_AUDIO)
         flags= AV_OPT_FLAG_AUDIO_PARAM;
@@ -108,6 +110,7 @@
 
     s->time_base           = (AVRational){0,1};
     s->framerate           = (AVRational){ 0, 1 };
+    s->pkt_timebase        = (AVRational){ 0, 1 };
     s->get_buffer2         = avcodec_default_get_buffer2;
     s->get_format          = avcodec_default_get_format;
     s->execute             = avcodec_default_execute;
@@ -115,7 +118,6 @@
     s->sample_aspect_ratio = (AVRational){0,1};
     s->pix_fmt             = AV_PIX_FMT_NONE;
     s->sample_fmt          = AV_SAMPLE_FMT_NONE;
-    s->timecode_frame_start = -1;
 
     s->reordered_opaque    = AV_NOPTS_VALUE;
     if(codec && codec->priv_data_size){
@@ -168,6 +170,9 @@
 
     av_freep(&avctx->extradata);
     av_freep(&avctx->subtitle_header);
+    av_freep(&avctx->intra_matrix);
+    av_freep(&avctx->inter_matrix);
+    av_freep(&avctx->rc_override);
 
     av_freep(pavctx);
 }
@@ -187,6 +192,7 @@
     av_opt_free(dest);
 
     memcpy(dest, src, sizeof(*dest));
+    av_opt_copy(dest, src);
 
     dest->priv_data       = orig_priv_data;
 
@@ -206,16 +212,6 @@
     dest->inter_matrix    = NULL;
     dest->rc_override     = NULL;
     dest->subtitle_header = NULL;
-#if FF_API_MPV_OPT
-    FF_DISABLE_DEPRECATION_WARNINGS
-    dest->rc_eq           = NULL;
-    if (src->rc_eq) {
-        dest->rc_eq = av_strdup(src->rc_eq);
-        if (!dest->rc_eq)
-            return AVERROR(ENOMEM);
-    }
-    FF_ENABLE_DEPRECATION_WARNINGS
-#endif
 
 #define alloc_and_copy_or_fail(obj, size, pad) \
     if (src->obj && size > 0) { \
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 7d948f1..1d5b078 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -106,8 +106,8 @@
 {"extradata_size", NULL, OFFSET(extradata_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
 {"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, INT_MIN, INT_MAX},
 {"g", "set the group of picture (GOP) size", OFFSET(gop_size), AV_OPT_TYPE_INT, {.i64 = 12 }, INT_MIN, INT_MAX, V|E},
-{"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|D|E},
-{"ac", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|D|E},
+{"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E},
+{"ac", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E},
 {"cutoff", "set cutoff bandwidth", OFFSET(cutoff), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E},
 {"frame_size", NULL, OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E},
 {"frame_number", NULL, OFFSET(frame_number), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
@@ -398,7 +398,7 @@
 {"compression_level", NULL, OFFSET(compression_level), AV_OPT_TYPE_INT, {.i64 = FF_COMPRESSION_DEFAULT }, INT_MIN, INT_MAX, V|A|E},
 {"min_prediction_order", NULL, OFFSET(min_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E},
 {"max_prediction_order", NULL, OFFSET(max_prediction_order), AV_OPT_TYPE_INT, {.i64 = -1 }, INT_MIN, INT_MAX, A|E},
-{"timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, V|E},
+{"timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = -1 }, -1, INT64_MAX, V|E},
 #if FF_API_REQUEST_CHANNELS
 {"request_channels", "set desired number of audio channels", OFFSET(request_channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D},
 #endif
@@ -432,7 +432,7 @@
 {"iec61966_2_1", "IEC 61966-2-1",    0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_IEC61966_2_1 }, INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
 {"bt2020_10bit", "BT.2020 - 10 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_10 },    INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
 {"bt2020_12bit", "BT.2020 - 12 bit", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_TRC_BT2020_12 },    INT_MIN, INT_MAX, V|E|D, "color_trc_type"},
-{"colorspace", "color space", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 1, AVCOL_SPC_NB-1, V|E|D, "colorspace_type"},
+{"colorspace", "color space", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64 = AVCOL_SPC_UNSPECIFIED }, 0, AVCOL_SPC_NB-1, V|E|D, "colorspace_type"},
 {"rgb",         "RGB",         0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_RGB },         INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
 {"bt709",       "BT.709",      0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_BT709 },       INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
 {"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCOL_SPC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, "colorspace_type"},
@@ -488,6 +488,8 @@
 {"bt", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_FIELD_BT }, 0, 0, V|D|E, "field_order" },
 {"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, A|V|S|D|E},
 {"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, A|V|S|D },
+{"pixel_format", "set pixel format", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_NONE}, -1, INT_MAX, 0 },
+{"video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, INT_MAX, 0 },
 {NULL},
 };
 
diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c
index e8a8de7..4f3212b 100644
--- a/libavcodec/opus_celt.c
+++ b/libavcodec/opus_celt.c
@@ -62,7 +62,7 @@
     // constant values that do not change during context lifetime
     AVCodecContext    *avctx;
     CeltIMDCTContext  *imdct[4];
-    AVFloatDSPContext  dsp;
+    AVFloatDSPContext  *dsp;
     int output_channels;
 
     // values that have inter-frame effect and must be reset on flush
@@ -2072,7 +2072,7 @@
 
     /* stereo -> mono downmix */
     if (s->output_channels < s->coded_channels) {
-        s->dsp.vector_fmac_scalar(s->coeffs[0], s->coeffs[1], 1.0, FFALIGN(frame_size, 16));
+        s->dsp->vector_fmac_scalar(s->coeffs[0], s->coeffs[1], 1.0, FFALIGN(frame_size, 16));
         imdct_scale = 0.5;
     } else if (s->output_channels > s->coded_channels)
         memcpy(s->coeffs[1], s->coeffs[0], frame_size * sizeof(float));
@@ -2098,7 +2098,7 @@
 
             imdct->imdct_half(imdct, dst + CELT_OVERLAP / 2, s->coeffs[i] + j,
                               s->blocks, imdct_scale);
-            s->dsp.vector_fmul_window(dst, dst, dst + CELT_OVERLAP / 2,
+            s->dsp->vector_fmul_window(dst, dst, dst + CELT_OVERLAP / 2,
                                       celt_window, CELT_OVERLAP / 2);
         }
 
@@ -2181,6 +2181,7 @@
     for (i = 0; i < FF_ARRAY_ELEMS(s->imdct); i++)
         ff_celt_imdct_uninit(&s->imdct[i]);
 
+    av_freep(&s->dsp);
     av_freep(ps);
 }
 
@@ -2208,7 +2209,11 @@
             goto fail;
     }
 
-    avpriv_float_dsp_init(&s->dsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->dsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->dsp) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
 
     ff_celt_flush(s);
 
diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c
index b28edfb..3ce519d 100644
--- a/libavcodec/opusdec.c
+++ b/libavcodec/opusdec.c
@@ -499,6 +499,12 @@
                 av_log(avctx, AV_LOG_ERROR, "Error parsing the packet header.\n");
                 return ret;
             }
+            if (coded_samples != s->packet.frame_count * s->packet.frame_duration) {
+                av_log(avctx, AV_LOG_ERROR,
+                       "Mismatching coded sample count in substream %d.\n", i);
+                return AVERROR_INVALIDDATA;
+            }
+
             s->silk_samplerate = get_silk_samplerate(s->packet.config);
         }
 
diff --git a/libavcodec/parser.c b/libavcodec/parser.c
index 55c2f52..d1e1574 100644
--- a/libavcodec/parser.c
+++ b/libavcodec/parser.c
@@ -212,7 +212,7 @@
     if (s) {
         if (s->parser->parser_close)
             s->parser->parser_close(s);
-        av_free(s->priv_data);
+        av_freep(&s->priv_data);
         av_free(s);
     }
 }
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index 835d962..9e52d0b 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -29,6 +29,7 @@
 #include "png.h"
 #include "pngdsp.h"
 #include "thread.h"
+#include "libavformat/apng.h"
 
 #include <zlib.h>
 
@@ -42,6 +43,9 @@
 
     int state;
     int width, height;
+    int cur_w, cur_h;
+    int x_offset, y_offset;
+    uint8_t dispose_op, blend_op;
     int bit_depth;
     int color_type;
     int compression_type;
@@ -267,8 +271,10 @@
             /* would write off the end of the array if we let it process
              * the last pixel with bpp=3 */
             int w = bpp == 4 ? size : size - 3;
-            dsp->add_paeth_prediction(dst + i, src + i, last + i, w - i, bpp);
-            i = w;
+            if (w > i) {
+                dsp->add_paeth_prediction(dst + i, src + i, last + i, w - i, bpp);
+                i = w;
+            }
         }
         ff_add_png_paeth_prediction(dst + i, src + i, last + i, size - i, bpp);
         break;
@@ -298,7 +304,7 @@
     int got_line;
 
     if (!s->interlace_type) {
-        ptr = s->image_buf + s->image_linesize * s->y;
+        ptr = s->image_buf + s->image_linesize * (s->y + s->y_offset) + s->x_offset * s->bpp;
             if (s->y == 0)
                 last_row = s->last_row;
             else
@@ -317,7 +323,7 @@
             }
         }
         s->y++;
-        if (s->y == s->height) {
+        if (s->y == s->cur_h) {
             s->state |= PNG_ALLIMAGE;
             if (s->filter_type == PNG_FILTER_TYPE_LOCO) {
                 if (s->bit_depth == 16) {
@@ -332,7 +338,7 @@
     } else {
         got_line = 0;
         for (;;) {
-            ptr = s->image_buf + s->image_linesize * s->y;
+            ptr = s->image_buf + s->image_linesize * (s->y + s->y_offset) + s->x_offset * s->bpp;
             if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
                 /* if we already read one row, it is time to stop to
                  * wait for the next one */
@@ -345,11 +351,11 @@
                 got_line = 1;
             }
             if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
-                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
+                png_put_interlaced_row(ptr, s->cur_w, s->bits_per_pixel, s->pass,
                                        s->color_type, s->last_row);
             }
             s->y++;
-            if (s->y == s->height) {
+            if (s->y == s->cur_h) {
                 memset(s->last_row, 0, s->row_size);
                 for (;;) {
                     if (s->pass == NB_PASSES - 1) {
@@ -360,7 +366,7 @@
                         s->y = 0;
                         s->pass_row_size = ff_png_pass_row_size(s->pass,
                                                                 s->bits_per_pixel,
-                                                                s->width);
+                                                                s->cur_w);
                         s->crow_size = s->pass_row_size + 1;
                         if (s->pass_row_size != 0)
                             break;
@@ -519,7 +525,562 @@
     return 0;
 }
 
-static int decode_frame(AVCodecContext *avctx,
+static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s,
+                             uint32_t length)
+{
+    if (length != 13)
+        return AVERROR_INVALIDDATA;
+
+    if (s->state & PNG_IDAT) {
+        av_log(avctx, AV_LOG_ERROR, "IHDR after IDAT\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    s->width  = s->cur_w = bytestream2_get_be32(&s->gb);
+    s->height = s->cur_h = bytestream2_get_be32(&s->gb);
+    if (av_image_check_size(s->width, s->height, 0, avctx)) {
+        s->width = s->height = 0;
+        av_log(avctx, AV_LOG_ERROR, "Invalid image size\n");
+        return AVERROR_INVALIDDATA;
+    }
+    s->bit_depth        = bytestream2_get_byte(&s->gb);
+    s->color_type       = bytestream2_get_byte(&s->gb);
+    s->compression_type = bytestream2_get_byte(&s->gb);
+    s->filter_type      = bytestream2_get_byte(&s->gb);
+    s->interlace_type   = bytestream2_get_byte(&s->gb);
+    bytestream2_skip(&s->gb, 4); /* crc */
+    s->state |= PNG_IHDR;
+    if (avctx->debug & FF_DEBUG_PICT_INFO)
+        av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d "
+                "compression_type=%d filter_type=%d interlace_type=%d\n",
+                s->width, s->height, s->bit_depth, s->color_type,
+                s->compression_type, s->filter_type, s->interlace_type);
+
+    return 0;
+}
+
+static int decode_phys_chunk(AVCodecContext *avctx, PNGDecContext *s)
+{
+    if (s->state & PNG_IDAT) {
+        av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
+        return AVERROR_INVALIDDATA;
+    }
+    avctx->sample_aspect_ratio.num = bytestream2_get_be32(&s->gb);
+    avctx->sample_aspect_ratio.den = bytestream2_get_be32(&s->gb);
+    if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.den < 0)
+        avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
+    bytestream2_skip(&s->gb, 1); /* unit specifier */
+    bytestream2_skip(&s->gb, 4); /* crc */
+
+    return 0;
+}
+
+static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
+                             uint32_t length, AVFrame *p)
+{
+    int ret;
+
+    if (!(s->state & PNG_IHDR)) {
+        av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
+        return AVERROR_INVALIDDATA;
+    }
+    if (!(s->state & PNG_IDAT)) {
+        /* init image info */
+        avctx->width  = s->width;
+        avctx->height = s->height;
+
+        s->channels       = ff_png_get_nb_channels(s->color_type);
+        s->bits_per_pixel = s->bit_depth * s->channels;
+        s->bpp            = (s->bits_per_pixel + 7) >> 3;
+        s->row_size       = (s->cur_w * s->bits_per_pixel + 7) >> 3;
+
+        if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
+                s->color_type == PNG_COLOR_TYPE_RGB) {
+            avctx->pix_fmt = AV_PIX_FMT_RGB24;
+        } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
+                s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+            avctx->pix_fmt = AV_PIX_FMT_RGBA;
+        } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
+                s->color_type == PNG_COLOR_TYPE_GRAY) {
+            avctx->pix_fmt = AV_PIX_FMT_GRAY8;
+        } else if (s->bit_depth == 16 &&
+                s->color_type == PNG_COLOR_TYPE_GRAY) {
+            avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
+        } else if (s->bit_depth == 16 &&
+                s->color_type == PNG_COLOR_TYPE_RGB) {
+            avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
+        } else if (s->bit_depth == 16 &&
+                s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+            avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
+        } else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) &&
+                s->color_type == PNG_COLOR_TYPE_PALETTE) {
+            avctx->pix_fmt = AV_PIX_FMT_PAL8;
+        } else if (s->bit_depth == 1 && s->bits_per_pixel == 1) {
+            avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
+        } else if (s->bit_depth == 8 &&
+                s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+            avctx->pix_fmt = AV_PIX_FMT_YA8;
+        } else if (s->bit_depth == 16 &&
+                s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+            avctx->pix_fmt = AV_PIX_FMT_YA16BE;
+        } else {
+            av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d "
+                    "and color type %d\n",
+                    s->bit_depth, s->color_type);
+            return AVERROR_INVALIDDATA;
+        }
+
+        if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0)
+            return ret;
+        ff_thread_finish_setup(avctx);
+
+        p->pict_type        = AV_PICTURE_TYPE_I;
+        p->key_frame        = 1;
+        p->interlaced_frame = !!s->interlace_type;
+
+        /* compute the compressed row size */
+        if (!s->interlace_type) {
+            s->crow_size = s->row_size + 1;
+        } else {
+            s->pass          = 0;
+            s->pass_row_size = ff_png_pass_row_size(s->pass,
+                    s->bits_per_pixel,
+                    s->cur_w);
+            s->crow_size = s->pass_row_size + 1;
+        }
+        av_dlog(avctx, "row_size=%d crow_size =%d\n",
+                s->row_size, s->crow_size);
+        s->image_buf      = p->data[0];
+        s->image_linesize = p->linesize[0];
+        /* copy the palette if needed */
+        if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
+            memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
+        /* empty row is used if differencing to the first row */
+        av_fast_padded_mallocz(&s->last_row, &s->last_row_size, s->row_size);
+        if (!s->last_row)
+            return AVERROR_INVALIDDATA;
+        if (s->interlace_type ||
+                s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
+            av_fast_padded_malloc(&s->tmp_row, &s->tmp_row_size, s->row_size);
+            if (!s->tmp_row)
+                return AVERROR_INVALIDDATA;
+        }
+        /* compressed row */
+        av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16);
+        if (!s->buffer)
+            return AVERROR(ENOMEM);
+
+        /* we want crow_buf+1 to be 16-byte aligned */
+        s->crow_buf          = s->buffer + 15;
+        s->zstream.avail_out = s->crow_size;
+        s->zstream.next_out  = s->crow_buf;
+    }
+    s->state |= PNG_IDAT;
+    if ((ret = png_decode_idat(s, length)) < 0)
+        return ret;
+    bytestream2_skip(&s->gb, 4); /* crc */
+
+    return 0;
+}
+
+static int decode_plte_chunk(AVCodecContext *avctx, PNGDecContext *s,
+                             uint32_t length)
+{
+    int n, i, r, g, b;
+
+    if ((length % 3) != 0 || length > 256 * 3)
+        return AVERROR_INVALIDDATA;
+    /* read the palette */
+    n = length / 3;
+    for (i = 0; i < n; i++) {
+        r = bytestream2_get_byte(&s->gb);
+        g = bytestream2_get_byte(&s->gb);
+        b = bytestream2_get_byte(&s->gb);
+        s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
+    }
+    for (; i < 256; i++)
+        s->palette[i] = (0xFFU << 24);
+    s->state |= PNG_PLTE;
+    bytestream2_skip(&s->gb, 4);     /* crc */
+
+    return 0;
+}
+
+static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
+                             uint32_t length)
+{
+    int v, i;
+
+    /* read the transparency. XXX: Only palette mode supported */
+    if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
+            length > 256 ||
+            !(s->state & PNG_PLTE))
+        return AVERROR_INVALIDDATA;
+    for (i = 0; i < length; i++) {
+        v = bytestream2_get_byte(&s->gb);
+        s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
+    }
+    bytestream2_skip(&s->gb, 4);     /* crc */
+
+    return 0;
+}
+
+static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
+{
+    if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE) {
+        int i, j, k;
+        uint8_t *pd = p->data[0];
+        for (j = 0; j < s->height; j++) {
+            i = s->width / 8;
+            for (k = 7; k >= 1; k--)
+                if ((s->width&7) >= k)
+                    pd[8*i + k - 1] = (pd[i]>>8-k) & 1;
+            for (i--; i >= 0; i--) {
+                pd[8*i + 7]=  pd[i]     & 1;
+                pd[8*i + 6]= (pd[i]>>1) & 1;
+                pd[8*i + 5]= (pd[i]>>2) & 1;
+                pd[8*i + 4]= (pd[i]>>3) & 1;
+                pd[8*i + 3]= (pd[i]>>4) & 1;
+                pd[8*i + 2]= (pd[i]>>5) & 1;
+                pd[8*i + 1]= (pd[i]>>6) & 1;
+                pd[8*i + 0]=  pd[i]>>7;
+            }
+            pd += s->image_linesize;
+        }
+    } else if (s->bits_per_pixel == 2) {
+        int i, j;
+        uint8_t *pd = p->data[0];
+        for (j = 0; j < s->height; j++) {
+            i = s->width / 4;
+            if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
+                if ((s->width&3) >= 3) pd[4*i + 2]= (pd[i] >> 2) & 3;
+                if ((s->width&3) >= 2) pd[4*i + 1]= (pd[i] >> 4) & 3;
+                if ((s->width&3) >= 1) pd[4*i + 0]=  pd[i] >> 6;
+                for (i--; i >= 0; i--) {
+                    pd[4*i + 3]=  pd[i]     & 3;
+                    pd[4*i + 2]= (pd[i]>>2) & 3;
+                    pd[4*i + 1]= (pd[i]>>4) & 3;
+                    pd[4*i + 0]=  pd[i]>>6;
+                }
+            } else {
+                if ((s->width&3) >= 3) pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
+                if ((s->width&3) >= 2) pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
+                if ((s->width&3) >= 1) pd[4*i + 0]= ( pd[i]>>6     )*0x55;
+                for (i--; i >= 0; i--) {
+                    pd[4*i + 3]= ( pd[i]     & 3)*0x55;
+                    pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
+                    pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
+                    pd[4*i + 0]= ( pd[i]>>6     )*0x55;
+                }
+            }
+            pd += s->image_linesize;
+        }
+    } else if (s->bits_per_pixel == 4) {
+        int i, j;
+        uint8_t *pd = p->data[0];
+        for (j = 0; j < s->height; j++) {
+            i = s->width/2;
+            if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
+                if (s->width&1) pd[2*i+0]= pd[i]>>4;
+                for (i--; i >= 0; i--) {
+                    pd[2*i + 1] = pd[i] & 15;
+                    pd[2*i + 0] = pd[i] >> 4;
+                }
+            } else {
+                if (s->width & 1) pd[2*i + 0]= (pd[i] >> 4) * 0x11;
+                for (i--; i >= 0; i--) {
+                    pd[2*i + 1] = (pd[i] & 15) * 0x11;
+                    pd[2*i + 0] = (pd[i] >> 4) * 0x11;
+                }
+            }
+            pd += s->image_linesize;
+        }
+    }
+}
+
+static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
+                             uint32_t length)
+{
+    uint32_t sequence_number;
+
+    if (length != 26)
+        return AVERROR_INVALIDDATA;
+
+    sequence_number = bytestream2_get_be32(&s->gb);
+    s->cur_w        = bytestream2_get_be32(&s->gb);
+    s->cur_h        = bytestream2_get_be32(&s->gb);
+    s->x_offset     = bytestream2_get_be32(&s->gb);
+    s->y_offset     = bytestream2_get_be32(&s->gb);
+    bytestream2_skip(&s->gb, 4); /* delay_num (2), delay_den (2) */
+    s->dispose_op   = bytestream2_get_byte(&s->gb);
+    s->blend_op     = bytestream2_get_byte(&s->gb);
+    bytestream2_skip(&s->gb, 4); /* crc */
+
+    if (sequence_number == 0 &&
+        (s->cur_w != s->width ||
+         s->cur_h != s->height ||
+         s->x_offset != 0 ||
+         s->y_offset != 0) ||
+        s->cur_w <= 0 || s->cur_h <= 0 ||
+        s->x_offset < 0 || s->y_offset < 0 ||
+        s->cur_w > s->width - s->x_offset|| s->cur_h > s->height - s->y_offset)
+            return AVERROR_INVALIDDATA;
+
+    /* always (re)start with a clean frame */
+    if (sequence_number == 0)
+        s->dispose_op = APNG_DISPOSE_OP_BACKGROUND;
+
+    if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
+        av_log(avctx, AV_LOG_ERROR,
+               "Dispose operation 'previous' is not yet implemented, using 'none'.\n");
+        s->dispose_op = APNG_DISPOSE_OP_NONE;
+    }
+
+    return 0;
+}
+
+static void handle_p_frame_png(PNGDecContext *s, AVFrame *p)
+{
+    int i, j;
+    uint8_t *pd      = p->data[0];
+    uint8_t *pd_last = s->last_picture.f->data[0];
+    int ls = FFMIN(av_image_get_linesize(p->format, s->width, 0), s->width * s->bpp);
+
+    ff_thread_await_progress(&s->last_picture, INT_MAX, 0);
+    for (j = 0; j < s->height; j++) {
+        for (i = 0; i < ls; i++)
+            pd[i] += pd_last[i];
+        pd      += s->image_linesize;
+        pd_last += s->image_linesize;
+    }
+}
+
+// divide by 255 and round to nearest
+// apply a fast variant: (X+127)/255 = ((X+127)*257+257)>>16 = ((X+128)*257)>>16
+#define FAST_DIV255(x) ((((x) + 128) * 257) >> 16)
+
+static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
+                               AVFrame *p)
+{
+    int i, j;
+    uint8_t *pd      = p->data[0];
+    /* TODO make pd_last point to the one before for APNG_DISPOSE_OP_PREVIOUS */
+    uint8_t *pd_last = s->last_picture.f->data[0];
+    int ls = FFMIN(av_image_get_linesize(p->format, s->width, 0), s->width * s->bpp);
+
+    if (s->blend_op == APNG_BLEND_OP_OVER &&
+        avctx->pix_fmt != AV_PIX_FMT_RGBA && avctx->pix_fmt != AV_PIX_FMT_ARGB) {
+        avpriv_request_sample(avctx, "Blending with pixel format %s",
+                              av_get_pix_fmt_name(avctx->pix_fmt));
+        return AVERROR_PATCHWELCOME;
+    }
+
+    ff_thread_await_progress(&s->last_picture, INT_MAX, 0);
+    for (j = 0; j < s->y_offset; j++) {
+        for (i = 0; i < ls; i++)
+            pd[i] = pd_last[i];
+        pd      += s->image_linesize;
+        pd_last += s->image_linesize;
+    }
+
+    if (s->dispose_op != APNG_DISPOSE_OP_BACKGROUND && s->blend_op == APNG_BLEND_OP_OVER) {
+        uint8_t ri, gi, bi, ai;
+
+        if (avctx->pix_fmt == AV_PIX_FMT_RGBA) {
+            ri = 0;
+            gi = 1;
+            bi = 2;
+            ai = 3;
+        } else {
+            ri = 3;
+            gi = 2;
+            bi = 1;
+            ai = 0;
+        }
+
+        for (j = s->y_offset; j < s->y_offset + s->cur_h; j++) {
+            for (i = 0; i < s->x_offset * s->bpp; i++)
+                pd[i] = pd_last[i];
+            for (; i < (s->x_offset + s->cur_w) * s->bpp; i += s->bpp) {
+                uint8_t alpha = pd[i+ai];
+
+                /* output = alpha * foreground + (1-alpha) * background */
+                switch (alpha) {
+                case 0:
+                    pd[i+ri] = pd_last[i+ri];
+                    pd[i+gi] = pd_last[i+gi];
+                    pd[i+bi] = pd_last[i+bi];
+                    pd[i+ai] = 0xff;
+                    break;
+                case 255:
+                    break;
+                default:
+                    pd[i+ri] = FAST_DIV255(alpha * pd[i+ri] + (255 - alpha) * pd_last[i+ri]);
+                    pd[i+gi] = FAST_DIV255(alpha * pd[i+gi] + (255 - alpha) * pd_last[i+gi]);
+                    pd[i+bi] = FAST_DIV255(alpha * pd[i+bi] + (255 - alpha) * pd_last[i+bi]);
+                    pd[i+ai] = 0xff;
+                    break;
+                }
+            }
+            for (; i < ls; i++)
+                pd[i] = pd_last[i];
+            pd      += s->image_linesize;
+            pd_last += s->image_linesize;
+        }
+    } else {
+        for (j = s->y_offset; j < s->y_offset + s->cur_h; j++) {
+            for (i = 0; i < s->x_offset * s->bpp; i++)
+                pd[i] = pd_last[i];
+            for (i = (s->x_offset + s->cur_w) * s->bpp; i < ls; i++)
+                pd[i] = pd_last[i];
+            pd      += s->image_linesize;
+            pd_last += s->image_linesize;
+        }
+    }
+
+    for (j = s->y_offset + s->cur_h; j < s->height; j++) {
+        for (i = 0; i < ls; i++)
+            pd[i] = pd_last[i];
+        pd      += s->image_linesize;
+        pd_last += s->image_linesize;
+    }
+
+    return 0;
+}
+
+static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
+                               AVFrame *p, AVPacket *avpkt)
+{
+    AVDictionary *metadata  = NULL;
+    uint32_t tag, length;
+    int decode_next_dat = 0;
+    int ret = AVERROR_INVALIDDATA;
+
+    for (;;) {
+        length = bytestream2_get_bytes_left(&s->gb);
+        if (length <= 0) {
+            if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && length == 0) {
+                if (!(s->state & PNG_IDAT))
+                    return 0;
+                else
+                    goto exit_loop;
+            }
+            av_log(avctx, AV_LOG_ERROR, "%d bytes left\n", length);
+            if (   s->state & PNG_ALLIMAGE
+                && avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL)
+                goto exit_loop;
+            goto fail;
+        }
+
+        length = bytestream2_get_be32(&s->gb);
+        if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb)) {
+            av_log(avctx, AV_LOG_ERROR, "chunk too big\n");
+            goto fail;
+        }
+        tag = bytestream2_get_le32(&s->gb);
+        if (avctx->debug & FF_DEBUG_STARTCODE)
+            av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
+                (tag & 0xff),
+                ((tag >> 8) & 0xff),
+                ((tag >> 16) & 0xff),
+                ((tag >> 24) & 0xff), length);
+        switch (tag) {
+        case MKTAG('I', 'H', 'D', 'R'):
+            if (decode_ihdr_chunk(avctx, s, length) < 0)
+                goto fail;
+            break;
+        case MKTAG('p', 'H', 'Y', 's'):
+            if (decode_phys_chunk(avctx, s) < 0)
+                goto fail;
+            break;
+        case MKTAG('f', 'c', 'T', 'L'):
+            if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
+                goto skip_tag;
+            if ((ret = decode_fctl_chunk(avctx, s, length)) < 0)
+                goto fail;
+            decode_next_dat = 1;
+            break;
+        case MKTAG('f', 'd', 'A', 'T'):
+            if (!CONFIG_APNG_DECODER || avctx->codec_id != AV_CODEC_ID_APNG)
+                goto skip_tag;
+            if (!decode_next_dat)
+                goto fail;
+            bytestream2_get_be32(&s->gb);
+            length -= 4;
+            /* fallthrough */
+        case MKTAG('I', 'D', 'A', 'T'):
+            if (CONFIG_APNG_DECODER && avctx->codec_id == AV_CODEC_ID_APNG && !decode_next_dat)
+                goto skip_tag;
+            if (decode_idat_chunk(avctx, s, length, p) < 0)
+                goto fail;
+            break;
+        case MKTAG('P', 'L', 'T', 'E'):
+            if (decode_plte_chunk(avctx, s, length) < 0)
+                goto skip_tag;
+            break;
+        case MKTAG('t', 'R', 'N', 'S'):
+            if (decode_trns_chunk(avctx, s, length) < 0)
+                goto skip_tag;
+            break;
+        case MKTAG('t', 'E', 'X', 't'):
+            if (decode_text_chunk(s, length, 0, &metadata) < 0)
+                av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
+            bytestream2_skip(&s->gb, length + 4);
+            break;
+        case MKTAG('z', 'T', 'X', 't'):
+            if (decode_text_chunk(s, length, 1, &metadata) < 0)
+                av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
+            bytestream2_skip(&s->gb, length + 4);
+            break;
+        case MKTAG('I', 'E', 'N', 'D'):
+            if (!(s->state & PNG_ALLIMAGE))
+                av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
+            if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
+                goto fail;
+            }
+            bytestream2_skip(&s->gb, 4); /* crc */
+            goto exit_loop;
+        default:
+            /* skip tag */
+skip_tag:
+            bytestream2_skip(&s->gb, length + 4);
+            break;
+        }
+    }
+exit_loop:
+
+    if (s->bits_per_pixel <= 4)
+        handle_small_bpp(s, p);
+
+    /* handle p-frames only if a predecessor frame is available */
+    if (s->last_picture.f->data[0]) {
+        if (   !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG")
+            && s->last_picture.f->width == p->width
+            && s->last_picture.f->height== p->height
+            && s->last_picture.f->format== p->format
+         ) {
+            if (CONFIG_PNG_DECODER && avctx->codec_id != AV_CODEC_ID_APNG)
+                handle_p_frame_png(s, p);
+            else if (CONFIG_APNG_DECODER &&
+                     avctx->codec_id == AV_CODEC_ID_APNG &&
+                     (ret = handle_p_frame_apng(avctx, s, p)) < 0)
+                goto fail;
+        }
+    }
+    ff_thread_report_progress(&s->picture, INT_MAX, 0);
+
+    av_frame_set_metadata(p, metadata);
+    metadata   = NULL;
+    return 0;
+
+fail:
+    av_dict_free(&metadata);
+    ff_thread_report_progress(&s->picture, INT_MAX, 0);
+    return ret;
+}
+
+#if CONFIG_PNG_DECODER
+static int decode_frame_png(AVCodecContext *avctx,
                         void *data, int *got_frame,
                         AVPacket *avpkt)
 {
@@ -527,8 +1088,6 @@
     const uint8_t *buf     = avpkt->data;
     int buf_size           = avpkt->size;
     AVFrame *p;
-    AVDictionary *metadata  = NULL;
-    uint32_t tag, length;
     int64_t sig;
     int ret;
 
@@ -557,324 +1116,9 @@
         av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret);
         return AVERROR_EXTERNAL;
     }
-    for (;;) {
-        if (bytestream2_get_bytes_left(&s->gb) <= 0) {
-            av_log(avctx, AV_LOG_ERROR, "%d bytes left\n", bytestream2_get_bytes_left(&s->gb));
-            if (   s->state & PNG_ALLIMAGE
-                && avctx->strict_std_compliance <= FF_COMPLIANCE_NORMAL)
-                goto exit_loop;
-            goto fail;
-        }
 
-        length = bytestream2_get_be32(&s->gb);
-        if (length > 0x7fffffff || length > bytestream2_get_bytes_left(&s->gb))  {
-            av_log(avctx, AV_LOG_ERROR, "chunk too big\n");
-            goto fail;
-        }
-        tag = bytestream2_get_le32(&s->gb);
-        if (avctx->debug & FF_DEBUG_STARTCODE)
-            av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
-                (tag & 0xff),
-                ((tag >> 8) & 0xff),
-                ((tag >> 16) & 0xff),
-                ((tag >> 24) & 0xff), length);
-        switch (tag) {
-        case MKTAG('I', 'H', 'D', 'R'):
-            if (length != 13)
-                goto fail;
-            s->width  = bytestream2_get_be32(&s->gb);
-            s->height = bytestream2_get_be32(&s->gb);
-            if (av_image_check_size(s->width, s->height, 0, avctx)) {
-                s->width = s->height = 0;
-                av_log(avctx, AV_LOG_ERROR, "Invalid image size\n");
-                goto fail;
-            }
-            s->bit_depth        = bytestream2_get_byte(&s->gb);
-            s->color_type       = bytestream2_get_byte(&s->gb);
-            s->compression_type = bytestream2_get_byte(&s->gb);
-            s->filter_type      = bytestream2_get_byte(&s->gb);
-            s->interlace_type   = bytestream2_get_byte(&s->gb);
-            bytestream2_skip(&s->gb, 4); /* crc */
-            s->state |= PNG_IHDR;
-            if (avctx->debug & FF_DEBUG_PICT_INFO)
-                av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d "
-                           "compression_type=%d filter_type=%d interlace_type=%d\n",
-                    s->width, s->height, s->bit_depth, s->color_type,
-                    s->compression_type, s->filter_type, s->interlace_type);
-            break;
-        case MKTAG('p', 'H', 'Y', 's'):
-            if (s->state & PNG_IDAT) {
-                av_log(avctx, AV_LOG_ERROR, "pHYs after IDAT\n");
-                goto fail;
-            }
-            avctx->sample_aspect_ratio.num = bytestream2_get_be32(&s->gb);
-            avctx->sample_aspect_ratio.den = bytestream2_get_be32(&s->gb);
-            if (avctx->sample_aspect_ratio.num < 0 || avctx->sample_aspect_ratio.den < 0)
-                avctx->sample_aspect_ratio = (AVRational){ 0, 1 };
-            bytestream2_skip(&s->gb, 1); /* unit specifier */
-            bytestream2_skip(&s->gb, 4); /* crc */
-            break;
-        case MKTAG('I', 'D', 'A', 'T'):
-            if (!(s->state & PNG_IHDR)) {
-                av_log(avctx, AV_LOG_ERROR, "IDAT without IHDR\n");
-                goto fail;
-            }
-            if (!(s->state & PNG_IDAT)) {
-                /* init image info */
-                avctx->width  = s->width;
-                avctx->height = s->height;
-
-                s->channels       = ff_png_get_nb_channels(s->color_type);
-                s->bits_per_pixel = s->bit_depth * s->channels;
-                s->bpp            = (s->bits_per_pixel + 7) >> 3;
-                s->row_size       = (avctx->width * s->bits_per_pixel + 7) >> 3;
-
-                if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
-                    s->color_type == PNG_COLOR_TYPE_RGB) {
-                    avctx->pix_fmt = AV_PIX_FMT_RGB24;
-                } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
-                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
-                    avctx->pix_fmt = AV_PIX_FMT_RGBA;
-                } else if ((s->bit_depth == 2 || s->bit_depth == 4 || s->bit_depth == 8) &&
-                           s->color_type == PNG_COLOR_TYPE_GRAY) {
-                    avctx->pix_fmt = AV_PIX_FMT_GRAY8;
-                } else if (s->bit_depth == 16 &&
-                           s->color_type == PNG_COLOR_TYPE_GRAY) {
-                    avctx->pix_fmt = AV_PIX_FMT_GRAY16BE;
-                } else if (s->bit_depth == 16 &&
-                           s->color_type == PNG_COLOR_TYPE_RGB) {
-                    avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
-                } else if (s->bit_depth == 16 &&
-                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
-                    avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
-                } else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) &&
-                           s->color_type == PNG_COLOR_TYPE_PALETTE) {
-                    avctx->pix_fmt = AV_PIX_FMT_PAL8;
-                } else if (s->bit_depth == 1 && s->bits_per_pixel == 1) {
-                    avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
-                } else if (s->bit_depth == 8 &&
-                           s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
-                    avctx->pix_fmt = AV_PIX_FMT_YA8;
-                } else if (s->bit_depth == 16 &&
-                           s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
-                    avctx->pix_fmt = AV_PIX_FMT_YA16BE;
-                } else {
-                    av_log(avctx, AV_LOG_ERROR, "unsupported bit depth %d "
-                                                "and color type %d\n",
-                                                 s->bit_depth, s->color_type);
-                    goto fail;
-                }
-
-                if (ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF) < 0)
-                    goto fail;
-                ff_thread_finish_setup(avctx);
-
-                p->pict_type        = AV_PICTURE_TYPE_I;
-                p->key_frame        = 1;
-                p->interlaced_frame = !!s->interlace_type;
-
-                /* compute the compressed row size */
-                if (!s->interlace_type) {
-                    s->crow_size = s->row_size + 1;
-                } else {
-                    s->pass          = 0;
-                    s->pass_row_size = ff_png_pass_row_size(s->pass,
-                                                            s->bits_per_pixel,
-                                                            s->width);
-                    s->crow_size = s->pass_row_size + 1;
-                }
-                av_dlog(avctx, "row_size=%d crow_size =%d\n",
-                        s->row_size, s->crow_size);
-                s->image_buf      = p->data[0];
-                s->image_linesize = p->linesize[0];
-                /* copy the palette if needed */
-                if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
-                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
-                /* empty row is used if differencing to the first row */
-                av_fast_padded_mallocz(&s->last_row, &s->last_row_size, s->row_size);
-                if (!s->last_row)
-                    goto fail;
-                if (s->interlace_type ||
-                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
-                    av_fast_padded_malloc(&s->tmp_row, &s->tmp_row_size, s->row_size);
-                    if (!s->tmp_row)
-                        goto fail;
-                }
-                /* compressed row */
-                av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16);
-                if (!s->buffer)
-                    goto fail;
-
-                /* we want crow_buf+1 to be 16-byte aligned */
-                s->crow_buf          = s->buffer + 15;
-                s->zstream.avail_out = s->crow_size;
-                s->zstream.next_out  = s->crow_buf;
-            }
-            s->state |= PNG_IDAT;
-            if (png_decode_idat(s, length) < 0)
-                goto fail;
-            bytestream2_skip(&s->gb, 4); /* crc */
-            break;
-        case MKTAG('P', 'L', 'T', 'E'):
-        {
-            int n, i, r, g, b;
-
-            if ((length % 3) != 0 || length > 256 * 3)
-                goto skip_tag;
-            /* read the palette */
-            n = length / 3;
-            for (i = 0; i < n; i++) {
-                r = bytestream2_get_byte(&s->gb);
-                g = bytestream2_get_byte(&s->gb);
-                b = bytestream2_get_byte(&s->gb);
-                s->palette[i] = (0xFFU << 24) | (r << 16) | (g << 8) | b;
-            }
-            for (; i < 256; i++)
-                s->palette[i] = (0xFFU << 24);
-            s->state |= PNG_PLTE;
-            bytestream2_skip(&s->gb, 4);     /* crc */
-        }
-        break;
-        case MKTAG('t', 'R', 'N', 'S'):
-        {
-            int v, i;
-
-            /* read the transparency. XXX: Only palette mode supported */
-            if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
-                length > 256 ||
-                !(s->state & PNG_PLTE))
-                goto skip_tag;
-            for (i = 0; i < length; i++) {
-                v = bytestream2_get_byte(&s->gb);
-                s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
-            }
-            bytestream2_skip(&s->gb, 4);     /* crc */
-        }
-        break;
-        case MKTAG('t', 'E', 'X', 't'):
-            if (decode_text_chunk(s, length, 0, &metadata) < 0)
-                av_log(avctx, AV_LOG_WARNING, "Broken tEXt chunk\n");
-            bytestream2_skip(&s->gb, length + 4);
-            break;
-        case MKTAG('z', 'T', 'X', 't'):
-            if (decode_text_chunk(s, length, 1, &metadata) < 0)
-                av_log(avctx, AV_LOG_WARNING, "Broken zTXt chunk\n");
-            bytestream2_skip(&s->gb, length + 4);
-            break;
-        case MKTAG('I', 'E', 'N', 'D'):
-            if (!(s->state & PNG_ALLIMAGE))
-                av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
-            if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
-                goto fail;
-            }
-            bytestream2_skip(&s->gb, 4); /* crc */
-            goto exit_loop;
-        default:
-            /* skip tag */
-skip_tag:
-            bytestream2_skip(&s->gb, length + 4);
-            break;
-        }
-    }
-exit_loop:
-
-    if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE){
-        int i, j, k;
-        uint8_t *pd = p->data[0];
-        for (j = 0; j < s->height; j++) {
-            i = s->width / 8;
-            for (k = 7; k >= 1; k--)
-                if ((s->width&7) >= k)
-                    pd[8*i + k - 1] = (pd[i]>>8-k) & 1;
-            for (i--; i >= 0; i--) {
-                pd[8*i + 7]=  pd[i]     & 1;
-                pd[8*i + 6]= (pd[i]>>1) & 1;
-                pd[8*i + 5]= (pd[i]>>2) & 1;
-                pd[8*i + 4]= (pd[i]>>3) & 1;
-                pd[8*i + 3]= (pd[i]>>4) & 1;
-                pd[8*i + 2]= (pd[i]>>5) & 1;
-                pd[8*i + 1]= (pd[i]>>6) & 1;
-                pd[8*i + 0]=  pd[i]>>7;
-            }
-            pd += s->image_linesize;
-        }
-    }
-    if (s->bits_per_pixel == 2){
-        int i, j;
-        uint8_t *pd = p->data[0];
-        for (j = 0; j < s->height; j++) {
-            i = s->width / 4;
-            if (s->color_type == PNG_COLOR_TYPE_PALETTE){
-                if ((s->width&3) >= 3) pd[4*i + 2]= (pd[i] >> 2) & 3;
-                if ((s->width&3) >= 2) pd[4*i + 1]= (pd[i] >> 4) & 3;
-                if ((s->width&3) >= 1) pd[4*i + 0]=  pd[i] >> 6;
-                for (i--; i >= 0; i--) {
-                    pd[4*i + 3]=  pd[i]     & 3;
-                    pd[4*i + 2]= (pd[i]>>2) & 3;
-                    pd[4*i + 1]= (pd[i]>>4) & 3;
-                    pd[4*i + 0]=  pd[i]>>6;
-                }
-            } else {
-                if ((s->width&3) >= 3) pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
-                if ((s->width&3) >= 2) pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
-                if ((s->width&3) >= 1) pd[4*i + 0]= ( pd[i]>>6     )*0x55;
-                for (i--; i >= 0; i--) {
-                    pd[4*i + 3]= ( pd[i]     & 3)*0x55;
-                    pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
-                    pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
-                    pd[4*i + 0]= ( pd[i]>>6     )*0x55;
-                }
-            }
-            pd += s->image_linesize;
-        }
-    }
-    if (s->bits_per_pixel == 4){
-        int i, j;
-        uint8_t *pd = p->data[0];
-        for (j = 0; j < s->height; j++) {
-            i = s->width/2;
-            if (s->color_type == PNG_COLOR_TYPE_PALETTE){
-                if (s->width&1) pd[2*i+0]= pd[i]>>4;
-                for (i--; i >= 0; i--) {
-                pd[2*i + 1] = pd[i] & 15;
-                pd[2*i + 0] = pd[i] >> 4;
-            }
-            } else {
-                if (s->width & 1) pd[2*i + 0]= (pd[i] >> 4) * 0x11;
-                for (i--; i >= 0; i--) {
-                    pd[2*i + 1] = (pd[i] & 15) * 0x11;
-                    pd[2*i + 0] = (pd[i] >> 4) * 0x11;
-                }
-            }
-            pd += s->image_linesize;
-        }
-    }
-
-    /* handle p-frames only if a predecessor frame is available */
-    if (s->last_picture.f->data[0]) {
-        if (   !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG")
-            && s->last_picture.f->width == p->width
-            && s->last_picture.f->height== p->height
-            && s->last_picture.f->format== p->format
-         ) {
-            int i, j;
-            uint8_t *pd      = p->data[0];
-            uint8_t *pd_last = s->last_picture.f->data[0];
-            int ls = FFMIN(av_image_get_linesize(p->format, s->width, 0), s->width * s->bpp);
-
-            ff_thread_await_progress(&s->last_picture, INT_MAX, 0);
-            for (j = 0; j < s->height; j++) {
-                for (i = 0; i < ls; i++)
-                    pd[i] += pd_last[i];
-                pd      += s->image_linesize;
-                pd_last += s->image_linesize;
-            }
-        }
-    }
-    ff_thread_report_progress(&s->picture, INT_MAX, 0);
-
-    av_frame_set_metadata(p, metadata);
-    metadata   = NULL;
+    if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
+        goto the_end;
 
     if ((ret = av_frame_ref(data, s->picture.f)) < 0)
         return ret;
@@ -886,12 +1130,64 @@
     inflateEnd(&s->zstream);
     s->crow_buf = NULL;
     return ret;
-fail:
-    av_dict_free(&metadata);
-    ff_thread_report_progress(&s->picture, INT_MAX, 0);
-    ret = AVERROR_INVALIDDATA;
-    goto the_end;
 }
+#endif
+
+#if CONFIG_APNG_DECODER
+static int decode_frame_apng(AVCodecContext *avctx,
+                        void *data, int *got_frame,
+                        AVPacket *avpkt)
+{
+    PNGDecContext *const s = avctx->priv_data;
+    int ret;
+    AVFrame *p;
+
+    ff_thread_release_buffer(avctx, &s->last_picture);
+    FFSWAP(ThreadFrame, s->picture, s->last_picture);
+    p = s->picture.f;
+
+    if (!(s->state & PNG_IHDR)) {
+        if (!avctx->extradata_size)
+            return AVERROR_INVALIDDATA;
+
+        /* only init fields, there is no zlib use in extradata */
+        s->zstream.zalloc = ff_png_zalloc;
+        s->zstream.zfree  = ff_png_zfree;
+
+        bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size);
+        if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
+            goto end;
+    }
+
+    /* reset state for a new frame */
+    if ((ret = inflateInit(&s->zstream)) != Z_OK) {
+        av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret);
+        ret = AVERROR_EXTERNAL;
+        goto end;
+    }
+    s->y = 0;
+    s->state &= ~(PNG_IDAT | PNG_ALLIMAGE);
+    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
+    if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0)
+        goto end;
+
+    if (!(s->state & PNG_ALLIMAGE))
+        av_log(avctx, AV_LOG_WARNING, "Frame did not contain a complete image\n");
+    if (!(s->state & (PNG_ALLIMAGE|PNG_IDAT))) {
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+    if ((ret = av_frame_ref(data, s->picture.f)) < 0)
+        goto end;
+
+    *got_frame = 1;
+    ret = bytestream2_tell(&s->gb);
+
+end:
+    inflateEnd(&s->zstream);
+    return ret;
+}
+#endif
 
 static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
 {
@@ -944,6 +1240,23 @@
     return 0;
 }
 
+#if CONFIG_APNG_DECODER
+AVCodec ff_apng_decoder = {
+    .name           = "apng",
+    .long_name      = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_APNG,
+    .priv_data_size = sizeof(PNGDecContext),
+    .init           = png_dec_init,
+    .close          = png_dec_end,
+    .decode         = decode_frame_apng,
+    .init_thread_copy = ONLY_IF_THREADS_ENABLED(png_dec_init),
+    .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
+    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
+};
+#endif
+
+#if CONFIG_PNG_DECODER
 AVCodec ff_png_decoder = {
     .name           = "png",
     .long_name      = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"),
@@ -952,8 +1265,9 @@
     .priv_data_size = sizeof(PNGDecContext),
     .init           = png_dec_init,
     .close          = png_dec_end,
-    .decode         = decode_frame,
+    .decode         = decode_frame_png,
     .init_thread_copy = ONLY_IF_THREADS_ENABLED(png_dec_init),
     .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context),
     .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
 };
+#endif
diff --git a/libavcodec/ppc/h264chroma_template.c b/libavcodec/ppc/h264chroma_template.c
index 7436e11..cb1e095 100644
--- a/libavcodec/ppc/h264chroma_template.c
+++ b/libavcodec/ppc/h264chroma_template.c
@@ -19,12 +19,14 @@
  */
 
 #include "libavutil/mem.h"
+#include "libavutil/ppc/types_altivec.h"
+#include "libavutil/ppc/util_altivec.h"
 
 /* this code assume that stride % 16 == 0 */
 
 #define CHROMA_MC8_ALTIVEC_CORE(BIAS1, BIAS2) \
-        vsrc2ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc2uc);\
-        vsrc3ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc3uc);\
+        vsrc2ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc2uc);\
+        vsrc3ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc3uc);\
 \
         psum = vec_mladd(vA, vsrc0ssH, BIAS1);\
         psum = vec_mladd(vB, vsrc1ssH, psum);\
@@ -49,8 +51,8 @@
 
 #define CHROMA_MC8_ALTIVEC_CORE_SIMPLE \
 \
-        vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc0uc);\
-        vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc1uc);\
+        vsrc0ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc0uc);\
+        vsrc1ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc1uc);\
 \
         psum = vec_mladd(vA, vsrc0ssH, v32ss);\
         psum = vec_mladd(vE, vsrc1ssH, psum);\
@@ -70,6 +72,43 @@
 #define noop(a) a
 #define add28(a) vec_add(v28ss, a)
 
+#if HAVE_BIGENDIAN
+#define GET_VSRC1(vs0, off, b, perm0, s){    \
+    vec_u8 vsrcCuc, vsrcDuc;                 \
+    vsrcCuc = vec_ld(off, s);                \
+    if (loadSecond){                         \
+        vsrcDuc = vec_ld(off + b, s);        \
+    } else                                   \
+        vsrcDuc = vsrcCuc;                   \
+                                             \
+    vs0 = vec_perm(vsrcCuc, vsrcDuc, perm0); \
+}
+#define GET_VSRC(vs0, vs1, off, b, perm0, perm1, s){ \
+    vec_u8 vsrcCuc, vsrcDuc;                         \
+    vsrcCuc = vec_ld(off, s);                        \
+    if (loadSecond){                                 \
+        vsrcDuc = vec_ld(off + b, s);                \
+    } else                                           \
+        vsrcDuc = vsrcCuc;                           \
+                                                     \
+    vs0 = vec_perm(vsrcCuc, vsrcDuc, perm0);         \
+    if (reallyBadAlign){                             \
+        vs1 = vsrcDuc;                               \
+    } else                                           \
+        vs1 = vec_perm(vsrcCuc, vsrcDuc, perm1);     \
+ }
+
+#else
+
+#define GET_VSRC1(vs0, off, b, perm0, s){            \
+    vs0 = vec_vsx_ld(off, s);                        \
+ }
+#define GET_VSRC(vs0, vs1, off, b, perm0, perm1, s){ \
+    vs0 = vec_vsx_ld(off, s);                        \
+    vs1 = vec_vsx_ld(off + 1, s);                    \
+ }
+#endif /* HAVE_BIGENDIAN */
+
 #ifdef PREFIX_h264_chroma_mc8_altivec
 static void PREFIX_h264_chroma_mc8_altivec(uint8_t * dst, uint8_t * src,
                                     int stride, int h, int x, int y) {
@@ -80,23 +119,27 @@
                          ((    x) * (    y))};
     register int i;
     vec_u8 fperm;
-    const vec_s32 vABCD = vec_ld(0, ABCD);
-    const vec_s16 vA = vec_splat((vec_s16)vABCD, 1);
-    const vec_s16 vB = vec_splat((vec_s16)vABCD, 3);
-    const vec_s16 vC = vec_splat((vec_s16)vABCD, 5);
-    const vec_s16 vD = vec_splat((vec_s16)vABCD, 7);
     LOAD_ZERO;
+    const vec_s32 vABCD = vec_ld(0, ABCD);
+    const vec_s16 vA = VEC_SPLAT16(vABCD, 1);
+    const vec_s16 vB = VEC_SPLAT16(vABCD, 3);
+    const vec_s16 vC = VEC_SPLAT16(vABCD, 5);
+    const vec_s16 vD = VEC_SPLAT16(vABCD, 7);
     const vec_s16 v32ss = vec_sl(vec_splat_s16(1),vec_splat_u16(5));
     const vec_u16 v6us = vec_splat_u16(6);
-    register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
-    register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
 
-    vec_u8 vsrcAuc, av_uninit(vsrcBuc), vsrcperm0, vsrcperm1;
+    vec_u8 vsrcperm0, vsrcperm1;
     vec_u8 vsrc0uc, vsrc1uc;
     vec_s16 vsrc0ssH, vsrc1ssH;
-    vec_u8 vsrcCuc, vsrc2uc, vsrc3uc;
+    vec_u8 vsrc2uc, vsrc3uc;
     vec_s16 vsrc2ssH, vsrc3ssH, psum;
     vec_u8 vdst, ppsum, vfdst, fsum;
+#if HAVE_BIGENDIAN
+    register int loadSecond = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
+    register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
+    vsrcperm0 = vec_lvsl(0, src);
+    vsrcperm1 = vec_lvsl(1, src);
+#endif
 
     if (((unsigned long)dst) % 16 == 0) {
         fperm = (vec_u8){0x10, 0x11, 0x12, 0x13,
@@ -110,89 +153,28 @@
                          0x1C, 0x1D, 0x1E, 0x1F};
     }
 
-    vsrcAuc = vec_ld(0, src);
+    GET_VSRC(vsrc0uc, vsrc1uc, 0, 16, vsrcperm0, vsrcperm1, src);
 
-    if (loadSecond)
-        vsrcBuc = vec_ld(16, src);
-    vsrcperm0 = vec_lvsl(0, src);
-    vsrcperm1 = vec_lvsl(1, src);
-
-    vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0);
-    if (reallyBadAlign)
-        vsrc1uc = vsrcBuc;
-    else
-        vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1);
-
-    vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc0uc);
-    vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v,(vec_u8)vsrc1uc);
+    vsrc0ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc0uc);
+    vsrc1ssH = (vec_s16)VEC_MERGEH(zero_u8v,(vec_u8)vsrc1uc);
 
     if (ABCD[3]) {
-        if (!loadSecond) {// -> !reallyBadAlign
-            for (i = 0 ; i < h ; i++) {
-                vsrcCuc = vec_ld(stride + 0, src);
-                vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
-                vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
-
-                CHROMA_MC8_ALTIVEC_CORE(v32ss, noop)
-            }
-        } else {
-            vec_u8 vsrcDuc;
-            for (i = 0 ; i < h ; i++) {
-                vsrcCuc = vec_ld(stride + 0, src);
-                vsrcDuc = vec_ld(stride + 16, src);
-                vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
-                if (reallyBadAlign)
-                    vsrc3uc = vsrcDuc;
-                else
-                    vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
-
-                CHROMA_MC8_ALTIVEC_CORE(v32ss, noop)
-            }
+        for (i = 0 ; i < h ; i++) {
+            GET_VSRC(vsrc2uc, vsrc3uc, stride, 16, vsrcperm0, vsrcperm1, src);
+            CHROMA_MC8_ALTIVEC_CORE(v32ss, noop);
         }
     } else {
         const vec_s16 vE = vec_add(vB, vC);
         if (ABCD[2]) { // x == 0 B == 0
-            if (!loadSecond) {// -> !reallyBadAlign
-                for (i = 0 ; i < h ; i++) {
-                    vsrcCuc = vec_ld(stride + 0, src);
-                    vsrc1uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
-                    CHROMA_MC8_ALTIVEC_CORE_SIMPLE
-
-                    vsrc0uc = vsrc1uc;
-                }
-            } else {
-                vec_u8 vsrcDuc;
-                for (i = 0 ; i < h ; i++) {
-                    vsrcCuc = vec_ld(stride + 0, src);
-                    vsrcDuc = vec_ld(stride + 15, src);
-                    vsrc1uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
-                    CHROMA_MC8_ALTIVEC_CORE_SIMPLE
-
-                    vsrc0uc = vsrc1uc;
-                }
+            for (i = 0 ; i < h ; i++) {
+                GET_VSRC1(vsrc1uc, stride, 15, vsrcperm0, src);
+                CHROMA_MC8_ALTIVEC_CORE_SIMPLE;
+                vsrc0uc = vsrc1uc;
             }
         } else { // y == 0 C == 0
-            if (!loadSecond) {// -> !reallyBadAlign
-                for (i = 0 ; i < h ; i++) {
-                    vsrcCuc = vec_ld(0, src);
-                    vsrc0uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
-                    vsrc1uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
-
-                    CHROMA_MC8_ALTIVEC_CORE_SIMPLE
-                }
-            } else {
-                vec_u8 vsrcDuc;
-                for (i = 0 ; i < h ; i++) {
-                    vsrcCuc = vec_ld(0, src);
-                    vsrcDuc = vec_ld(15, src);
-                    vsrc0uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
-                    if (reallyBadAlign)
-                        vsrc1uc = vsrcDuc;
-                    else
-                        vsrc1uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
-
-                    CHROMA_MC8_ALTIVEC_CORE_SIMPLE
-                }
+            for (i = 0 ; i < h ; i++) {
+               GET_VSRC(vsrc0uc, vsrc1uc, 0, 15, vsrcperm0, vsrcperm1, src);
+               CHROMA_MC8_ALTIVEC_CORE_SIMPLE;
             }
         }
     }
@@ -209,23 +191,27 @@
                          ((    x) * (    y))};
     register int i;
     vec_u8 fperm;
-    const vec_s32 vABCD = vec_ld(0, ABCD);
-    const vec_s16 vA = vec_splat((vec_s16)vABCD, 1);
-    const vec_s16 vB = vec_splat((vec_s16)vABCD, 3);
-    const vec_s16 vC = vec_splat((vec_s16)vABCD, 5);
-    const vec_s16 vD = vec_splat((vec_s16)vABCD, 7);
     LOAD_ZERO;
+    const vec_s32 vABCD = vec_ld(0, ABCD);
+    const vec_s16 vA = VEC_SPLAT16(vABCD, 1);
+    const vec_s16 vB = VEC_SPLAT16(vABCD, 3);
+    const vec_s16 vC = VEC_SPLAT16(vABCD, 5);
+    const vec_s16 vD = VEC_SPLAT16(vABCD, 7);
     const vec_s16 v28ss = vec_sub(vec_sl(vec_splat_s16(1),vec_splat_u16(5)),vec_splat_s16(4));
     const vec_u16 v6us  = vec_splat_u16(6);
-    register int loadSecond     = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
-    register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
 
-    vec_u8 vsrcAuc, av_uninit(vsrcBuc), vsrcperm0, vsrcperm1;
+    vec_u8 vsrcperm0, vsrcperm1;
     vec_u8 vsrc0uc, vsrc1uc;
     vec_s16 vsrc0ssH, vsrc1ssH;
-    vec_u8 vsrcCuc, vsrc2uc, vsrc3uc;
+    vec_u8 vsrc2uc, vsrc3uc;
     vec_s16 vsrc2ssH, vsrc3ssH, psum;
     vec_u8 vdst, ppsum, vfdst, fsum;
+#if HAVE_BIGENDIAN
+    register int loadSecond     = (((unsigned long)src) % 16) <= 7 ? 0 : 1;
+    register int reallyBadAlign = (((unsigned long)src) % 16) == 15 ? 1 : 0;
+    vsrcperm0 = vec_lvsl(0, src);
+    vsrcperm1 = vec_lvsl(1, src);
+#endif
 
     if (((unsigned long)dst) % 16 == 0) {
         fperm = (vec_u8){0x10, 0x11, 0x12, 0x13,
@@ -239,47 +225,14 @@
                          0x1C, 0x1D, 0x1E, 0x1F};
     }
 
-    vsrcAuc = vec_ld(0, src);
+    GET_VSRC(vsrc0uc, vsrc1uc, 0, 16, vsrcperm0, vsrcperm1, src);
 
-    if (loadSecond)
-        vsrcBuc = vec_ld(16, src);
-    vsrcperm0 = vec_lvsl(0, src);
-    vsrcperm1 = vec_lvsl(1, src);
+    vsrc0ssH = (vec_s16)VEC_MERGEH(zero_u8v, (vec_u8)vsrc0uc);
+    vsrc1ssH = (vec_s16)VEC_MERGEH(zero_u8v, (vec_u8)vsrc1uc);
 
-    vsrc0uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm0);
-    if (reallyBadAlign)
-        vsrc1uc = vsrcBuc;
-    else
-        vsrc1uc = vec_perm(vsrcAuc, vsrcBuc, vsrcperm1);
-
-    vsrc0ssH = (vec_s16)vec_mergeh(zero_u8v, (vec_u8)vsrc0uc);
-    vsrc1ssH = (vec_s16)vec_mergeh(zero_u8v, (vec_u8)vsrc1uc);
-
-    if (!loadSecond) {// -> !reallyBadAlign
-        for (i = 0 ; i < h ; i++) {
-
-
-            vsrcCuc = vec_ld(stride + 0, src);
-
-            vsrc2uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm0);
-            vsrc3uc = vec_perm(vsrcCuc, vsrcCuc, vsrcperm1);
-
-            CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28)
-        }
-    } else {
-        vec_u8 vsrcDuc;
-        for (i = 0 ; i < h ; i++) {
-            vsrcCuc = vec_ld(stride + 0, src);
-            vsrcDuc = vec_ld(stride + 16, src);
-
-            vsrc2uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm0);
-            if (reallyBadAlign)
-                vsrc3uc = vsrcDuc;
-            else
-                vsrc3uc = vec_perm(vsrcCuc, vsrcDuc, vsrcperm1);
-
-            CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28)
-        }
+    for (i = 0 ; i < h ; i++) {
+        GET_VSRC(vsrc2uc, vsrc3uc, stride, 16, vsrcperm0, vsrcperm1, src);
+        CHROMA_MC8_ALTIVEC_CORE(vec_splat_s16(0), add28);
     }
 }
 #endif
diff --git a/libavcodec/ppc/h264dsp.c b/libavcodec/ppc/h264dsp.c
index 7fc7e0b..da118a4 100644
--- a/libavcodec/ppc/h264dsp.c
+++ b/libavcodec/ppc/h264dsp.c
@@ -62,10 +62,17 @@
     b2 = vec_mergeh( a1, a3 ); \
     b3 = vec_mergel( a1, a3 )
 
+#if HAVE_BIGENDIAN
+#define vdst_load(d)              \
+    vdst_orig = vec_ld(0, dst);   \
+    vdst = vec_perm(vdst_orig, zero_u8v, vdst_mask);
+#else
+#define vdst_load(d) vdst = vec_vsx_ld(0, dst)
+#endif
+
 #define VEC_LOAD_U8_ADD_S16_STORE_U8(va)                      \
-    vdst_orig = vec_ld(0, dst);                               \
-    vdst = vec_perm(vdst_orig, zero_u8v, vdst_mask);          \
-    vdst_ss = (vec_s16) vec_mergeh(zero_u8v, vdst);         \
+    vdst_load();                                              \
+    vdst_ss = (vec_s16) VEC_MERGEH(zero_u8v, vdst);           \
     va = vec_add(va, vdst_ss);                                \
     va_u8 = vec_packsu(va, zero_s16v);                        \
     va_u32 = vec_splat((vec_u32)va_u8, 0);                  \
@@ -165,26 +172,43 @@
     d7 = vec_sub(b0v, b7v); \
 }
 
-#define ALTIVEC_STORE_SUM_CLIP(dest, idctv, perm_ldv, perm_stv, sel) { \
-    /* unaligned load */                                       \
-    vec_u8 hv = vec_ld( 0, dest );                           \
-    vec_u8 lv = vec_ld( 7, dest );                           \
-    vec_u8 dstv   = vec_perm( hv, lv, (vec_u8)perm_ldv );  \
-    vec_s16 idct_sh6 = vec_sra(idctv, sixv);                 \
-    vec_u16 dst16 = (vec_u16)vec_mergeh(zero_u8v, dstv);   \
-    vec_s16 idstsum = vec_adds(idct_sh6, (vec_s16)dst16);  \
-    vec_u8 idstsum8 = vec_packsu(zero_s16v, idstsum);        \
-    vec_u8 edgehv;                                           \
-    /* unaligned store */                                      \
-    vec_u8 bodyv  = vec_perm( idstsum8, idstsum8, perm_stv );\
-    vec_u8 edgelv = vec_perm( sel, zero_u8v, perm_stv );     \
+#if HAVE_BIGENDIAN
+#define GET_2PERM(ldv, stv, d)  \
+    ldv = vec_lvsl(0, d);       \
+    stv = vec_lvsr(8, d);
+#define dstv_load(d)            \
+    vec_u8 hv = vec_ld( 0, d ); \
+    vec_u8 lv = vec_ld( 7, d);  \
+    vec_u8 dstv   = vec_perm( hv, lv, (vec_u8)perm_ldv );
+#define dest_unligned_store(d)                                 \
+    vec_u8 edgehv;                                             \
+    vec_u8 bodyv  = vec_perm( idstsum8, idstsum8, perm_stv );  \
+    vec_u8 edgelv = vec_perm( sel, zero_u8v, perm_stv );       \
     lv    = vec_sel( lv, bodyv, edgelv );                      \
-    vec_st( lv, 7, dest );                                     \
-    hv    = vec_ld( 0, dest );                                 \
+    vec_st( lv, 7, d );                                        \
+    hv    = vec_ld( 0, d );                                    \
     edgehv = vec_perm( zero_u8v, sel, perm_stv );              \
     hv    = vec_sel( hv, bodyv, edgehv );                      \
-    vec_st( hv, 0, dest );                                     \
- }
+    vec_st( hv, 0, d );
+#else
+
+#define GET_2PERM(ldv, stv, d) {}
+#define dstv_load(d) vec_u8 dstv = vec_vsx_ld(0, d)
+#define dest_unligned_store(d)\
+    vec_u8 dst8 = vec_perm((vec_u8)idstsum8, dstv, vcprm(2,3,s2,s3));\
+    vec_vsx_st(dst8, 0, d)
+#endif /* HAVE_BIGENDIAN */
+
+#define ALTIVEC_STORE_SUM_CLIP(dest, idctv, perm_ldv, perm_stv, sel) { \
+    /* unaligned load */                                       \
+    dstv_load(dest);                                           \
+    vec_s16 idct_sh6 = vec_sra(idctv, sixv);                 \
+    vec_u16 dst16 = (vec_u16)VEC_MERGEH(zero_u8v, dstv);   \
+    vec_s16 idstsum = vec_adds(idct_sh6, (vec_s16)dst16);  \
+    vec_u8 idstsum8 = vec_packsu(zero_s16v, idstsum);        \
+    /* unaligned store */                                      \
+    dest_unligned_store(dest);\
+}
 
 static void h264_idct8_add_altivec(uint8_t *dst, int16_t *dct, int stride)
 {
@@ -192,8 +216,8 @@
     vec_s16 d0, d1, d2, d3, d4, d5, d6, d7;
     vec_s16 idct0, idct1, idct2, idct3, idct4, idct5, idct6, idct7;
 
-    vec_u8 perm_ldv = vec_lvsl(0, dst);
-    vec_u8 perm_stv = vec_lvsr(8, dst);
+    vec_u8 perm_ldv, perm_stv;
+    GET_2PERM(perm_ldv, perm_stv, dst);
 
     const vec_u16 onev = vec_splat_u16(1);
     const vec_u16 twov = vec_splat_u16(2);
@@ -236,20 +260,25 @@
 {
     vec_s16 dc16;
     vec_u8 dcplus, dcminus, v0, v1, v2, v3, aligner;
+    vec_s32 v_dc32;
     LOAD_ZERO;
     DECLARE_ALIGNED(16, int, dc);
     int i;
 
     dc = (block[0] + 32) >> 6;
     block[0] = 0;
-    dc16 = vec_splat((vec_s16) vec_lde(0, &dc), 1);
+    v_dc32 = vec_lde(0, &dc);
+    dc16 = VEC_SPLAT16((vec_s16)v_dc32, 1);
 
     if (size == 4)
-        dc16 = vec_sld(dc16, zero_s16v, 8);
+        dc16 = VEC_SLD16(dc16, zero_s16v, 8);
     dcplus = vec_packsu(dc16, zero_s16v);
     dcminus = vec_packsu(vec_sub(zero_s16v, dc16), zero_s16v);
 
     aligner = vec_lvsr(0, dst);
+#if !HAVE_BIGENDIAN
+    aligner = vec_perm(aligner, zero_u8v, vcswapc());
+#endif
     dcplus = vec_perm(dcplus, dcplus, aligner);
     dcminus = vec_perm(dcminus, dcminus, aligner);
 
@@ -633,6 +662,9 @@
     temp[2] = offset;
 
     vtemp = (vec_s16)vec_ld(0, temp);
+#if !HAVE_BIGENDIAN
+    vtemp =(vec_s16)vec_perm(vtemp, vtemp, vcswapi2s(0,1,2,3));
+#endif
     vlog2_denom = (vec_u16)vec_splat(vtemp, 1);
     vweight = vec_splat(vtemp, 3);
     voffset = vec_splat(vtemp, 5);
@@ -641,8 +673,8 @@
     for (y = 0; y < height; y++) {
         vblock = vec_ld(0, block);
 
-        v0 = (vec_s16)vec_mergeh(zero_u8v, vblock);
-        v1 = (vec_s16)vec_mergel(zero_u8v, vblock);
+        v0 = (vec_s16)VEC_MERGEH(zero_u8v, vblock);
+        v1 = (vec_s16)VEC_MERGEL(zero_u8v, vblock);
 
         if (w == 16 || aligned) {
             v0 = vec_mladd(v0, vweight, zero_s16v);
@@ -679,6 +711,9 @@
     temp[3] = offset;
 
     vtemp = (vec_s16)vec_ld(0, temp);
+#if !HAVE_BIGENDIAN
+    vtemp =(vec_s16)vec_perm(vtemp, vtemp, vcswapi2s(0,1,2,3));
+#endif
     vlog2_denom = (vec_u16)vec_splat(vtemp, 1);
     vweights = vec_splat(vtemp, 3);
     vweightd = vec_splat(vtemp, 5);
@@ -690,10 +725,10 @@
         vdst = vec_ld(0, dst);
         vsrc = vec_ld(0, src);
 
-        v0 = (vec_s16)vec_mergeh(zero_u8v, vdst);
-        v1 = (vec_s16)vec_mergel(zero_u8v, vdst);
-        v2 = (vec_s16)vec_mergeh(zero_u8v, vsrc);
-        v3 = (vec_s16)vec_mergel(zero_u8v, vsrc);
+        v0 = (vec_s16)VEC_MERGEH(zero_u8v, vdst);
+        v1 = (vec_s16)VEC_MERGEL(zero_u8v, vdst);
+        v2 = (vec_s16)VEC_MERGEH(zero_u8v, vsrc);
+        v3 = (vec_s16)VEC_MERGEL(zero_u8v, vsrc);
 
         if (w == 8) {
             if (src_aligned)
diff --git a/libavcodec/ppc/h264qpel.c b/libavcodec/ppc/h264qpel.c
index 4a01f17..575f504 100644
--- a/libavcodec/ppc/h264qpel.c
+++ b/libavcodec/ppc/h264qpel.c
@@ -191,86 +191,79 @@
     OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfV, halfHV, stride, SIZE, SIZE);\
 }\
 
+#if HAVE_BIGENDIAN
+#define put_unligned_store(s, dest) {    \
+    tmp1 = vec_ld(0, dest);              \
+    mask = vec_lvsl(0, dest);            \
+    tmp2 = vec_ld(15, dest);             \
+    edges = vec_perm(tmp2, tmp1, mask);  \
+    align = vec_lvsr(0, dest);           \
+    tmp2 = vec_perm(s, edges, align);    \
+    tmp1 = vec_perm(edges, s, align);    \
+    vec_st(tmp2, 15, dest);              \
+    vec_st(tmp1, 0 , dest);              \
+ }
+#else
+#define put_unligned_store(s, dest) vec_vsx_st(s, 0, dest);
+#endif /* HAVE_BIGENDIAN */
+
 static inline void put_pixels16_l2_altivec( uint8_t * dst, const uint8_t * src1,
                                     const uint8_t * src2, int dst_stride,
                                     int src_stride1, int h)
 {
     int i;
-    vec_u8 a, b, d, tmp1, tmp2, mask, mask_, edges, align;
-
+    vec_u8 a, b, d, mask_;
+#if HAVE_BIGENDIAN
+    vec_u8 tmp1, tmp2, mask, edges, align;
     mask_ = vec_lvsl(0, src2);
+#endif
 
     for (i = 0; i < h; i++) {
-
-        tmp1 = vec_ld(i * src_stride1, src1);
-        mask = vec_lvsl(i * src_stride1, src1);
-        tmp2 = vec_ld(i * src_stride1 + 15, src1);
-
-        a = vec_perm(tmp1, tmp2, mask);
-
-        tmp1 = vec_ld(i * 16, src2);
-        tmp2 = vec_ld(i * 16 + 15, src2);
-
-        b = vec_perm(tmp1, tmp2, mask_);
-
-        tmp1 = vec_ld(0, dst);
-        mask = vec_lvsl(0, dst);
-        tmp2 = vec_ld(15, dst);
-
+        a = unaligned_load(i * src_stride1, src1);
+        b = load_with_perm_vec(i * 16, src2, mask_);
         d = vec_avg(a, b);
-
-        edges = vec_perm(tmp2, tmp1, mask);
-
-        align = vec_lvsr(0, dst);
-
-        tmp2 = vec_perm(d, edges, align);
-        tmp1 = vec_perm(edges, d, align);
-
-        vec_st(tmp2, 15, dst);
-        vec_st(tmp1, 0 , dst);
-
+        put_unligned_store(d, dst);
         dst += dst_stride;
     }
 }
 
+#if HAVE_BIGENDIAN
+#define avg_unligned_store(s, dest){            \
+    tmp1 = vec_ld(0, dest);                     \
+    mask = vec_lvsl(0, dest);                   \
+    tmp2 = vec_ld(15, dest);                    \
+    a = vec_avg(vec_perm(tmp1, tmp2, mask), s); \
+    edges = vec_perm(tmp2, tmp1, mask);         \
+    align = vec_lvsr(0, dest);                  \
+    tmp2 = vec_perm(a, edges, align);           \
+    tmp1 = vec_perm(edges, a, align);           \
+    vec_st(tmp2, 15, dest);                     \
+    vec_st(tmp1, 0 , dest);                     \
+ }
+#else
+#define avg_unligned_store(s, dest){            \
+    a = vec_avg(vec_vsx_ld(0, dst), s);         \
+    vec_vsx_st(a, 0, dst);                      \
+ }
+#endif /* HAVE_BIGENDIAN */
+
 static inline void avg_pixels16_l2_altivec( uint8_t * dst, const uint8_t * src1,
                                     const uint8_t * src2, int dst_stride,
                                     int src_stride1, int h)
 {
     int i;
-    vec_u8 a, b, d, tmp1, tmp2, mask, mask_, edges, align;
+    vec_u8 a, b, d, mask_;
 
+#if HAVE_BIGENDIAN
+    vec_u8 tmp1, tmp2, mask, edges, align;
     mask_ = vec_lvsl(0, src2);
+#endif
 
     for (i = 0; i < h; i++) {
-
-        tmp1 = vec_ld(i * src_stride1, src1);
-        mask = vec_lvsl(i * src_stride1, src1);
-        tmp2 = vec_ld(i * src_stride1 + 15, src1);
-
-        a = vec_perm(tmp1, tmp2, mask);
-
-        tmp1 = vec_ld(i * 16, src2);
-        tmp2 = vec_ld(i * 16 + 15, src2);
-
-        b = vec_perm(tmp1, tmp2, mask_);
-
-        tmp1 = vec_ld(0, dst);
-        mask = vec_lvsl(0, dst);
-        tmp2 = vec_ld(15, dst);
-
-        d = vec_avg(vec_perm(tmp1, tmp2, mask), vec_avg(a, b));
-
-        edges = vec_perm(tmp2, tmp1, mask);
-
-        align = vec_lvsr(0, dst);
-
-        tmp2 = vec_perm(d, edges, align);
-        tmp1 = vec_perm(edges, d, align);
-
-        vec_st(tmp2, 15, dst);
-        vec_st(tmp1, 0 , dst);
-
+        a = unaligned_load(i * src_stride1, src1);
+        b = load_with_perm_vec(i * 16, src2, mask_);
+        d = vec_avg(a, b);
+        avg_unligned_store(d, dst);
         dst += dst_stride;
     }
 }
diff --git a/libavcodec/ppc/h264qpel_template.c b/libavcodec/ppc/h264qpel_template.c
index 360e9e3..9a34548 100644
--- a/libavcodec/ppc/h264qpel_template.c
+++ b/libavcodec/ppc/h264qpel_template.c
@@ -18,7 +18,14 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #include "libavutil/mem.h"
+#include "libavutil/ppc/types_altivec.h"
+#include "libavutil/ppc/util_altivec.h"
 
 #ifdef DEBUG
 #define ASSERT_ALIGNED(ptr) assert(((unsigned long)ptr&0x0000000F));
@@ -26,6 +33,76 @@
 #define ASSERT_ALIGNED(ptr) ;
 #endif
 
+#if HAVE_BIGENDIAN
+#define load_alignment(s, ali, pm2, pm1, pp0, pp1, pp2, pp3){\
+    vec_u8 srcR1 = vec_ld(-2, s);\
+    vec_u8 srcR2 = vec_ld(14, s);\
+    switch (ali) {\
+    default: {\
+        srcM2 = vec_perm(srcR1, srcR2, pm2);\
+        srcM1 = vec_perm(srcR1, srcR2, pm1);\
+        srcP0 = vec_perm(srcR1, srcR2, pp0);\
+        srcP1 = vec_perm(srcR1, srcR2, pp1);\
+        srcP2 = vec_perm(srcR1, srcR2, pp2);\
+        srcP3 = vec_perm(srcR1, srcR2, pp3);\
+    } break;\
+    case 11: {\
+        srcM2 = vec_perm(srcR1, srcR2, pm2);\
+        srcM1 = vec_perm(srcR1, srcR2, pm1);\
+        srcP0 = vec_perm(srcR1, srcR2, pp0);\
+        srcP1 = vec_perm(srcR1, srcR2, pp1);\
+        srcP2 = vec_perm(srcR1, srcR2, pp2);\
+        srcP3 = srcR2;\
+    } break;\
+    case 12: {\
+        vec_u8 srcR3 = vec_ld(30, s);\
+        srcM2 = vec_perm(srcR1, srcR2, pm2);\
+        srcM1 = vec_perm(srcR1, srcR2, pm1);\
+        srcP0 = vec_perm(srcR1, srcR2, pp0);\
+        srcP1 = vec_perm(srcR1, srcR2, pp1);\
+        srcP2 = srcR2;\
+        srcP3 = vec_perm(srcR2, srcR3, pp3);\
+    } break;\
+    case 13: {\
+        vec_u8 srcR3 = vec_ld(30, s);\
+        srcM2 = vec_perm(srcR1, srcR2, pm2);\
+        srcM1 = vec_perm(srcR1, srcR2, pm1);\
+        srcP0 = vec_perm(srcR1, srcR2, pp0);\
+        srcP1 = srcR2;\
+        srcP2 = vec_perm(srcR2, srcR3, pp2);\
+        srcP3 = vec_perm(srcR2, srcR3, pp3);\
+    } break;\
+    case 14: {\
+        vec_u8 srcR3 = vec_ld(30, s);\
+        srcM2 = vec_perm(srcR1, srcR2, pm2);\
+        srcM1 = vec_perm(srcR1, srcR2, pm1);\
+        srcP0 = srcR2;\
+        srcP1 = vec_perm(srcR2, srcR3, pp1);\
+        srcP2 = vec_perm(srcR2, srcR3, pp2);\
+        srcP3 = vec_perm(srcR2, srcR3, pp3);\
+    } break;\
+    case 15: {\
+        vec_u8 srcR3 = vec_ld(30, s);\
+        srcM2 = vec_perm(srcR1, srcR2, pm2);\
+        srcM1 = srcR2;\
+        srcP0 = vec_perm(srcR2, srcR3, pp0);\
+        srcP1 = vec_perm(srcR2, srcR3, pp1);\
+        srcP2 = vec_perm(srcR2, srcR3, pp2);\
+        srcP3 = vec_perm(srcR2, srcR3, pp3);\
+    } break;\
+    }\
+ }
+#else
+#define load_alignment(s, ali, pm2, pm1, pp0, pp1, pp2, pp3){\
+    srcM2 =  vec_vsx_ld(-2, s);\
+    srcM1 = vec_vsx_ld(-1, s);\
+    srcP0 = vec_vsx_ld(0, s);\
+    srcP1 = vec_vsx_ld(1, s);\
+    srcP2 = vec_vsx_ld(2, s);\
+    srcP3 = vec_vsx_ld(3, s);\
+ }
+#endif /* HAVE_BIGENDIAN */
+
 /* this code assume stride % 16 == 0 */
 #ifdef PREFIX_h264_qpel16_h_lowpass_altivec
 static void PREFIX_h264_qpel16_h_lowpass_altivec(uint8_t *dst,
@@ -35,12 +112,7 @@
     register int i;
 
     LOAD_ZERO;
-    const vec_u8 permM2 = vec_lvsl(-2, src);
-    const vec_u8 permM1 = vec_lvsl(-1, src);
-    const vec_u8 permP0 = vec_lvsl(+0, src);
-    const vec_u8 permP1 = vec_lvsl(+1, src);
-    const vec_u8 permP2 = vec_lvsl(+2, src);
-    const vec_u8 permP3 = vec_lvsl(+3, src);
+    vec_u8 permM2, permM1, permP0, permP1, permP2, permP3;
     const vec_s16 v5ss = vec_splat_s16(5);
     const vec_u16 v5us = vec_splat_u16(5);
     const vec_s16 v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
@@ -59,79 +131,32 @@
 
     vec_u8 sum, fsum;
 
+#if HAVE_BIGENDIAN
+    permM2 = vec_lvsl(-2, src);
+    permM1 = vec_lvsl(-1, src);
+    permP0 = vec_lvsl(+0, src);
+    permP1 = vec_lvsl(+1, src);
+    permP2 = vec_lvsl(+2, src);
+    permP3 = vec_lvsl(+3, src);
+#endif /* HAVE_BIGENDIAN */
+
     for (i = 0 ; i < 16 ; i ++) {
-        vec_u8 srcR1 = vec_ld(-2, src);
-        vec_u8 srcR2 = vec_ld(14, src);
+        load_alignment(src, align, permM2, permM1, permP0, permP1, permP2, permP3);
 
-        switch (align) {
-        default: {
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = vec_perm(srcR1, srcR2, permP1);
-            srcP2 = vec_perm(srcR1, srcR2, permP2);
-            srcP3 = vec_perm(srcR1, srcR2, permP3);
-        } break;
-        case 11: {
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = vec_perm(srcR1, srcR2, permP1);
-            srcP2 = vec_perm(srcR1, srcR2, permP2);
-            srcP3 = srcR2;
-        } break;
-        case 12: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = vec_perm(srcR1, srcR2, permP1);
-            srcP2 = srcR2;
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        case 13: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = srcR2;
-            srcP2 = vec_perm(srcR2, srcR3, permP2);
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        case 14: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = srcR2;
-            srcP1 = vec_perm(srcR2, srcR3, permP1);
-            srcP2 = vec_perm(srcR2, srcR3, permP2);
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        case 15: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = srcR2;
-            srcP0 = vec_perm(srcR2, srcR3, permP0);
-            srcP1 = vec_perm(srcR2, srcR3, permP1);
-            srcP2 = vec_perm(srcR2, srcR3, permP2);
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        }
+        srcP0A = (vec_s16) VEC_MERGEH(zero_u8v, srcP0);
+        srcP0B = (vec_s16) VEC_MERGEL(zero_u8v, srcP0);
+        srcP1A = (vec_s16) VEC_MERGEH(zero_u8v, srcP1);
+        srcP1B = (vec_s16) VEC_MERGEL(zero_u8v, srcP1);
 
-        srcP0A = (vec_s16) vec_mergeh(zero_u8v, srcP0);
-        srcP0B = (vec_s16) vec_mergel(zero_u8v, srcP0);
-        srcP1A = (vec_s16) vec_mergeh(zero_u8v, srcP1);
-        srcP1B = (vec_s16) vec_mergel(zero_u8v, srcP1);
+        srcP2A = (vec_s16) VEC_MERGEH(zero_u8v, srcP2);
+        srcP2B = (vec_s16) VEC_MERGEL(zero_u8v, srcP2);
+        srcP3A = (vec_s16) VEC_MERGEH(zero_u8v, srcP3);
+        srcP3B = (vec_s16) VEC_MERGEL(zero_u8v, srcP3);
 
-        srcP2A = (vec_s16) vec_mergeh(zero_u8v, srcP2);
-        srcP2B = (vec_s16) vec_mergel(zero_u8v, srcP2);
-        srcP3A = (vec_s16) vec_mergeh(zero_u8v, srcP3);
-        srcP3B = (vec_s16) vec_mergel(zero_u8v, srcP3);
-
-        srcM1A = (vec_s16) vec_mergeh(zero_u8v, srcM1);
-        srcM1B = (vec_s16) vec_mergel(zero_u8v, srcM1);
-        srcM2A = (vec_s16) vec_mergeh(zero_u8v, srcM2);
-        srcM2B = (vec_s16) vec_mergel(zero_u8v, srcM2);
+        srcM1A = (vec_s16) VEC_MERGEH(zero_u8v, srcM1);
+        srcM1B = (vec_s16) VEC_MERGEL(zero_u8v, srcM1);
+        srcM2A = (vec_s16) VEC_MERGEH(zero_u8v, srcM2);
+        srcM2B = (vec_s16) VEC_MERGEL(zero_u8v, srcM2);
 
         sum1A = vec_adds(srcP0A, srcP1A);
         sum1B = vec_adds(srcP0B, srcP1B);
@@ -178,7 +203,10 @@
     register int i;
 
     LOAD_ZERO;
-    const vec_u8 perm = vec_lvsl(0, src);
+    vec_u8 perm;
+#if HAVE_BIGENDIAN
+    perm = vec_lvsl(0, src);
+#endif
     const vec_s16 v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
     const vec_u16 v5us = vec_splat_u16(5);
     const vec_s16 v5ss = vec_splat_s16(5);
@@ -186,52 +214,41 @@
 
     const uint8_t *srcbis = src - (srcStride * 2);
 
-    const vec_u8 srcM2a = vec_ld(0, srcbis);
-    const vec_u8 srcM2b = vec_ld(16, srcbis);
-    const vec_u8 srcM2 = vec_perm(srcM2a, srcM2b, perm);
-    //srcbis += srcStride;
-    const vec_u8 srcM1a = vec_ld(0, srcbis += srcStride);
-    const vec_u8 srcM1b = vec_ld(16, srcbis);
-    const vec_u8 srcM1 = vec_perm(srcM1a, srcM1b, perm);
-    //srcbis += srcStride;
-    const vec_u8 srcP0a = vec_ld(0, srcbis += srcStride);
-    const vec_u8 srcP0b = vec_ld(16, srcbis);
-    const vec_u8 srcP0 = vec_perm(srcP0a, srcP0b, perm);
-    //srcbis += srcStride;
-    const vec_u8 srcP1a = vec_ld(0, srcbis += srcStride);
-    const vec_u8 srcP1b = vec_ld(16, srcbis);
-    const vec_u8 srcP1 = vec_perm(srcP1a, srcP1b, perm);
-    //srcbis += srcStride;
-    const vec_u8 srcP2a = vec_ld(0, srcbis += srcStride);
-    const vec_u8 srcP2b = vec_ld(16, srcbis);
-    const vec_u8 srcP2 = vec_perm(srcP2a, srcP2b, perm);
-    //srcbis += srcStride;
+    const vec_u8 srcM2 = load_with_perm_vec(0, srcbis, perm);
+    srcbis += srcStride;
+    const vec_u8 srcM1 = load_with_perm_vec(0, srcbis, perm);
+    srcbis += srcStride;
+    const vec_u8 srcP0 = load_with_perm_vec(0, srcbis, perm);
+    srcbis += srcStride;
+    const vec_u8 srcP1 = load_with_perm_vec(0, srcbis, perm);
+    srcbis += srcStride;
+    const vec_u8 srcP2 = load_with_perm_vec(0, srcbis, perm);
+    srcbis += srcStride;
 
-    vec_s16 srcM2ssA = (vec_s16) vec_mergeh(zero_u8v, srcM2);
-    vec_s16 srcM2ssB = (vec_s16) vec_mergel(zero_u8v, srcM2);
-    vec_s16 srcM1ssA = (vec_s16) vec_mergeh(zero_u8v, srcM1);
-    vec_s16 srcM1ssB = (vec_s16) vec_mergel(zero_u8v, srcM1);
-    vec_s16 srcP0ssA = (vec_s16) vec_mergeh(zero_u8v, srcP0);
-    vec_s16 srcP0ssB = (vec_s16) vec_mergel(zero_u8v, srcP0);
-    vec_s16 srcP1ssA = (vec_s16) vec_mergeh(zero_u8v, srcP1);
-    vec_s16 srcP1ssB = (vec_s16) vec_mergel(zero_u8v, srcP1);
-    vec_s16 srcP2ssA = (vec_s16) vec_mergeh(zero_u8v, srcP2);
-    vec_s16 srcP2ssB = (vec_s16) vec_mergel(zero_u8v, srcP2);
+    vec_s16 srcM2ssA = (vec_s16) VEC_MERGEH(zero_u8v, srcM2);
+    vec_s16 srcM2ssB = (vec_s16) VEC_MERGEL(zero_u8v, srcM2);
+    vec_s16 srcM1ssA = (vec_s16) VEC_MERGEH(zero_u8v, srcM1);
+    vec_s16 srcM1ssB = (vec_s16) VEC_MERGEL(zero_u8v, srcM1);
+    vec_s16 srcP0ssA = (vec_s16) VEC_MERGEH(zero_u8v, srcP0);
+    vec_s16 srcP0ssB = (vec_s16) VEC_MERGEL(zero_u8v, srcP0);
+    vec_s16 srcP1ssA = (vec_s16) VEC_MERGEH(zero_u8v, srcP1);
+    vec_s16 srcP1ssB = (vec_s16) VEC_MERGEL(zero_u8v, srcP1);
+    vec_s16 srcP2ssA = (vec_s16) VEC_MERGEH(zero_u8v, srcP2);
+    vec_s16 srcP2ssB = (vec_s16) VEC_MERGEL(zero_u8v, srcP2);
 
     vec_s16 pp1A, pp1B, pp2A, pp2B, pp3A, pp3B,
               psumA, psumB, sumA, sumB,
               srcP3ssA, srcP3ssB,
               sum1A, sum1B, sum2A, sum2B, sum3A, sum3B;
 
-    vec_u8 sum, fsum, srcP3a, srcP3b, srcP3;
+    vec_u8 sum, fsum, srcP3;
 
     for (i = 0 ; i < 16 ; i++) {
-        srcP3a = vec_ld(0, srcbis += srcStride);
-        srcP3b = vec_ld(16, srcbis);
-        srcP3 = vec_perm(srcP3a, srcP3b, perm);
-        srcP3ssA = (vec_s16) vec_mergeh(zero_u8v, srcP3);
-        srcP3ssB = (vec_s16) vec_mergel(zero_u8v, srcP3);
-        //srcbis += srcStride;
+        srcP3 = load_with_perm_vec(0, srcbis, perm);
+        srcbis += srcStride;
+
+        srcP3ssA = (vec_s16) VEC_MERGEH(zero_u8v, srcP3);
+        srcP3ssB = (vec_s16) VEC_MERGEL(zero_u8v, srcP3);
 
         sum1A = vec_adds(srcP0ssA, srcP1ssA);
         sum1B = vec_adds(srcP0ssB, srcP1ssB);
@@ -288,12 +305,7 @@
 {
     register int i;
     LOAD_ZERO;
-    const vec_u8 permM2 = vec_lvsl(-2, src);
-    const vec_u8 permM1 = vec_lvsl(-1, src);
-    const vec_u8 permP0 = vec_lvsl(+0, src);
-    const vec_u8 permP1 = vec_lvsl(+1, src);
-    const vec_u8 permP2 = vec_lvsl(+2, src);
-    const vec_u8 permP3 = vec_lvsl(+3, src);
+    vec_u8 permM2, permM1, permP0, permP1, permP2, permP3;
     const vec_s16 v20ss = vec_sl(vec_splat_s16(5),vec_splat_u16(2));
     const vec_u32 v10ui = vec_splat_u32(10);
     const vec_s16 v5ss = vec_splat_s16(5);
@@ -325,81 +337,35 @@
     vec_u8 fsum, sumv, sum;
     vec_s16 ssume, ssumo;
 
+#if HAVE_BIGENDIAN
+    permM2 = vec_lvsl(-2, src);
+    permM1 = vec_lvsl(-1, src);
+    permP0 = vec_lvsl(+0, src);
+    permP1 = vec_lvsl(+1, src);
+    permP2 = vec_lvsl(+2, src);
+    permP3 = vec_lvsl(+3, src);
+#endif /* HAVE_BIGENDIAN */
+
     src -= (2 * srcStride);
     for (i = 0 ; i < 21 ; i ++) {
         vec_u8 srcM2, srcM1, srcP0, srcP1, srcP2, srcP3;
-        vec_u8 srcR1 = vec_ld(-2, src);
-        vec_u8 srcR2 = vec_ld(14, src);
 
-        switch (align) {
-        default: {
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = vec_perm(srcR1, srcR2, permP1);
-            srcP2 = vec_perm(srcR1, srcR2, permP2);
-            srcP3 = vec_perm(srcR1, srcR2, permP3);
-        } break;
-        case 11: {
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = vec_perm(srcR1, srcR2, permP1);
-            srcP2 = vec_perm(srcR1, srcR2, permP2);
-            srcP3 = srcR2;
-        } break;
-        case 12: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = vec_perm(srcR1, srcR2, permP1);
-            srcP2 = srcR2;
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        case 13: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = vec_perm(srcR1, srcR2, permP0);
-            srcP1 = srcR2;
-            srcP2 = vec_perm(srcR2, srcR3, permP2);
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        case 14: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = vec_perm(srcR1, srcR2, permM1);
-            srcP0 = srcR2;
-            srcP1 = vec_perm(srcR2, srcR3, permP1);
-            srcP2 = vec_perm(srcR2, srcR3, permP2);
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        case 15: {
-            vec_u8 srcR3 = vec_ld(30, src);
-            srcM2 = vec_perm(srcR1, srcR2, permM2);
-            srcM1 = srcR2;
-            srcP0 = vec_perm(srcR2, srcR3, permP0);
-            srcP1 = vec_perm(srcR2, srcR3, permP1);
-            srcP2 = vec_perm(srcR2, srcR3, permP2);
-            srcP3 = vec_perm(srcR2, srcR3, permP3);
-        } break;
-        }
+        load_alignment(src, align, permM2, permM1, permP0, permP1, permP2, permP3);
 
-        srcP0A = (vec_s16) vec_mergeh(zero_u8v, srcP0);
-        srcP0B = (vec_s16) vec_mergel(zero_u8v, srcP0);
-        srcP1A = (vec_s16) vec_mergeh(zero_u8v, srcP1);
-        srcP1B = (vec_s16) vec_mergel(zero_u8v, srcP1);
+        srcP0A = (vec_s16) VEC_MERGEH(zero_u8v, srcP0);
+        srcP0B = (vec_s16) VEC_MERGEL(zero_u8v, srcP0);
+        srcP1A = (vec_s16) VEC_MERGEH(zero_u8v, srcP1);
+        srcP1B = (vec_s16) VEC_MERGEL(zero_u8v, srcP1);
 
-        srcP2A = (vec_s16) vec_mergeh(zero_u8v, srcP2);
-        srcP2B = (vec_s16) vec_mergel(zero_u8v, srcP2);
-        srcP3A = (vec_s16) vec_mergeh(zero_u8v, srcP3);
-        srcP3B = (vec_s16) vec_mergel(zero_u8v, srcP3);
+        srcP2A = (vec_s16) VEC_MERGEH(zero_u8v, srcP2);
+        srcP2B = (vec_s16) VEC_MERGEL(zero_u8v, srcP2);
+        srcP3A = (vec_s16) VEC_MERGEH(zero_u8v, srcP3);
+        srcP3B = (vec_s16) VEC_MERGEL(zero_u8v, srcP3);
 
-        srcM1A = (vec_s16) vec_mergeh(zero_u8v, srcM1);
-        srcM1B = (vec_s16) vec_mergel(zero_u8v, srcM1);
-        srcM2A = (vec_s16) vec_mergeh(zero_u8v, srcM2);
-        srcM2B = (vec_s16) vec_mergel(zero_u8v, srcM2);
+        srcM1A = (vec_s16) VEC_MERGEH(zero_u8v, srcM1);
+        srcM1B = (vec_s16) VEC_MERGEL(zero_u8v, srcM1);
+        srcM2A = (vec_s16) VEC_MERGEH(zero_u8v, srcM2);
+        srcM2B = (vec_s16) VEC_MERGEL(zero_u8v, srcM2);
 
         sum1A = vec_adds(srcP0A, srcP1A);
         sum1B = vec_adds(srcP0B, srcP1B);
@@ -448,8 +414,8 @@
         const vec_s16 sum1B = vec_adds(tmpP0ssB, tmpP1ssB);
         const vec_s16 sum2A = vec_adds(tmpM1ssA, tmpP2ssA);
         const vec_s16 sum2B = vec_adds(tmpM1ssB, tmpP2ssB);
-        const vec_s16 sum3A = vec_adds(tmpM2ssA, tmpP3ssA);
-        const vec_s16 sum3B = vec_adds(tmpM2ssB, tmpP3ssB);
+        vec_s16 sum3A = vec_adds(tmpM2ssA, tmpP3ssA);
+        vec_s16 sum3B = vec_adds(tmpM2ssB, tmpP3ssB);
 
         tmpbis += tmpStride;
 
@@ -474,10 +440,14 @@
         pp2Be = vec_mule(sum2B, v5ss);
         pp2Bo = vec_mulo(sum2B, v5ss);
 
-        pp3Ae = vec_sra((vec_s32)sum3A, v16ui);
         pp3Ao = vec_mulo(sum3A, v1ss);
-        pp3Be = vec_sra((vec_s32)sum3B, v16ui);
         pp3Bo = vec_mulo(sum3B, v1ss);
+#if !HAVE_BIGENDIAN
+        sum3A = (vec_s16)vec_perm(sum3A, sum3A,vcswapi2s(0,1,2,3));
+        sum3B = (vec_s16)vec_perm(sum3B, sum3B,vcswapi2s(0,1,2,3));
+#endif
+        pp3Ae = vec_sra((vec_s32)sum3A, v16ui);
+        pp3Be = vec_sra((vec_s32)sum3B, v16ui);
 
         pp1cAe = vec_add(pp1Ae, v512si);
         pp1cAo = vec_add(pp1Ao, v512si);
diff --git a/libavcodec/ppc/hpeldsp_altivec.c b/libavcodec/ppc/hpeldsp_altivec.c
index 79c2af8..87a1f05 100644
--- a/libavcodec/ppc/hpeldsp_altivec.c
+++ b/libavcodec/ppc/hpeldsp_altivec.c
@@ -36,46 +36,13 @@
 
 #if HAVE_ALTIVEC
 /* next one assumes that ((line_size % 16) == 0) */
-#if HAVE_VSX
 void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
 {
-  register vector unsigned char pixelsv1;
-  register vector unsigned char pixelsv1B;
-  register vector unsigned char pixelsv1C;
-  register vector unsigned char pixelsv1D;
+    register vector unsigned char pixelsv1;
+    register vector unsigned char pixelsv1B;
+    register vector unsigned char pixelsv1C;
+    register vector unsigned char pixelsv1D;
 
-  int i;
-  register ptrdiff_t line_size_2 = line_size << 1;
-  register ptrdiff_t line_size_3 = line_size + line_size_2;
-  register ptrdiff_t line_size_4 = line_size << 2;
-
-// hand-unrolling the loop by 4 gains about 15%
-// mininum execution time goes from 74 to 60 cycles
-// it's faster than -funroll-loops, but using
-// -funroll-loops w/ this is bad - 74 cycles again.
-// all this is on a 7450, tuning for the 7450
-  for (i = 0; i < h; i += 4) {
-    pixelsv1  = vec_vsx_ld( 0, pixels);
-    pixelsv1B = vec_vsx_ld(line_size, pixels);
-    pixelsv1C = vec_vsx_ld(line_size_2, pixels);
-    pixelsv1D = vec_vsx_ld(line_size_3, pixels);
-    vec_vsx_st(pixelsv1, 0, (unsigned char*)block);
-    vec_vsx_st(pixelsv1B, line_size, (unsigned char*)block);
-    vec_vsx_st(pixelsv1C, line_size_2, (unsigned char*)block);
-    vec_st(pixelsv1D, line_size_3, (unsigned char*)block);
-    pixels+=line_size_4;
-    block +=line_size_4;
-  }
-}
-#else
-void ff_put_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
-{
-    register vector unsigned char pixelsv1, pixelsv2;
-    register vector unsigned char pixelsv1B, pixelsv2B;
-    register vector unsigned char pixelsv1C, pixelsv2C;
-    register vector unsigned char pixelsv1D, pixelsv2D;
-
-    register vector unsigned char perm = vec_lvsl(0, pixels);
     int i;
     register ptrdiff_t line_size_2 = line_size << 1;
     register ptrdiff_t line_size_3 = line_size + line_size_2;
@@ -87,42 +54,29 @@
 // -funroll-loops w/ this is bad - 74 cycles again.
 // all this is on a 7450, tuning for the 7450
     for (i = 0; i < h; i += 4) {
-        pixelsv1  = vec_ld( 0, pixels);
-        pixelsv2  = vec_ld(15, pixels);
-        pixelsv1B = vec_ld(line_size, pixels);
-        pixelsv2B = vec_ld(15 + line_size, pixels);
-        pixelsv1C = vec_ld(line_size_2, pixels);
-        pixelsv2C = vec_ld(15 + line_size_2, pixels);
-        pixelsv1D = vec_ld(line_size_3, pixels);
-        pixelsv2D = vec_ld(15 + line_size_3, pixels);
-        vec_st(vec_perm(pixelsv1, pixelsv2, perm),
-               0, (unsigned char*)block);
-        vec_st(vec_perm(pixelsv1B, pixelsv2B, perm),
-               line_size, (unsigned char*)block);
-        vec_st(vec_perm(pixelsv1C, pixelsv2C, perm),
-               line_size_2, (unsigned char*)block);
-        vec_st(vec_perm(pixelsv1D, pixelsv2D, perm),
-               line_size_3, (unsigned char*)block);
+        pixelsv1  = unaligned_load( 0, pixels);
+        pixelsv1B = unaligned_load(line_size, pixels);
+        pixelsv1C = unaligned_load(line_size_2, pixels);
+        pixelsv1D = unaligned_load(line_size_3, pixels);
+        VEC_ST(pixelsv1, 0, (unsigned char*)block);
+        VEC_ST(pixelsv1B, line_size, (unsigned char*)block);
+        VEC_ST(pixelsv1C, line_size_2, (unsigned char*)block);
+        VEC_ST(pixelsv1D, line_size_3, (unsigned char*)block);
         pixels+=line_size_4;
         block +=line_size_4;
     }
 }
 
-#endif /* HAVE_VSX */
-
 /* next one assumes that ((line_size % 16) == 0) */
 #define op_avg(a,b)  a = ( ((a)|(b)) - ((((a)^(b))&0xFEFEFEFEUL)>>1) )
 void ff_avg_pixels16_altivec(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h)
 {
-    register vector unsigned char pixelsv1, pixelsv2, pixelsv, blockv;
-    register vector unsigned char perm = vec_lvsl(0, pixels);
-    int i;
+    register vector unsigned char pixelsv, blockv;
 
+    int i;
     for (i = 0; i < h; i++) {
-        pixelsv1 = vec_ld( 0, pixels);
-        pixelsv2 = vec_ld(16,pixels);
         blockv = vec_ld(0, block);
-        pixelsv = vec_perm(pixelsv1, pixelsv2, perm);
+        pixelsv = VEC_LD( 0, pixels);
         blockv = vec_avg(blockv,pixelsv);
         vec_st(blockv, 0, (unsigned char*)block);
         pixels+=line_size;
@@ -142,9 +96,7 @@
        int rightside = ((unsigned long)block & 0x0000000F);
 
        blockv = vec_ld(0, block);
-       pixelsv1 = vec_ld( 0, pixels);
-       pixelsv2 = vec_ld(16, pixels);
-       pixelsv = vec_perm(pixelsv1, pixelsv2, vec_lvsl(0, pixels));
+       pixelsv = VEC_LD( 0, pixels);
 
        if (rightside) {
            pixelsv = vec_perm(blockv, pixelsv, vcprm(0,1,s0,s1));
@@ -166,21 +118,16 @@
 {
     register int i;
     register vector unsigned char pixelsv1, pixelsv2, pixelsavg;
-    register vector unsigned char blockv, temp1, temp2;
+    register vector unsigned char blockv;
     register vector unsigned short pixelssum1, pixelssum2, temp3;
     register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
     register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
 
-    temp1 = vec_ld(0, pixels);
-    temp2 = vec_ld(16, pixels);
-    pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
-    if ((((unsigned long)pixels) & 0x0000000F) ==  0x0000000F) {
-        pixelsv2 = temp2;
-    } else {
-        pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
-    }
-    pixelsv1 = vec_mergeh(vczero, pixelsv1);
-    pixelsv2 = vec_mergeh(vczero, pixelsv2);
+    pixelsv1 = VEC_LD(0, pixels);
+    pixelsv2 = VEC_LD(1, pixels);
+    pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+    pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
+
     pixelssum1 = vec_add((vector unsigned short)pixelsv1,
                          (vector unsigned short)pixelsv2);
     pixelssum1 = vec_add(pixelssum1, vctwo);
@@ -189,17 +136,10 @@
         int rightside = ((unsigned long)block & 0x0000000F);
         blockv = vec_ld(0, block);
 
-        temp1 = vec_ld(line_size, pixels);
-        temp2 = vec_ld(line_size + 16, pixels);
-        pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
-        if (((((unsigned long)pixels) + line_size) & 0x0000000F) ==  0x0000000F) {
-            pixelsv2 = temp2;
-        } else {
-            pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
-        }
-
-        pixelsv1 = vec_mergeh(vczero, pixelsv1);
-        pixelsv2 = vec_mergeh(vczero, pixelsv2);
+        pixelsv1 = unaligned_load(line_size, pixels);
+        pixelsv2 = unaligned_load(line_size+1, pixels);
+        pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+        pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
         pixelssum2 = vec_add((vector unsigned short)pixelsv1,
                              (vector unsigned short)pixelsv2);
         temp3 = vec_add(pixelssum1, pixelssum2);
@@ -225,22 +165,16 @@
 {
     register int i;
     register vector unsigned char pixelsv1, pixelsv2, pixelsavg;
-    register vector unsigned char blockv, temp1, temp2;
+    register vector unsigned char blockv;
     register vector unsigned short pixelssum1, pixelssum2, temp3;
     register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
     register const vector unsigned short vcone = (const vector unsigned short)vec_splat_u16(1);
     register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
 
-    temp1 = vec_ld(0, pixels);
-    temp2 = vec_ld(16, pixels);
-    pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
-    if ((((unsigned long)pixels) & 0x0000000F) ==  0x0000000F) {
-        pixelsv2 = temp2;
-    } else {
-        pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
-    }
-    pixelsv1 = vec_mergeh(vczero, pixelsv1);
-    pixelsv2 = vec_mergeh(vczero, pixelsv2);
+    pixelsv1 = VEC_LD(0, pixels);
+    pixelsv2 = VEC_LD(1, pixels);
+    pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+    pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
     pixelssum1 = vec_add((vector unsigned short)pixelsv1,
                          (vector unsigned short)pixelsv2);
     pixelssum1 = vec_add(pixelssum1, vcone);
@@ -249,17 +183,10 @@
         int rightside = ((unsigned long)block & 0x0000000F);
         blockv = vec_ld(0, block);
 
-        temp1 = vec_ld(line_size, pixels);
-        temp2 = vec_ld(line_size + 16, pixels);
-        pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
-        if (((((unsigned long)pixels) + line_size) & 0x0000000F) ==  0x0000000F) {
-            pixelsv2 = temp2;
-        } else {
-            pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
-        }
-
-        pixelsv1 = vec_mergeh(vczero, pixelsv1);
-        pixelsv2 = vec_mergeh(vczero, pixelsv2);
+        pixelsv1 = unaligned_load(line_size, pixels);
+        pixelsv2 = unaligned_load(line_size+1, pixels);
+        pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+        pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
         pixelssum2 = vec_add((vector unsigned short)pixelsv1,
                              (vector unsigned short)pixelsv2);
         temp3 = vec_add(pixelssum1, pixelssum2);
@@ -285,24 +212,18 @@
 {
     register int i;
     register vector unsigned char pixelsv1, pixelsv2, pixelsv3, pixelsv4;
-    register vector unsigned char blockv, temp1, temp2;
+    register vector unsigned char blockv;
     register vector unsigned short temp3, temp4,
         pixelssum1, pixelssum2, pixelssum3, pixelssum4;
     register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
     register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
 
-    temp1 = vec_ld(0, pixels);
-    temp2 = vec_ld(16, pixels);
-    pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
-    if ((((unsigned long)pixels) & 0x0000000F) ==  0x0000000F) {
-        pixelsv2 = temp2;
-    } else {
-        pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
-    }
-    pixelsv3 = vec_mergel(vczero, pixelsv1);
-    pixelsv4 = vec_mergel(vczero, pixelsv2);
-    pixelsv1 = vec_mergeh(vczero, pixelsv1);
-    pixelsv2 = vec_mergeh(vczero, pixelsv2);
+    pixelsv1 = VEC_LD(0, pixels);
+    pixelsv2 = VEC_LD(1, pixels);
+    pixelsv3 = VEC_MERGEL(vczero, pixelsv1);
+    pixelsv4 = VEC_MERGEL(vczero, pixelsv2);
+    pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+    pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
     pixelssum3 = vec_add((vector unsigned short)pixelsv3,
                          (vector unsigned short)pixelsv4);
     pixelssum3 = vec_add(pixelssum3, vctwo);
@@ -313,20 +234,13 @@
     for (i = 0; i < h ; i++) {
         blockv = vec_ld(0, block);
 
-        temp1 = vec_ld(line_size, pixels);
-        temp2 = vec_ld(line_size + 16, pixels);
-        pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
-        if (((((unsigned long)pixels) + line_size) & 0x0000000F) ==  0x0000000F) {
-            pixelsv2 = temp2;
-        } else {
-            pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
-        }
+        pixelsv1 = unaligned_load(line_size, pixels);
+        pixelsv2 = unaligned_load(line_size+1, pixels);
 
-        pixelsv3 = vec_mergel(vczero, pixelsv1);
-        pixelsv4 = vec_mergel(vczero, pixelsv2);
-        pixelsv1 = vec_mergeh(vczero, pixelsv1);
-        pixelsv2 = vec_mergeh(vczero, pixelsv2);
-
+        pixelsv3 = VEC_MERGEL(vczero, pixelsv1);
+        pixelsv4 = VEC_MERGEL(vczero, pixelsv2);
+        pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+        pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
         pixelssum4 = vec_add((vector unsigned short)pixelsv3,
                              (vector unsigned short)pixelsv4);
         pixelssum2 = vec_add((vector unsigned short)pixelsv1,
@@ -353,25 +267,19 @@
 {
     register int i;
     register vector unsigned char pixelsv1, pixelsv2, pixelsv3, pixelsv4;
-    register vector unsigned char blockv, temp1, temp2;
+    register vector unsigned char blockv;
     register vector unsigned short temp3, temp4,
         pixelssum1, pixelssum2, pixelssum3, pixelssum4;
     register const vector unsigned char vczero = (const vector unsigned char)vec_splat_u8(0);
     register const vector unsigned short vcone = (const vector unsigned short)vec_splat_u16(1);
     register const vector unsigned short vctwo = (const vector unsigned short)vec_splat_u16(2);
 
-    temp1 = vec_ld(0, pixels);
-    temp2 = vec_ld(16, pixels);
-    pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
-    if ((((unsigned long)pixels) & 0x0000000F) ==  0x0000000F) {
-        pixelsv2 = temp2;
-    } else {
-        pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
-    }
-    pixelsv3 = vec_mergel(vczero, pixelsv1);
-    pixelsv4 = vec_mergel(vczero, pixelsv2);
-    pixelsv1 = vec_mergeh(vczero, pixelsv1);
-    pixelsv2 = vec_mergeh(vczero, pixelsv2);
+    pixelsv1 = VEC_LD(0, pixels);
+    pixelsv2 = VEC_LD(1, pixels);
+    pixelsv3 = VEC_MERGEL(vczero, pixelsv1);
+    pixelsv4 = VEC_MERGEL(vczero, pixelsv2);
+    pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+    pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
     pixelssum3 = vec_add((vector unsigned short)pixelsv3,
                          (vector unsigned short)pixelsv4);
     pixelssum3 = vec_add(pixelssum3, vcone);
@@ -380,22 +288,13 @@
     pixelssum1 = vec_add(pixelssum1, vcone);
 
     for (i = 0; i < h ; i++) {
-        blockv = vec_ld(0, block);
+        pixelsv1 = unaligned_load(line_size, pixels);
+        pixelsv2 = unaligned_load(line_size+1, pixels);
 
-        temp1 = vec_ld(line_size, pixels);
-        temp2 = vec_ld(line_size + 16, pixels);
-        pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
-        if (((((unsigned long)pixels) + line_size) & 0x0000000F) ==  0x0000000F) {
-            pixelsv2 = temp2;
-        } else {
-            pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
-        }
-
-        pixelsv3 = vec_mergel(vczero, pixelsv1);
-        pixelsv4 = vec_mergel(vczero, pixelsv2);
-        pixelsv1 = vec_mergeh(vczero, pixelsv1);
-        pixelsv2 = vec_mergeh(vczero, pixelsv2);
-
+        pixelsv3 = VEC_MERGEL(vczero, pixelsv1);
+        pixelsv4 = VEC_MERGEL(vczero, pixelsv2);
+        pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+        pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
         pixelssum4 = vec_add((vector unsigned short)pixelsv3,
                              (vector unsigned short)pixelsv4);
         pixelssum2 = vec_add((vector unsigned short)pixelsv1,
@@ -410,7 +309,7 @@
 
         blockv = vec_packsu(temp3, temp4);
 
-        vec_st(blockv, 0, block);
+        VEC_ST(blockv, 0, block);
 
         block += line_size;
         pixels += line_size;
@@ -422,7 +321,7 @@
 {
     register int i;
     register vector unsigned char pixelsv1, pixelsv2, pixelsavg;
-    register vector unsigned char blockv, temp1, temp2, blocktemp;
+    register vector unsigned char blockv, blocktemp;
     register vector unsigned short pixelssum1, pixelssum2, temp3;
 
     register const vector unsigned char vczero = (const vector unsigned char)
@@ -430,16 +329,10 @@
     register const vector unsigned short vctwo = (const vector unsigned short)
                                         vec_splat_u16(2);
 
-    temp1 = vec_ld(0, pixels);
-    temp2 = vec_ld(16, pixels);
-    pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(0, pixels));
-    if ((((unsigned long)pixels) & 0x0000000F) ==  0x0000000F) {
-        pixelsv2 = temp2;
-    } else {
-        pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(1, pixels));
-    }
-    pixelsv1 = vec_mergeh(vczero, pixelsv1);
-    pixelsv2 = vec_mergeh(vczero, pixelsv2);
+    pixelsv1 = VEC_LD(0, pixels);
+    pixelsv2 = VEC_LD(1, pixels);
+    pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+    pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
     pixelssum1 = vec_add((vector unsigned short)pixelsv1,
                          (vector unsigned short)pixelsv2);
     pixelssum1 = vec_add(pixelssum1, vctwo);
@@ -448,17 +341,11 @@
         int rightside = ((unsigned long)block & 0x0000000F);
         blockv = vec_ld(0, block);
 
-        temp1 = vec_ld(line_size, pixels);
-        temp2 = vec_ld(line_size + 16, pixels);
-        pixelsv1 = vec_perm(temp1, temp2, vec_lvsl(line_size, pixels));
-        if (((((unsigned long)pixels) + line_size) & 0x0000000F) ==  0x0000000F) {
-            pixelsv2 = temp2;
-        } else {
-            pixelsv2 = vec_perm(temp1, temp2, vec_lvsl(line_size + 1, pixels));
-        }
+        pixelsv1 = unaligned_load(line_size, pixels);
+        pixelsv2 = unaligned_load(line_size+1, pixels);
 
-        pixelsv1 = vec_mergeh(vczero, pixelsv1);
-        pixelsv2 = vec_mergeh(vczero, pixelsv2);
+        pixelsv1 = VEC_MERGEH(vczero, pixelsv1);
+        pixelsv2 = VEC_MERGEH(vczero, pixelsv2);
         pixelssum2 = vec_add((vector unsigned short)pixelsv1,
                              (vector unsigned short)pixelsv2);
         temp3 = vec_add(pixelssum1, pixelssum2);
diff --git a/libavcodec/ppc/me_cmp.c b/libavcodec/ppc/me_cmp.c
index 8ff8193..38a7ba1 100644
--- a/libavcodec/ppc/me_cmp.c
+++ b/libavcodec/ppc/me_cmp.c
@@ -35,64 +35,43 @@
 #include "libavcodec/me_cmp.h"
 
 #if HAVE_ALTIVEC
-#if HAVE_VSX
-static int sad16_x2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                                                        int line_size, int h)
-{
-    int i, s = 0;
-    const vector unsigned char zero =
-        (const vector unsigned char) vec_splat_u8(0);
-    vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
-    vector signed int sumdiffs;
 
-    for (i = 0; i < h; i++) {
-        /* Read unaligned pixels into our vectors. The vectors are as follows:
-         * pix1v: pix1[0] - pix1[15]
-         * pix2v: pix2[0] - pix2[15]      pix2iv: pix2[1] - pix2[16] */
-        vector unsigned char pix1v  = vec_vsx_ld(0,  pix1);
-        vector unsigned char pix2v  = vec_vsx_ld(0,  pix2);
-        vector unsigned char pix2iv = vec_vsx_ld(1,  pix2);
-
-        /* Calculate the average vector. */
-        vector unsigned char avgv = vec_avg(pix2v, pix2iv);
-
-        /* Calculate a sum of abs differences vector. */
-        vector unsigned char t5 = vec_sub(vec_max(pix1v, avgv),
-                                          vec_min(pix1v, avgv));
-
-        /* Add each 4 pixel group together and put 4 results into sad. */
-        sad = vec_sum4s(t5, sad);
-
-        pix1 += line_size;
-        pix2 += line_size;
-    }
-    /* Sum up the four partial sums, and put the result into s. */
-    sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
-    sumdiffs = vec_splat(sumdiffs, 3);
-    vec_vsx_st(sumdiffs, 0, &s);
-    return s;
+#if HAVE_BIGENDIAN
+#define GET_PERM(per1, per2, pix) {\
+    per1 = vec_lvsl(0, pix);\
+    per2 = vec_add(per1, vec_splat_u8(1));\
+}
+#define LOAD_PIX(v, iv, pix, per1, per2) {\
+    vector unsigned char pix2l  = vec_ld(0,  pix);\
+    vector unsigned char pix2r  = vec_ld(16, pix);\
+    v  = vec_perm(pix2l, pix2r, per1);\
+    iv = vec_perm(pix2l, pix2r, per2);\
 }
 #else
+#define GET_PERM(per1, per2, pix) {}
+#define LOAD_PIX(v, iv, pix, per1, per2) {\
+    v  = vec_vsx_ld(0,  pix);\
+    iv = vec_vsx_ld(1,  pix);\
+}
+#endif
 static int sad16_x2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                            int line_size, int h)
+                            ptrdiff_t stride, int h)
 {
-    int i, s = 0;
+    int i;
+    int __attribute__((aligned(16))) s = 0;
     const vector unsigned char zero =
         (const vector unsigned char) vec_splat_u8(0);
-    vector unsigned char perm1 = vec_lvsl(0, pix2);
-    vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1));
     vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumdiffs;
+    vector unsigned char perm1, perm2, pix2v, pix2iv;
 
+    GET_PERM(perm1, perm2, pix2);
     for (i = 0; i < h; i++) {
         /* Read unaligned pixels into our vectors. The vectors are as follows:
          * pix1v: pix1[0] - pix1[15]
          * pix2v: pix2[0] - pix2[15]      pix2iv: pix2[1] - pix2[16] */
         vector unsigned char pix1v  = vec_ld(0,  pix1);
-        vector unsigned char pix2l  = vec_ld(0,  pix2);
-        vector unsigned char pix2r  = vec_ld(16, pix2);
-        vector unsigned char pix2v  = vec_perm(pix2l, pix2r, perm1);
-        vector unsigned char pix2iv = vec_perm(pix2l, pix2r, perm2);
+        LOAD_PIX(pix2v, pix2iv, pix2, perm1, perm2);
 
         /* Calculate the average vector. */
         vector unsigned char avgv = vec_avg(pix2v, pix2iv);
@@ -104,8 +83,8 @@
         /* Add each 4 pixel group together and put 4 results into sad. */
         sad = vec_sum4s(t5, sad);
 
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
     /* Sum up the four partial sums, and put the result into s. */
     sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
@@ -114,90 +93,35 @@
 
     return s;
 }
-#endif /* HAVE_VSX */
 
-#if HAVE_VSX
 static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                                                        int line_size, int h)
+                            ptrdiff_t stride, int h)
 {
-  int i, s = 0;
-  const vector unsigned char zero =
-    (const vector unsigned char) vec_splat_u8(0);
-  vector unsigned char perm = vec_lvsl(0, pix2);
-  vector unsigned char pix1v, pix3v, avgv, t5;
-  vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
-  vector signed int sumdiffs;
-  uint8_t *pix3 = pix2 + line_size;
-
-  /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one
-   * iteration becomes pix2 in the next iteration. We can use this
-   * fact to avoid a potentially expensive unaligned read, each
-   * time around the loop.
-   * Read unaligned pixels into our vectors. The vectors are as follows:
-   * pix2v: pix2[0] - pix2[15]
-   * Split the pixel vectors into shorts. */
-  vector unsigned char pix2v = vec_vsx_ld(0, pix2);
-
-  for (i = 0; i < h; i++) {
-    /* Read unaligned pixels into our vectors. The vectors are as follows:
-     * pix1v: pix1[0] - pix1[15]
-     * pix3v: pix3[0] - pix3[15] */
-    pix1v = vec_vsx_ld(0,  pix1);
-    pix3v = vec_vsx_ld(0,  pix3);
-
-    /* Calculate the average vector. */
-    avgv = vec_avg(pix2v, pix3v);
-
-    /* Calculate a sum of abs differences vector. */
-    t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
-
-    /* Add each 4 pixel group together and put 4 results into sad. */
-    sad = vec_sum4s(t5, sad);
-
-    pix1 += line_size;
-    pix2v = pix3v;
-    pix3 += line_size;
-  }
-
-  /* Sum up the four partial sums, and put the result into s. */
-  sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
-  sumdiffs = vec_splat(sumdiffs, 3);
-  vec_vsx_st(sumdiffs, 0, &s);
-  return s;
-}
-#else
-static int sad16_y2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                            int line_size, int h)
-{
-    int i, s = 0;
+    int i;
+    int  __attribute__((aligned(16))) s = 0;
     const vector unsigned char zero =
         (const vector unsigned char) vec_splat_u8(0);
-    vector unsigned char perm = vec_lvsl(0, pix2);
     vector unsigned char pix1v, pix3v, avgv, t5;
     vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumdiffs;
-    uint8_t *pix3 = pix2 + line_size;
 
-    /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one
+    uint8_t *pix3 = pix2 + stride;
+
+    /* Due to the fact that pix3 = pix2 + stride, the pix3 of one
      * iteration becomes pix2 in the next iteration. We can use this
      * fact to avoid a potentially expensive unaligned read, each
      * time around the loop.
      * Read unaligned pixels into our vectors. The vectors are as follows:
      * pix2v: pix2[0] - pix2[15]
      * Split the pixel vectors into shorts. */
-    vector unsigned char pix2l = vec_ld(0,  pix2);
-    vector unsigned char pix2r = vec_ld(15, pix2);
-    vector unsigned char pix2v = vec_perm(pix2l, pix2r, perm);
+    vector unsigned char pix2v = VEC_LD(0, pix2);
 
     for (i = 0; i < h; i++) {
         /* Read unaligned pixels into our vectors. The vectors are as follows:
          * pix1v: pix1[0] - pix1[15]
          * pix3v: pix3[0] - pix3[15] */
         pix1v = vec_ld(0,  pix1);
-
-        pix2l = vec_ld(0,  pix3);
-        pix2r = vec_ld(15, pix3);
-        pix3v = vec_perm(pix2l, pix2r, perm);
+        pix3v = VEC_LD(0,  pix3);
 
         /* Calculate the average vector. */
         avgv = vec_avg(pix2v, pix3v);
@@ -208,9 +132,9 @@
         /* Add each 4 pixel group together and put 4 results into sad. */
         sad = vec_sum4s(t5, sad);
 
-        pix1 += line_size;
+        pix1 += stride;
         pix2v = pix3v;
-        pix3 += line_size;
+        pix3 += stride;
     }
 
     /* Sum up the four partial sums, and put the result into s. */
@@ -219,134 +143,43 @@
     vec_ste(sumdiffs, 0, &s);
     return s;
 }
-#endif /* HAVE_VSX */
 
-#if HAVE_VSX
 static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                             int line_size, int h)
+                             ptrdiff_t stride, int h)
 {
-  int i, s = 0;
-  uint8_t *pix3 = pix2 + line_size;
-  const vector unsigned char zero =
-    (const vector unsigned char) vec_splat_u8(0);
-  const vector unsigned short two =
-    (const vector unsigned short) vec_splat_u16(2);
-  vector unsigned char avgv, t5;
-  vector unsigned char pix1v, pix3v, pix3iv;
-  vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv;
-  vector unsigned short avghv, avglv;
-  vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
-  vector signed int sumdiffs;
-
-  /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one
-   * iteration becomes pix2 in the next iteration. We can use this
-   * fact to avoid a potentially expensive unaligned read, as well
-   * as some splitting, and vector addition each time around the loop.
-   * Read unaligned pixels into our vectors. The vectors are as follows:
-   * pix2v: pix2[0] - pix2[15]  pix2iv: pix2[1] - pix2[16]
-   * Split the pixel vectors into shorts. */
-  vector unsigned char pix2v  = vec_vsx_ld(0,  pix2);
-  vector unsigned char pix2iv = vec_vsx_ld(1,  pix2);
-    vector unsigned short pix2hv  =
-      (vector unsigned short) vec_mergeh(pix2v, zero);
-    vector unsigned short pix2lv  =
-      (vector unsigned short) vec_mergel(pix2v, zero);
-    vector unsigned short pix2ihv =
-      (vector unsigned short) vec_mergeh(pix2iv, zero);
-    vector unsigned short pix2ilv =
-      (vector unsigned short) vec_mergel(pix2iv, zero);
-  vector unsigned short t1 = vec_add(pix2hv, pix2ihv);
-  vector unsigned short t2 = vec_add(pix2lv, pix2ilv);
-
-  vector unsigned short t3, t4;
-
-  for (i = 0; i < h; i++) {
-    /* Read unaligned pixels into our vectors. The vectors are as follows:
-     * pix1v: pix1[0] - pix1[15]
-     * pix3v: pix3[0] - pix3[15]      pix3iv: pix3[1] - pix3[16] */
-    pix1v  = vec_vsx_ld(0, pix1);
-    pix3v  = vec_vsx_ld(0, pix3);
-    pix3iv = vec_vsx_ld(1, pix3);
-
-    /* Note that AltiVec does have vec_avg, but this works on vector pairs
-     * and rounds up. We could do avg(avg(a, b), avg(c, d)), but the
-     * rounding would mean that, for example, avg(3, 0, 0, 1) = 2, when
-     * it should be 1. Instead, we have to split the pixel vectors into
-     * vectors of shorts and do the averaging by hand. */
-
-    /* Split the pixel vectors into shorts. */
-    pix3hv  = (vector unsigned short) vec_mergeh(pix3v, zero);
-    pix3lv  = (vector unsigned short) vec_mergel(pix3v, zero);
-    pix3ihv = (vector unsigned short) vec_mergeh(pix3iv, zero);
-    pix3ilv = (vector unsigned short) vec_mergel(pix3iv, zero);
-
-    /* Do the averaging on them. */
-    t3 = vec_add(pix3hv, pix3ihv);
-    t4 = vec_add(pix3lv, pix3ilv);
-
-    avghv = vec_sr(vec_add(vec_add(t1, t3), two), two);
-    avglv = vec_sr(vec_add(vec_add(t2, t4), two), two);
-
-    /* Pack the shorts back into a result. */
-    avgv = vec_pack(avghv, avglv);
-
-    /* Calculate a sum of abs differences vector. */
-    t5 = vec_sub(vec_max(pix1v, avgv), vec_min(pix1v, avgv));
-
-    /* Add each 4 pixel group together and put 4 results into sad. */
-    sad = vec_sum4s(t5, sad);
-
-    pix1 += line_size;
-    pix3 += line_size;
-    /* Transfer the calculated values for pix3 into pix2. */
-    t1 = t3;
-    t2 = t4;
-  }
-  /* Sum up the four partial sums, and put the result into s. */
-  sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
-  sumdiffs = vec_splat(sumdiffs, 3);
-  vec_vsx_st(sumdiffs, 0, &s);
-  return s;
-}
-#else
-static int sad16_xy2_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                             int line_size, int h)
-{
-    int i, s = 0;
-    uint8_t *pix3 = pix2 + line_size;
+    int i;
+    int  __attribute__((aligned(16))) s = 0;
+    uint8_t *pix3 = pix2 + stride;
     const vector unsigned char zero =
         (const vector unsigned char) vec_splat_u8(0);
     const vector unsigned short two =
         (const vector unsigned short) vec_splat_u16(2);
     vector unsigned char avgv, t5;
-    vector unsigned char perm1 = vec_lvsl(0, pix2);
-    vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1));
     vector unsigned char pix1v, pix3v, pix3iv;
     vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv;
     vector unsigned short avghv, avglv;
     vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumdiffs;
+    vector unsigned char perm1, perm2, pix2v, pix2iv;
+    GET_PERM(perm1, perm2, pix2);
 
-    /* Due to the fact that pix3 = pix2 + line_size, the pix3 of one
+    /* Due to the fact that pix3 = pix2 + stride, the pix3 of one
      * iteration becomes pix2 in the next iteration. We can use this
      * fact to avoid a potentially expensive unaligned read, as well
      * as some splitting, and vector addition each time around the loop.
      * Read unaligned pixels into our vectors. The vectors are as follows:
      * pix2v: pix2[0] - pix2[15]  pix2iv: pix2[1] - pix2[16]
      * Split the pixel vectors into shorts. */
-    vector unsigned char pix2l  = vec_ld(0,  pix2);
-    vector unsigned char pix2r  = vec_ld(16, pix2);
-    vector unsigned char pix2v  = vec_perm(pix2l, pix2r, perm1);
-    vector unsigned char pix2iv = vec_perm(pix2l, pix2r, perm2);
-
+    LOAD_PIX(pix2v, pix2iv, pix2, perm1, perm2);
     vector unsigned short pix2hv  =
-        (vector unsigned short) vec_mergeh(zero, pix2v);
+        (vector unsigned short) VEC_MERGEH(zero, pix2v);
     vector unsigned short pix2lv  =
-        (vector unsigned short) vec_mergel(zero, pix2v);
+        (vector unsigned short) VEC_MERGEL(zero, pix2v);
     vector unsigned short pix2ihv =
-        (vector unsigned short) vec_mergeh(zero, pix2iv);
+        (vector unsigned short) VEC_MERGEH(zero, pix2iv);
     vector unsigned short pix2ilv =
-        (vector unsigned short) vec_mergel(zero, pix2iv);
+        (vector unsigned short) VEC_MERGEL(zero, pix2iv);
+
     vector unsigned short t1 = vec_add(pix2hv, pix2ihv);
     vector unsigned short t2 = vec_add(pix2lv, pix2ilv);
     vector unsigned short t3, t4;
@@ -356,11 +189,7 @@
          * pix1v: pix1[0] - pix1[15]
          * pix3v: pix3[0] - pix3[15]      pix3iv: pix3[1] - pix3[16] */
         pix1v  = vec_ld(0, pix1);
-
-        pix2l  = vec_ld(0, pix3);
-        pix2r  = vec_ld(16, pix3);
-        pix3v  = vec_perm(pix2l, pix2r, perm1);
-        pix3iv = vec_perm(pix2l, pix2r, perm2);
+        LOAD_PIX(pix3v, pix3iv, pix3, perm1, perm2);
 
         /* Note that AltiVec does have vec_avg, but this works on vector pairs
          * and rounds up. We could do avg(avg(a, b), avg(c, d)), but the
@@ -369,10 +198,10 @@
          * vectors of shorts and do the averaging by hand. */
 
         /* Split the pixel vectors into shorts. */
-        pix3hv  = (vector unsigned short) vec_mergeh(zero, pix3v);
-        pix3lv  = (vector unsigned short) vec_mergel(zero, pix3v);
-        pix3ihv = (vector unsigned short) vec_mergeh(zero, pix3iv);
-        pix3ilv = (vector unsigned short) vec_mergel(zero, pix3iv);
+        pix3hv  = (vector unsigned short) VEC_MERGEH(zero, pix3v);
+        pix3lv  = (vector unsigned short) VEC_MERGEL(zero, pix3v);
+        pix3ihv = (vector unsigned short) VEC_MERGEH(zero, pix3iv);
+        pix3ilv = (vector unsigned short) VEC_MERGEL(zero, pix3iv);
 
         /* Do the averaging on them. */
         t3 = vec_add(pix3hv, pix3ihv);
@@ -390,8 +219,8 @@
         /* Add each 4 pixel group together and put 4 results into sad. */
         sad = vec_sum4s(t5, sad);
 
-        pix1 += line_size;
-        pix3 += line_size;
+        pix1 += stride;
+        pix3 += stride;
         /* Transfer the calculated values for pix3 into pix2. */
         t1 = t3;
         t2 = t4;
@@ -403,58 +232,21 @@
 
     return s;
 }
-#endif /* HAVE_VSX */
 
-#if HAVE_VSX
 static int sad16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                         int line_size, int h)
+                         ptrdiff_t stride, int h)
 {
-  int i, s;
-  const vector unsigned int zero =
-    (const vector unsigned int) vec_splat_u32(0);
-  vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
-  vector signed int sumdiffs;
-
-  for (i = 0; i < h; i++) {
-    /* Read potentially unaligned pixels into t1 and t2. */
-    vector unsigned char t1 =vec_vsx_ld(0, pix1);
-    vector unsigned char t2 = vec_vsx_ld(0, pix2);
-
-    /* Calculate a sum of abs differences vector. */
-    vector unsigned char t3 = vec_max(t1, t2);
-    vector unsigned char t4 = vec_min(t1, t2);
-    vector unsigned char t5 = vec_sub(t3, t4);
-
-    /* Add each 4 pixel group together and put 4 results into sad. */
-    sad = vec_sum4s(t5, sad);
-
-    pix1 += line_size;
-    pix2 += line_size;
-  }
-
-  /* Sum up the four partial sums, and put the result into s. */
-  sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
-  sumdiffs = vec_splat(sumdiffs, 3);
-  vec_vsx_st(sumdiffs, 0, &s);
-  return s;
-}
-#else
-static int sad16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                         int line_size, int h)
-{
-    int i, s;
+    int i;
+    int  __attribute__((aligned(16))) s;
     const vector unsigned int zero =
         (const vector unsigned int) vec_splat_u32(0);
-    vector unsigned char perm = vec_lvsl(0, pix2);
     vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumdiffs;
 
     for (i = 0; i < h; i++) {
         /* Read potentially unaligned pixels into t1 and t2. */
-        vector unsigned char pix2l = vec_ld(0,  pix2);
-        vector unsigned char pix2r = vec_ld(15, pix2);
-        vector unsigned char t1 = vec_ld(0, pix1);
-        vector unsigned char t2 = vec_perm(pix2l, pix2r, perm);
+        vector unsigned char t1 =vec_ld(0, pix1);
+        vector unsigned char t2 = VEC_LD(0, pix2);
 
         /* Calculate a sum of abs differences vector. */
         vector unsigned char t3 = vec_max(t1, t2);
@@ -464,8 +256,8 @@
         /* Add each 4 pixel group together and put 4 results into sad. */
         sad = vec_sum4s(t5, sad);
 
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
 
     /* Sum up the four partial sums, and put the result into s. */
@@ -475,60 +267,17 @@
 
     return s;
 }
-#endif /* HAVE_VSX */
 
-#if HAVE_VSX
 static int sad8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                                                int line_size, int h)
+                        ptrdiff_t stride, int h)
 {
-  int i, s;
-  const vector unsigned int zero =
-    (const vector unsigned int) vec_splat_u32(0);
-  const vector unsigned char permclear =
-    (vector unsigned char)
-    { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
-  vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
-  vector signed int sumdiffs;
-
-  for (i = 0; i < h; i++) {
-    /* Read potentially unaligned pixels into t1 and t2.
-     * Since we're reading 16 pixels, and actually only want 8,
-     * mask out the last 8 pixels. The 0s don't change the sum. */
-    vector unsigned char pix1l = vec_vsx_ld(0, pix1);
-    vector unsigned char pix2l = vec_vsx_ld(0, pix2);
-    vector unsigned char t1 = vec_and(pix1l, permclear);
-    vector unsigned char t2 = vec_and(pix2l, permclear);
-
-    /* Calculate a sum of abs differences vector. */
-    vector unsigned char t3 = vec_max(t1, t2);
-    vector unsigned char t4 = vec_min(t1, t2);
-    vector unsigned char t5 = vec_sub(t3, t4);
-
-    /* Add each 4 pixel group together and put 4 results into sad. */
-    sad = vec_sum4s(t5, sad);
-
-    pix1 += line_size;
-    pix2 += line_size;
-  }
-
-  /* Sum up the four partial sums, and put the result into s. */
-  sumdiffs = vec_sums((vector signed int) sad, (vector signed int) zero);
-  sumdiffs = vec_splat(sumdiffs, 3);
-  vec_vsx_st(sumdiffs, 0, &s);
-  return s;
-}
-#else
-static int sad8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                        int line_size, int h)
-{
-    int i, s;
+    int i;
+    int  __attribute__((aligned(16))) s;
     const vector unsigned int zero =
         (const vector unsigned int) vec_splat_u32(0);
     const vector unsigned char permclear =
         (vector unsigned char)
         { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
-    vector unsigned char perm1 = vec_lvsl(0, pix1);
-    vector unsigned char perm2 = vec_lvsl(0, pix2);
     vector unsigned int sad = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumdiffs;
 
@@ -536,14 +285,10 @@
         /* Read potentially unaligned pixels into t1 and t2.
          * Since we're reading 16 pixels, and actually only want 8,
          * mask out the last 8 pixels. The 0s don't change the sum. */
-        vector unsigned char pix1l = vec_ld(0, pix1);
-        vector unsigned char pix1r = vec_ld(7, pix1);
-        vector unsigned char pix2l = vec_ld(0, pix2);
-        vector unsigned char pix2r = vec_ld(7, pix2);
-        vector unsigned char t1 = vec_and(vec_perm(pix1l, pix1r, perm1),
-                                          permclear);
-        vector unsigned char t2 = vec_and(vec_perm(pix2l, pix2r, perm2),
-                                          permclear);
+        vector unsigned char pix1l = VEC_LD(0, pix1);
+        vector unsigned char pix2l = VEC_LD(0, pix2);
+        vector unsigned char t1 = vec_and(pix1l, permclear);
+        vector unsigned char t2 = vec_and(pix2l, permclear);
 
         /* Calculate a sum of abs differences vector. */
         vector unsigned char t3 = vec_max(t1, t2);
@@ -553,8 +298,8 @@
         /* Add each 4 pixel group together and put 4 results into sad. */
         sad = vec_sum4s(t5, sad);
 
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
 
     /* Sum up the four partial sums, and put the result into s. */
@@ -564,21 +309,19 @@
 
     return s;
 }
-#endif /* HAVE_VSX */
 
 /* Sum of Squared Errors for an 8x8 block, AltiVec-enhanced.
  * It's the sad8_altivec code above w/ squaring added. */
 static int sse8_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                        int line_size, int h)
+                        ptrdiff_t stride, int h)
 {
-    int i, s;
+    int i;
+    int  __attribute__((aligned(16))) s;
     const vector unsigned int zero =
         (const vector unsigned int) vec_splat_u32(0);
     const vector unsigned char permclear =
         (vector unsigned char)
         { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
-    vector unsigned char perm1 = vec_lvsl(0, pix1);
-    vector unsigned char perm2 = vec_lvsl(0, pix2);
     vector unsigned int sum = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumsqr;
 
@@ -586,14 +329,8 @@
         /* Read potentially unaligned pixels into t1 and t2.
          * Since we're reading 16 pixels, and actually only want 8,
          * mask out the last 8 pixels. The 0s don't change the sum. */
-        vector unsigned char pix1l = vec_ld(0, pix1);
-        vector unsigned char pix1r = vec_ld(7, pix1);
-        vector unsigned char pix2l = vec_ld(0, pix2);
-        vector unsigned char pix2r = vec_ld(7, pix2);
-        vector unsigned char t1 = vec_and(vec_perm(pix1l, pix1r, perm1),
-                                          permclear);
-        vector unsigned char t2 = vec_and(vec_perm(pix2l, pix2r, perm2),
-                                          permclear);
+        vector unsigned char t1 = vec_and(VEC_LD(0, pix1), permclear);
+        vector unsigned char t2 = vec_and(VEC_LD(0, pix2), permclear);
 
         /* Since we want to use unsigned chars, we can take advantage
          * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */
@@ -606,8 +343,8 @@
         /* Square the values and add them to our sum. */
         sum = vec_msum(t5, t5, sum);
 
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
 
     /* Sum up the four partial sums, and put the result into s. */
@@ -620,59 +357,20 @@
 
 /* Sum of Squared Errors for a 16x16 block, AltiVec-enhanced.
  * It's the sad16_altivec code above w/ squaring added. */
-#if HAVE_VSX
 static int sse16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                                                  int line_size, int h)
+                         ptrdiff_t stride, int h)
 {
-  int i, s;
-  const vector unsigned int zero =
-    (const vector unsigned int) vec_splat_u32(0);
-  vector unsigned int sum = (vector unsigned int) vec_splat_u32(0);
-  vector signed int sumsqr;
-
-  for (i = 0; i < h; i++) {
-    /* Read potentially unaligned pixels into t1 and t2. */
-    vector unsigned char t1 = vec_vsx_ld(0, pix1);
-    vector unsigned char t2 = vec_vsx_ld(0, pix2);
-
-    /* Since we want to use unsigned chars, we can take advantage
-     *          * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */
-
-    /* Calculate abs differences vector. */
-    vector unsigned char t3 = vec_max(t1, t2);
-    vector unsigned char t4 = vec_min(t1, t2);
-    vector unsigned char t5 = vec_sub(t3, t4);
-
-    /* Square the values and add them to our sum. */
-    sum = vec_msum(t5, t5, sum);
-
-    pix1 += line_size;
-    pix2 += line_size;
-  }
-
-  /* Sum up the four partial sums, and put the result into s. */
-  sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero);
-  sumsqr = vec_splat(sumsqr, 3);
-  vec_vsx_st(sumsqr, 0, &s);
-  return s;
-}
-#else
-static int sse16_altivec(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                         int line_size, int h)
-{
-    int i, s;
+    int i;
+    int  __attribute__((aligned(16))) s;
     const vector unsigned int zero =
         (const vector unsigned int) vec_splat_u32(0);
-    vector unsigned char perm = vec_lvsl(0, pix2);
     vector unsigned int sum = (vector unsigned int) vec_splat_u32(0);
     vector signed int sumsqr;
 
     for (i = 0; i < h; i++) {
         /* Read potentially unaligned pixels into t1 and t2. */
-        vector unsigned char pix2l = vec_ld(0,  pix2);
-        vector unsigned char pix2r = vec_ld(15, pix2);
         vector unsigned char t1 = vec_ld(0, pix1);
-        vector unsigned char t2 = vec_perm(pix2l, pix2r, perm);
+        vector unsigned char t2 = VEC_LD(0, pix2);
 
         /* Since we want to use unsigned chars, we can take advantage
          * of the fact that abs(a - b) ^ 2 = (a - b) ^ 2. */
@@ -685,23 +383,22 @@
         /* Square the values and add them to our sum. */
         sum = vec_msum(t5, t5, sum);
 
-        pix1 += line_size;
-        pix2 += line_size;
+        pix1 += stride;
+        pix2 += stride;
     }
 
     /* Sum up the four partial sums, and put the result into s. */
     sumsqr = vec_sums((vector signed int) sum, (vector signed int) zero);
     sumsqr = vec_splat(sumsqr, 3);
-    vec_ste(sumsqr, 0, &s);
 
+    vec_ste(sumsqr, 0, &s);
     return s;
 }
-#endif /* HAVE_VSX */
 
 static int hadamard8_diff8x8_altivec(MpegEncContext *s, uint8_t *dst,
-                                     uint8_t *src, int stride, int h)
+                                     uint8_t *src, ptrdiff_t stride, int h)
 {
-    int sum;
+    int __attribute__((aligned(16))) sum;
     register const vector unsigned char vzero =
         (const vector unsigned char) vec_splat_u8(0);
     register vector signed short temp0, temp1, temp2, temp3, temp4,
@@ -726,24 +423,19 @@
             { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
 
+
 #define ONEITERBUTTERFLY(i, res)                                            \
     {                                                                       \
-        register vector unsigned char src1 = vec_ld(stride * i, src);       \
-        register vector unsigned char src2 = vec_ld(stride * i + 15, src);  \
-        register vector unsigned char srcO =                                \
-            vec_perm(src1, src2, vec_lvsl(stride * i, src));                \
-        register vector unsigned char dst1 = vec_ld(stride * i, dst);       \
-        register vector unsigned char dst2 = vec_ld(stride * i + 15, dst);  \
-        register vector unsigned char dstO =                                \
-            vec_perm(dst1, dst2, vec_lvsl(stride * i, dst));                \
+        register vector unsigned char srcO =  unaligned_load(stride * i, src);  \
+        register vector unsigned char dstO = unaligned_load(stride * i, dst);\
                                                                             \
         /* Promote the unsigned chars to signed shorts. */                  \
         /* We're in the 8x8 function, we only care for the first 8. */      \
         register vector signed short srcV =                                 \
-            (vector signed short) vec_mergeh((vector signed char) vzero,    \
+            (vector signed short) VEC_MERGEH((vector signed char) vzero,    \
                                              (vector signed char) srcO);    \
         register vector signed short dstV =                                 \
-            (vector signed short) vec_mergeh((vector signed char) vzero,    \
+            (vector signed short) VEC_MERGEH((vector signed char) vzero,    \
                                              (vector signed char) dstO);    \
                                                                             \
         /* subtractions inside the first butterfly */                       \
@@ -755,6 +447,7 @@
         register vector signed short op3  = vec_perm(but2, but2, perm3);    \
         res  = vec_mladd(but2, vprod3, op3);                                \
     }
+
         ONEITERBUTTERFLY(0, temp0);
         ONEITERBUTTERFLY(1, temp1);
         ONEITERBUTTERFLY(2, temp2);
@@ -804,6 +497,7 @@
         vsum = vec_sum4s(vec_abs(line7C), vsum);
         vsum = vec_sums(vsum, (vector signed int) vzero);
         vsum = vec_splat(vsum, 3);
+
         vec_ste(vsum, 0, &sum);
     }
     return sum;
@@ -828,9 +522,9 @@
  * but xlc goes to around 660 on the regular C code...
  */
 static int hadamard8_diff16x8_altivec(MpegEncContext *s, uint8_t *dst,
-                                      uint8_t *src, int stride, int h)
+                                      uint8_t *src, ptrdiff_t stride, int h)
 {
-    int sum;
+    int __attribute__((aligned(16))) sum;
     register vector signed short
         temp0 __asm__ ("v0"),
         temp1 __asm__ ("v1"),
@@ -878,31 +572,23 @@
 
 #define ONEITERBUTTERFLY(i, res1, res2)                                     \
     {                                                                       \
-        register vector unsigned char src1 __asm__ ("v22") =                \
-            vec_ld(stride * i, src);                                        \
-        register vector unsigned char src2 __asm__ ("v23") =                \
-            vec_ld(stride * i + 16, src);                                   \
         register vector unsigned char srcO __asm__ ("v22") =                \
-            vec_perm(src1, src2, vec_lvsl(stride * i, src));                \
-        register vector unsigned char dst1 __asm__ ("v24") =                \
-            vec_ld(stride * i, dst);                                        \
-        register vector unsigned char dst2 __asm__ ("v25") =                \
-            vec_ld(stride * i + 16, dst);                                   \
+            unaligned_load(stride * i, src);                                    \
         register vector unsigned char dstO __asm__ ("v23") =                \
-            vec_perm(dst1, dst2, vec_lvsl(stride * i, dst));                \
+            unaligned_load(stride * i, dst);\
                                                                             \
         /* Promote the unsigned chars to signed shorts. */                  \
         register vector signed short srcV __asm__ ("v24") =                 \
-            (vector signed short) vec_mergeh((vector signed char) vzero,    \
+            (vector signed short) VEC_MERGEH((vector signed char) vzero,    \
                                              (vector signed char) srcO);    \
         register vector signed short dstV __asm__ ("v25") =                 \
-            (vector signed short) vec_mergeh((vector signed char) vzero,    \
+            (vector signed short) VEC_MERGEH((vector signed char) vzero,    \
                                              (vector signed char) dstO);    \
         register vector signed short srcW __asm__ ("v26") =                 \
-            (vector signed short) vec_mergel((vector signed char) vzero,    \
+            (vector signed short) VEC_MERGEL((vector signed char) vzero,    \
                                              (vector signed char) srcO);    \
         register vector signed short dstW __asm__ ("v27") =                 \
-            (vector signed short) vec_mergel((vector signed char) vzero,    \
+            (vector signed short) VEC_MERGEL((vector signed char) vzero,    \
                                              (vector signed char) dstO);    \
                                                                             \
         /* subtractions inside the first butterfly */                       \
@@ -933,6 +619,7 @@
         res1 = vec_mladd(but2, vprod3, op3);                                \
         res2 = vec_mladd(but2S, vprod3, op3S);                              \
     }
+
         ONEITERBUTTERFLY(0, temp0, temp0S);
         ONEITERBUTTERFLY(1, temp1, temp1S);
         ONEITERBUTTERFLY(2, temp2, temp2S);
@@ -1019,13 +706,14 @@
         vsum = vec_sum4s(vec_abs(line7CS), vsum);
         vsum = vec_sums(vsum, (vector signed int) vzero);
         vsum = vec_splat(vsum, 3);
+
         vec_ste(vsum, 0, &sum);
     }
     return sum;
 }
 
 static int hadamard8_diff16_altivec(MpegEncContext *s, uint8_t *dst,
-                                    uint8_t *src, int stride, int h)
+                                    uint8_t *src, ptrdiff_t stride, int h)
 {
     int score = hadamard8_diff16x8_altivec(s, dst, src, stride, 8);
 
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index e4f92d9..5a4ab84 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -286,13 +286,10 @@
 
     if (src->slice_count && src->slice_offset) {
         if (dst->slice_count < src->slice_count) {
-            int *tmp = av_realloc(dst->slice_offset, src->slice_count *
-                                  sizeof(*dst->slice_offset));
-            if (!tmp) {
-                av_free(dst->slice_offset);
-                return AVERROR(ENOMEM);
-            }
-            dst->slice_offset = tmp;
+            int err = av_reallocp_array(&dst->slice_offset, src->slice_count,
+                                        sizeof(*dst->slice_offset));
+            if (err < 0)
+                return err;
         }
         memcpy(dst->slice_offset, src->slice_offset,
                src->slice_count * sizeof(*dst->slice_offset));
@@ -654,8 +651,8 @@
 
         p->frame = av_frame_alloc();
         if (!p->frame) {
-            err = AVERROR(ENOMEM);
             av_freep(&copy);
+            err = AVERROR(ENOMEM);
             goto error;
         }
 
diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
index fea989f..b948e16 100644
--- a/libavcodec/pthread_slice.c
+++ b/libavcodec/pthread_slice.c
@@ -120,7 +120,7 @@
     pthread_mutex_destroy(&c->current_job_lock);
     pthread_cond_destroy(&c->current_job_cond);
     pthread_cond_destroy(&c->last_job_cond);
-    av_free(c->workers);
+    av_freep(&c->workers);
     av_freep(&avctx->internal->thread_ctx);
 }
 
diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c
index 968672c..dbb2643 100644
--- a/libavcodec/ra288.c
+++ b/libavcodec/ra288.c
@@ -38,7 +38,7 @@
 #define RA288_BLOCKS_PER_FRAME 32
 
 typedef struct {
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     DECLARE_ALIGNED(32, float,   sp_lpc)[FFALIGN(36, 16)];   ///< LPC coefficients for speech data (spec: A)
     DECLARE_ALIGNED(32, float, gain_lpc)[FFALIGN(10, 16)];   ///< LPC coefficients for gain        (spec: GB)
 
@@ -59,6 +59,15 @@
     float gain_rec[11];
 } RA288Context;
 
+static av_cold int ra288_decode_close(AVCodecContext *avctx)
+{
+    RA288Context *ractx = avctx->priv_data;
+
+    av_freep(&ractx->fdsp);
+
+    return 0;
+}
+
 static av_cold int ra288_decode_init(AVCodecContext *avctx)
 {
     RA288Context *ractx = avctx->priv_data;
@@ -72,7 +81,9 @@
         return AVERROR_PATCHWELCOME;
     }
 
-    avpriv_float_dsp_init(&ractx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    ractx->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!ractx->fdsp)
+        return AVERROR(ENOMEM);
 
     return 0;
 }
@@ -146,7 +157,7 @@
 
     av_assert2(order>=0);
 
-    ractx->fdsp.vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 16));
+    ractx->fdsp->vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 16));
 
     convolve(buffer1, work + order    , n      , order);
     convolve(buffer2, work + order + n, non_rec, order);
@@ -173,7 +184,7 @@
     do_hybrid_window(ractx, order, n, non_rec, temp, hist, rec, window);
 
     if (!compute_lpc_coefs(temp, order, lpc, 0, 1, 1))
-        ractx->fdsp.vector_fmul(lpc, lpc, tab, FFALIGN(order, 16));
+        ractx->fdsp->vector_fmul(lpc, lpc, tab, FFALIGN(order, 16));
 
     memmove(hist, hist + n, move_size*sizeof(*hist));
 }
@@ -235,5 +246,6 @@
     .priv_data_size = sizeof(RA288Context),
     .init           = ra288_decode_init,
     .decode         = ra288_decode_frame,
+    .close          = ra288_decode_close,
     .capabilities   = CODEC_CAP_DR1,
 };
diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c
index 28792a1..647dfa9 100644
--- a/libavcodec/rawdec.c
+++ b/libavcodec/rawdec.c
@@ -172,6 +172,9 @@
         context->frame_size = avpicture_get_size(avctx->pix_fmt, avctx->width,
                                                  avctx->height);
     }
+    if (context->frame_size < 0)
+        return context->frame_size;
+
     need_copy = !avpkt->buf || context->is_2_4_bpp || context->is_yuv2 || context->is_lt_16bpp;
 
     frame->pict_type        = AV_PICTURE_TYPE_I;
diff --git a/libavcodec/rl2.c b/libavcodec/rl2.c
index 6e63ed1..eaf31b6 100644
--- a/libavcodec/rl2.c
+++ b/libavcodec/rl2.c
@@ -207,7 +207,7 @@
 {
     Rl2Context *s = avctx->priv_data;
 
-    av_free(s->back_frame);
+    av_freep(&s->back_frame);
 
     return 0;
 }
diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c
index b0b76d0..2c59074 100644
--- a/libavcodec/roqaudioenc.c
+++ b/libavcodec/roqaudioenc.c
@@ -148,9 +148,8 @@
             return 0;
         }
     }
-    if (context->input_frames < 8) {
+    if (context->input_frames < 8)
         in = context->frame_buffer;
-    }
 
     if (stereo) {
         context->lastSample[0] &= 0xFF00;
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index 1c5970f..694792e 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -936,8 +936,8 @@
     FFSWAP(motion_vect *, enc->last_motion4, enc->this_motion4);
     FFSWAP(motion_vect *, enc->last_motion8, enc->this_motion8);
 
-    av_free(tempData->cel_evals);
-    av_free(tempData->closest_cb2);
+    av_freep(&tempData->cel_evals);
+    av_freep(&tempData->closest_cb2);
 
     enc->framesSinceKeyframe++;
 
@@ -951,11 +951,11 @@
     av_frame_free(&enc->current_frame);
     av_frame_free(&enc->last_frame);
 
-    av_free(enc->tmpData);
-    av_free(enc->this_motion4);
-    av_free(enc->last_motion4);
-    av_free(enc->this_motion8);
-    av_free(enc->last_motion8);
+    av_freep(&enc->tmpData);
+    av_freep(&enc->this_motion4);
+    av_freep(&enc->last_motion4);
+    av_freep(&enc->this_motion8);
+    av_freep(&enc->last_motion8);
 
     return 0;
 }
diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c
index fd8fd4f..1483107c 100644
--- a/libavcodec/rv30.c
+++ b/libavcodec/rv30.c
@@ -259,13 +259,13 @@
     RV34DecContext *r = avctx->priv_data;
     int ret;
 
+    if (avctx->extradata_size < 2) {
+        av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");
+        return AVERROR(EINVAL);
+    }
     r->rv30 = 1;
     if ((ret = ff_rv34_decode_init(avctx)) < 0)
         return ret;
-    if(avctx->extradata_size < 2){
-        av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");
-        return -1;
-    }
 
     r->max_rpr = avctx->extradata[1] & 7;
     if(avctx->extradata_size < 2*r->max_rpr + 8){
diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c
index 5c4bf81..4c9cc06 100644
--- a/libavcodec/shorten.c
+++ b/libavcodec/shorten.c
@@ -510,7 +510,7 @@
                 if (bitshift > 31) {
                     av_log(avctx, AV_LOG_ERROR, "bitshift %d is invalid\n",
                            bitshift);
-                    return AVERROR_PATCHWELCOME;
+                    return AVERROR_INVALIDDATA;
                 }
                 s->bitshift = bitshift;
                 break;
diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c
index 518bdad..b5538c7 100644
--- a/libavcodec/smacker.c
+++ b/libavcodec/smacker.c
@@ -589,6 +589,7 @@
     /* decode huffman trees from extradata */
     if(avctx->extradata_size < 16){
         av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n");
+        decode_end(avctx);
         return AVERROR(EINVAL);
     }
 
diff --git a/libavcodec/smvjpegdec.c b/libavcodec/smvjpegdec.c
index 69327cd..375c9d9 100644
--- a/libavcodec/smvjpegdec.c
+++ b/libavcodec/smvjpegdec.c
@@ -75,6 +75,20 @@
         dst_data[1] = src_data[1];
 }
 
+static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
+{
+    SMVJpegDecodeContext *s = avctx->priv_data;
+    MJpegDecodeContext *jpg = &s->jpg;
+    int ret;
+
+    jpg->picture_ptr = NULL;
+    av_frame_free(&s->picture[0]);
+    av_frame_free(&s->picture[1]);
+    ret = avcodec_close(s->avctx);
+    av_freep(&s->avctx);
+    return ret;
+}
+
 static av_cold int smvjpeg_decode_init(AVCodecContext *avctx)
 {
     SMVJpegDecodeContext *s = avctx->priv_data;
@@ -89,8 +103,10 @@
         return AVERROR(ENOMEM);
 
     s->picture[1] = av_frame_alloc();
-    if (!s->picture[1])
+    if (!s->picture[1]) {
+        av_frame_free(&s->picture[0]);
         return AVERROR(ENOMEM);
+    }
 
     s->jpg.picture_ptr      = s->picture[0];
 
@@ -120,6 +136,8 @@
     }
     av_dict_free(&thread_opt);
 
+    if (ret < 0)
+        smvjpeg_decode_end(avctx);
     return ret;
 }
 
@@ -176,20 +194,6 @@
     return ret;
 }
 
-static av_cold int smvjpeg_decode_end(AVCodecContext *avctx)
-{
-    SMVJpegDecodeContext *s = avctx->priv_data;
-    MJpegDecodeContext *jpg = &s->jpg;
-    int ret;
-
-    jpg->picture_ptr = NULL;
-    av_frame_free(&s->picture[0]);
-    av_frame_free(&s->picture[1]);
-    ret = avcodec_close(s->avctx);
-    av_freep(&s->avctx);
-    return ret;
-}
-
 static const AVClass smvjpegdec_class = {
     .class_name = "SMVJPEG decoder",
     .item_name  = av_default_item_name,
diff --git a/libavcodec/snow.c b/libavcodec/snow.c
index 3701707..83db3c7 100644
--- a/libavcodec/snow.c
+++ b/libavcodec/snow.c
@@ -637,8 +637,10 @@
     if(s->last_picture[s->max_ref_frames-1]->data[0]){
         av_frame_unref(s->last_picture[s->max_ref_frames-1]);
         for(i=0; i<9; i++)
-            if(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3])
+            if(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3]) {
                 av_free(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] - EDGE_WIDTH*(1+s->current_picture->linesize[i%3]));
+                s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] = NULL;
+            }
     }
 }
 
diff --git a/libavcodec/snow_dwt.c b/libavcodec/snow_dwt.c
index 63ff7a0..5b890e0 100644
--- a/libavcodec/snow_dwt.c
+++ b/libavcodec/snow_dwt.c
@@ -745,7 +745,7 @@
                               decomposition_count, y);
 }
 
-static inline int w_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size,
+static inline int w_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size,
                       int w, int h, int type)
 {
     int s, i, j;
@@ -814,32 +814,32 @@
     return s >> 9;
 }
 
-static int w53_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+static int w53_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h)
 {
     return w_c(v, pix1, pix2, line_size, 8, h, 1);
 }
 
-static int w97_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+static int w97_8_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h)
 {
     return w_c(v, pix1, pix2, line_size, 8, h, 0);
 }
 
-static int w53_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+static int w53_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h)
 {
     return w_c(v, pix1, pix2, line_size, 16, h, 1);
 }
 
-static int w97_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+static int w97_16_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h)
 {
     return w_c(v, pix1, pix2, line_size, 16, h, 0);
 }
 
-int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h)
 {
     return w_c(v, pix1, pix2, line_size, 32, h, 1);
 }
 
-int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
+int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h)
 {
     return w_c(v, pix1, pix2, line_size, 32, h, 0);
 }
diff --git a/libavcodec/snow_dwt.h b/libavcodec/snow_dwt.h
index e929189..e2d7528 100644
--- a/libavcodec/snow_dwt.h
+++ b/libavcodec/snow_dwt.h
@@ -21,6 +21,7 @@
 #ifndef AVCODEC_SNOW_DWT_H
 #define AVCODEC_SNOW_DWT_H
 
+#include <stddef.h>
 #include <stdint.h>
 
 typedef int DWTELEM;
@@ -105,8 +106,8 @@
                               int src_y, int src_stride, slice_buffer *sb,
                               int add, uint8_t *dst8);
 
-int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
-int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h);
+int ff_w53_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h);
+int ff_w97_32_c(struct MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t line_size, int h);
 
 void ff_spatial_dwt(int *buffer, int *temp, int width, int height, int stride,
                     int type, int decomposition_count);
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index c790d9b..cbc89c9 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -1862,7 +1862,7 @@
     ff_snow_common_end(s);
     ff_rate_control_uninit(&s->m);
     av_frame_free(&s->input_picture);
-    av_free(avctx->stats_out);
+    av_freep(&avctx->stats_out);
 
     return 0;
 }
diff --git a/libavcodec/sunrastenc.c b/libavcodec/sunrastenc.c
index a55e3d4..cff8c85 100644
--- a/libavcodec/sunrastenc.c
+++ b/libavcodec/sunrastenc.c
@@ -158,6 +158,7 @@
     case AV_PIX_FMT_PAL8 :
         s->maptype   = RMT_EQUAL_RGB;
         s->maplength = 3 * 256;
+        /* fall-through */
     case AV_PIX_FMT_GRAY8:
         s->depth = 8;
         break;
diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c
index 121ebc4..052b618 100644
--- a/libavcodec/svq1dec.c
+++ b/libavcodec/svq1dec.c
@@ -499,7 +499,7 @@
     return result;
 }
 
-static void svq1_parse_string(GetBitContext *bitbuf, uint8_t *out)
+static void svq1_parse_string(GetBitContext *bitbuf, uint8_t out[257])
 {
     uint8_t seed;
     int i;
@@ -511,6 +511,7 @@
         out[i] = get_bits(bitbuf, 8) ^ seed;
         seed   = string_table[out[i] ^ seed];
     }
+    out[i] = 0;
 }
 
 static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame)
@@ -553,12 +554,12 @@
         }
 
         if ((s->frame_code ^ 0x10) >= 0x50) {
-            uint8_t msg[256];
+            uint8_t msg[257];
 
             svq1_parse_string(bitbuf, msg);
 
             av_log(avctx, AV_LOG_INFO,
-                   "embedded message:\n%s\n", (char *)msg);
+                   "embedded message:\n%s\n", ((char *)msg) + 1);
         }
 
         skip_bits(bitbuf, 2);
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index 288da1f..2a0d780 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -96,7 +96,7 @@
     int w            = 2 << (level + 2 >> 1);
     int h            = 2 << (level + 1 >> 1);
     int size         = w * h;
-    DECLARE_ALIGNED(16, int16_t, block)[7][256];
+    int16_t (*block)[256] = s->encoded_block_levels[level];
     const int8_t *codebook_sum, *codebook;
     const uint16_t(*mean_vlc)[2];
     const uint8_t(*multistage_vlc)[2];
diff --git a/libavcodec/svq1enc.h b/libavcodec/svq1enc.h
index 740d2ff..8e74885 100644
--- a/libavcodec/svq1enc.h
+++ b/libavcodec/svq1enc.h
@@ -59,6 +59,8 @@
     int c_block_width;
     int c_block_height;
 
+    DECLARE_ALIGNED(16, int16_t, encoded_block_levels)[6][7][256];
+
     uint16_t *mb_type;
     uint32_t *dummy;
     int16_t (*motion_val8[3])[2];
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 0870e31..ee16d78 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -29,6 +29,7 @@
 #include <zlib.h>
 #endif
 #if CONFIG_LZMA
+#define LZMA_API_STATIC
 #include <lzma.h>
 #endif
 
diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c
index 138d214..72219da 100644
--- a/libavcodec/tiffenc.c
+++ b/libavcodec/tiffenc.c
@@ -235,7 +235,7 @@
     int bytes_per_row;
     uint32_t res[2] = { s->dpi, 1 };    // image resolution (72/1)
     uint16_t bpp_tab[4];
-    int ret = -1;
+    int ret = 0;
     int is_yuv = 0, alpha = 0;
     int shift_h, shift_v;
     int packet_size;
@@ -327,6 +327,10 @@
     offset = ptr;
     bytestream_put_le32(&ptr, 0);
 
+    if (strips > INT_MAX / FFMAX(sizeof(s->strip_sizes[0]), sizeof(s->strip_offsets[0]))) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
     av_fast_padded_mallocz(&s->strip_sizes  , &s->strip_sizes_size  , sizeof(s->strip_sizes  [0]) * strips);
     av_fast_padded_mallocz(&s->strip_offsets, &s->strip_offsets_size, sizeof(s->strip_offsets[0]) * strips);
 
@@ -416,7 +420,7 @@
         }
     }
     if (s->compr == TIFF_LZW)
-        av_free(s->lzws);
+        av_freep(&s->lzws);
     }
 
     s->num_entries = 0;
diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c
index 18d7c1e..d2aa3c6 100644
--- a/libavcodec/truemotion2.c
+++ b/libavcodec/truemotion2.c
@@ -996,14 +996,14 @@
     av_free(l->last);
     av_free(l->clast);
     for (i = 0; i < TM2_NUM_STREAMS; i++)
-        av_free(l->tokens[i]);
+        av_freep(&l->tokens[i]);
     if (l->Y1) {
-        av_free(l->Y1_base);
-        av_free(l->U1_base);
-        av_free(l->V1_base);
-        av_free(l->Y2_base);
-        av_free(l->U2_base);
-        av_free(l->V2_base);
+        av_freep(&l->Y1_base);
+        av_freep(&l->U1_base);
+        av_freep(&l->V1_base);
+        av_freep(&l->Y2_base);
+        av_freep(&l->U2_base);
+        av_freep(&l->V2_base);
     }
     av_freep(&l->buffer);
     l->buffer_size = 0;
diff --git a/libavcodec/tta.c b/libavcodec/tta.c
index 5fdbac8..01584d9 100644
--- a/libavcodec/tta.c
+++ b/libavcodec/tta.c
@@ -394,7 +394,7 @@
     TTAContext *s = avctx->priv_data;
 
     if (s->bps < 3)
-        av_free(s->decode_buffer);
+        av_freep(&s->decode_buffer);
     s->decode_buffer = NULL;
     av_freep(&s->ch_ctx);
 
diff --git a/libavcodec/twinvq.c b/libavcodec/twinvq.c
index f117220..4c289b0 100644
--- a/libavcodec/twinvq.c
+++ b/libavcodec/twinvq.c
@@ -358,7 +358,7 @@
 
         mdct->imdct_half(mdct, buf1 + bsize * j, in + bsize * j);
 
-        tctx->fdsp.vector_fmul_window(out2, prev_buf + (bsize - wsize) / 2,
+        tctx->fdsp->vector_fmul_window(out2, prev_buf + (bsize - wsize) / 2,
                                       buf1 + bsize * j,
                                       ff_sine_windows[av_log2(wsize)],
                                       wsize / 2);
@@ -405,7 +405,7 @@
                size1 * sizeof(*out2));
         memcpy(out2 + size1, &tctx->curr_frame[2 * mtab->size],
                size2 * sizeof(*out2));
-        tctx->fdsp.butterflies_float(out1, out2, mtab->size);
+        tctx->fdsp->butterflies_float(out1, out2, mtab->size);
     }
 }
 
@@ -446,7 +446,7 @@
                                bits->bark_use_hist[i][j], i,
                                tctx->tmp_buf, gain[sub * i + j], ftype);
 
-            tctx->fdsp.vector_fmul(chunk + block_size * j,
+            tctx->fdsp->vector_fmul(chunk + block_size * j,
                                    chunk + block_size * j,
                                    tctx->tmp_buf, block_size);
         }
@@ -461,7 +461,7 @@
         dec_lpc_spectrum_inv(tctx, lsp, ftype, tctx->tmp_buf);
 
         for (j = 0; j < mtab->fmode[ftype].sub; j++) {
-            tctx->fdsp.vector_fmul(chunk, chunk, tctx->tmp_buf, block_size);
+            tctx->fdsp->vector_fmul(chunk, chunk, tctx->tmp_buf, block_size);
             chunk += block_size;
         }
     }
@@ -755,13 +755,14 @@
 
     for (i = 0; i < 3; i++) {
         ff_mdct_end(&tctx->mdct_ctx[i]);
-        av_free(tctx->cos_tabs[i]);
+        av_freep(&tctx->cos_tabs[i]);
     }
 
-    av_free(tctx->curr_frame);
-    av_free(tctx->spectrum);
-    av_free(tctx->prev_frame);
-    av_free(tctx->tmp_buf);
+    av_freep(&tctx->curr_frame);
+    av_freep(&tctx->spectrum);
+    av_freep(&tctx->prev_frame);
+    av_freep(&tctx->tmp_buf);
+    av_freep(&tctx->fdsp);
 
     return 0;
 }
@@ -788,7 +789,11 @@
         return AVERROR_INVALIDDATA;
     }
 
-    avpriv_float_dsp_init(&tctx->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    tctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!tctx->fdsp) {
+        ff_twinvq_decode_close(avctx);
+        return AVERROR(ENOMEM);
+    }
     if ((ret = init_mdct_win(tctx))) {
         av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n");
         ff_twinvq_decode_close(avctx);
diff --git a/libavcodec/twinvq.h b/libavcodec/twinvq.h
index c4e9688..ae0f595 100644
--- a/libavcodec/twinvq.h
+++ b/libavcodec/twinvq.h
@@ -136,7 +136,7 @@
 
 typedef struct TwinVQContext {
     AVCodecContext *avctx;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FFTContext mdct_ctx[3];
 
     const TwinVQModeTab *mtab;
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 76dec1f..66fe62c 100755
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -735,44 +735,34 @@
 int ff_init_buffer_info(AVCodecContext *avctx, AVFrame *frame)
 {
     AVPacket *pkt = avctx->internal->pkt;
+    int i;
+    static const struct {
+        enum AVPacketSideDataType packet;
+        enum AVFrameSideDataType frame;
+    } sd[] = {
+        { AV_PKT_DATA_REPLAYGAIN ,   AV_FRAME_DATA_REPLAYGAIN },
+        { AV_PKT_DATA_DISPLAYMATRIX, AV_FRAME_DATA_DISPLAYMATRIX },
+        { AV_PKT_DATA_STEREO3D,      AV_FRAME_DATA_STEREO3D },
+    };
 
     if (pkt) {
-        uint8_t *packet_sd;
-        AVFrameSideData *frame_sd;
-        int size;
         frame->pkt_pts = pkt->pts;
         av_frame_set_pkt_pos     (frame, pkt->pos);
         av_frame_set_pkt_duration(frame, pkt->duration);
         av_frame_set_pkt_size    (frame, pkt->size);
 
-        /* copy the replaygain data to the output frame */
-        packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_REPLAYGAIN, &size);
-        if (packet_sd) {
-            frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_REPLAYGAIN, size);
-            if (!frame_sd)
-                return AVERROR(ENOMEM);
+        for (i = 0; i < FF_ARRAY_ELEMS(sd); i++) {
+            int size;
+            uint8_t *packet_sd = av_packet_get_side_data(pkt, sd[i].packet, &size);
+            if (packet_sd) {
+                AVFrameSideData *frame_sd = av_frame_new_side_data(frame,
+                                                                   sd[i].frame,
+                                                                   size);
+                if (!frame_sd)
+                    return AVERROR(ENOMEM);
 
-            memcpy(frame_sd->data, packet_sd, size);
-        }
-
-        /* copy the displaymatrix to the output frame */
-        packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_DISPLAYMATRIX, &size);
-        if (packet_sd) {
-            frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX, size);
-            if (!frame_sd)
-                return AVERROR(ENOMEM);
-
-            memcpy(frame_sd->data, packet_sd, size);
-        }
-
-        /* copy the stereo3d format to the output frame */
-        packet_sd = av_packet_get_side_data(pkt, AV_PKT_DATA_STEREO3D, &size);
-        if (packet_sd) {
-            frame_sd = av_frame_new_side_data(frame, AV_FRAME_DATA_STEREO3D, size);
-            if (!frame_sd)
-                return AVERROR(ENOMEM);
-
-            memcpy(frame_sd->data, packet_sd, size);
+                memcpy(frame_sd->data, packet_sd, size);
+            }
         }
     } else {
         frame->pkt_pts = AV_NOPTS_VALUE;
@@ -1210,6 +1200,11 @@
     memcpy(choices, fmt, (n + 1) * sizeof(*choices));
 
     for (;;) {
+        if (avctx->hwaccel && avctx->hwaccel->uninit)
+            avctx->hwaccel->uninit(avctx);
+        av_freep(&avctx->internal->hwaccel_priv_data);
+        avctx->hwaccel = NULL;
+
         ret = avctx->get_format(avctx, choices);
 
         desc = av_pix_fmt_desc_get(ret);
@@ -1218,11 +1213,6 @@
             break;
         }
 
-        if (avctx->hwaccel && avctx->hwaccel->uninit)
-            avctx->hwaccel->uninit(avctx);
-        av_freep(&avctx->internal->hwaccel_priv_data);
-        avctx->hwaccel = NULL;
-
         if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
             break;
         if (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
@@ -1700,6 +1690,8 @@
     return ret;
 free_and_end:
     av_dict_free(&tmp);
+    if (codec->priv_class && codec->priv_data_size)
+        av_opt_free(avctx->priv_data);
     av_freep(&avctx->priv_data);
     if (avctx->internal) {
         av_frame_free(&avctx->internal->to_free);
@@ -3033,8 +3025,8 @@
             if (enc->colorspace != AVCOL_SPC_UNSPECIFIED ||
                 enc->color_primaries != AVCOL_PRI_UNSPECIFIED ||
                 enc->color_trc != AVCOL_TRC_UNSPECIFIED) {
-                if (enc->colorspace != (enum AVColorSpace)enc->color_primaries ||
-                    enc->colorspace != (enum AVColorSpace)enc->color_trc) {
+                if (enc->colorspace != (int)enc->color_primaries ||
+                    enc->colorspace != (int)enc->color_trc) {
                     new_line = 1;
                     av_strlcatf(detail, sizeof(detail), "%s/%s/%s, ",
                                 av_color_space_name(enc->colorspace),
@@ -3322,6 +3314,7 @@
     case AV_CODEC_ID_MP1:          return  384;
     case AV_CODEC_ID_ATRAC1:       return  512;
     case AV_CODEC_ID_ATRAC3:       return 1024;
+    case AV_CODEC_ID_ATRAC3P:      return 2048;
     case AV_CODEC_ID_MP2:
     case AV_CODEC_ID_MUSEPACK7:    return 1152;
     case AV_CODEC_ID_AC3:          return 1536;
@@ -3740,6 +3733,11 @@
     ret = av_bprint_finalize(buf, &str);
     if (ret < 0)
         return ret;
+    if (!av_bprint_is_complete(buf)) {
+        av_free(str);
+        return AVERROR(ENOMEM);
+    }
+
     avctx->extradata = str;
     /* Note: the string is NUL terminated (so extradata can be read as a
      * string), but the ending character is not accounted in the size (in
diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c
index afd56ea..b565c10 100644
--- a/libavcodec/utvideodec.c
+++ b/libavcodec/utvideodec.c
@@ -56,13 +56,14 @@
         *fsym = he[0].sym;
         return 0;
     }
-    if (he[0].len > 32)
-        return -1;
 
     last = 255;
     while (he[last].len == 255 && last)
         last--;
 
+    if (he[last].len > 32)
+        return -1;
+
     code = 1;
     for (i = last; i >= 0; i--) {
         codes[i] = code >> (32 - he[i].len);
@@ -224,7 +225,7 @@
             A        = bsrc[i];
         }
         bsrc += stride;
-        if (slice_height == 1)
+        if (slice_height <= 1)
             continue;
         // second line - first element has top prediction, the rest uses median
         C        = bsrc[-stride];
@@ -284,7 +285,7 @@
             A                 = bsrc[stride + i];
         }
         bsrc += stride2;
-        if (slice_height == 1)
+        if (slice_height <= 1)
             continue;
         // second line - first element has top prediction, the rest uses median
         C        = bsrc[-stride2];
diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c
index 1e53bdb..0d40f99 100644
--- a/libavcodec/v210enc.c
+++ b/libavcodec/v210enc.c
@@ -24,82 +24,190 @@
 #include "avcodec.h"
 #include "bytestream.h"
 #include "internal.h"
+#include "v210enc.h"
+
+#define CLIP(v) av_clip(v, 4, 1019)
+#define CLIP8(v) av_clip(v, 1, 254)
+
+#define WRITE_PIXELS(a, b, c)           \
+    do {                                \
+        val =   CLIP(*a++);             \
+        val |= (CLIP(*b++) << 10) |     \
+               (CLIP(*c++) << 20);      \
+        AV_WL32(dst, val);              \
+        dst += 4;                       \
+    } while (0)
+
+#define WRITE_PIXELS8(a, b, c)          \
+    do {                                \
+        val =  (CLIP8(*a++) << 2);       \
+        val |= (CLIP8(*b++) << 12) |     \
+               (CLIP8(*c++) << 22);      \
+        AV_WL32(dst, val);              \
+        dst += 4;                       \
+    } while (0)
+
+static void v210_planar_pack_8_c(const uint8_t *y, const uint8_t *u,
+                                 const uint8_t *v, uint8_t *dst, ptrdiff_t width)
+{
+    uint32_t val;
+    int i;
+
+    /* unroll this to match the assembly */
+    for( i = 0; i < width-11; i += 12 ){
+        WRITE_PIXELS8(u, y, v);
+        WRITE_PIXELS8(y, u, y);
+        WRITE_PIXELS8(v, y, u);
+        WRITE_PIXELS8(y, v, y);
+        WRITE_PIXELS8(u, y, v);
+        WRITE_PIXELS8(y, u, y);
+        WRITE_PIXELS8(v, y, u);
+        WRITE_PIXELS8(y, v, y);
+    }
+}
+
+static void v210_planar_pack_10_c(const uint16_t *y, const uint16_t *u,
+                                  const uint16_t *v, uint8_t *dst, ptrdiff_t width)
+{
+    uint32_t val;
+    int i;
+
+    for( i = 0; i < width-5; i += 6 ){
+        WRITE_PIXELS(u, y, v);
+        WRITE_PIXELS(y, u, y);
+        WRITE_PIXELS(v, y, u);
+        WRITE_PIXELS(y, v, y);
+    }
+}
 
 static av_cold int encode_init(AVCodecContext *avctx)
 {
+    V210EncContext *s = avctx->priv_data;
+
     if (avctx->width & 1) {
         av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n");
         return AVERROR(EINVAL);
     }
 
-    if (avctx->bits_per_raw_sample != 10)
-        av_log(avctx, AV_LOG_WARNING, "bits per raw sample: %d != 10-bit\n",
-               avctx->bits_per_raw_sample);
-
     avctx->coded_frame = av_frame_alloc();
     if (!avctx->coded_frame)
         return AVERROR(ENOMEM);
 
     avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
 
+    s->pack_line_8          = v210_planar_pack_8_c;
+    s->pack_line_10         = v210_planar_pack_10_c;
+
+    if (ARCH_X86)
+        ff_v210enc_init_x86(s);
+
     return 0;
 }
 
 static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                         const AVFrame *pic, int *got_packet)
 {
+    V210EncContext *s = avctx->priv_data;
+
     int aligned_width = ((avctx->width + 47) / 48) * 48;
     int stride = aligned_width * 8 / 3;
     int line_padding = stride - ((avctx->width * 8 + 11) / 12) * 4;
     int h, w, ret;
-    const uint16_t *y = (const uint16_t*)pic->data[0];
-    const uint16_t *u = (const uint16_t*)pic->data[1];
-    const uint16_t *v = (const uint16_t*)pic->data[2];
-    PutByteContext p;
+    uint8_t *dst;
 
-    if ((ret = ff_alloc_packet2(avctx, pkt, avctx->height * stride)) < 0)
+    if ((ret = ff_alloc_packet(pkt, avctx->height * stride)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n");
         return ret;
+    }
 
-    bytestream2_init_writer(&p, pkt->data, pkt->size);
+    dst = pkt->data;
 
-#define CLIP(v) av_clip(v, 4, 1019)
+    if (pic->format == AV_PIX_FMT_YUV422P10) {
+        const uint16_t *y = (const uint16_t*)pic->data[0];
+        const uint16_t *u = (const uint16_t*)pic->data[1];
+        const uint16_t *v = (const uint16_t*)pic->data[2];
+        for (h = 0; h < avctx->height; h++) {
+            uint32_t val;
+            w = (avctx->width / 6) * 6;
+            s->pack_line_10(y, u, v, dst, w);
 
-#define WRITE_PIXELS(a, b, c)           \
-    do {                                \
-        val =   CLIP(*a++);             \
-        val |= (CLIP(*b++) << 10) |     \
-               (CLIP(*c++) << 20);      \
-        bytestream2_put_le32u(&p, val); \
-    } while (0)
+            y += w;
+            u += w >> 1;
+            v += w >> 1;
+            dst += (w / 6) * 16;
+            if (w < avctx->width - 1) {
+                WRITE_PIXELS(u, y, v);
 
-    for (h = 0; h < avctx->height; h++) {
-        uint32_t val;
-        for (w = 0; w < avctx->width - 5; w += 6) {
-            WRITE_PIXELS(u, y, v);
-            WRITE_PIXELS(y, u, y);
-            WRITE_PIXELS(v, y, u);
-            WRITE_PIXELS(y, v, y);
-        }
-        if (w < avctx->width - 1) {
-            WRITE_PIXELS(u, y, v);
-
-            val = CLIP(*y++);
-            if (w == avctx->width - 2)
-                bytestream2_put_le32u(&p, val);
+                val = CLIP(*y++);
+                if (w == avctx->width - 2) {
+                    AV_WL32(dst, val);
+                    dst += 4;
+                }
+            }
             if (w < avctx->width - 3) {
                 val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20);
-                bytestream2_put_le32u(&p, val);
+                AV_WL32(dst, val);
+                dst += 4;
 
                 val = CLIP(*v++) | (CLIP(*y++) << 10);
-                bytestream2_put_le32u(&p, val);
+                AV_WL32(dst, val);
+                dst += 4;
             }
+
+            memset(dst, 0, line_padding);
+            dst += line_padding;
+
+            y += pic->linesize[0] / 2 - avctx->width;
+            u += pic->linesize[1] / 2 - avctx->width / 2;
+            v += pic->linesize[2] / 2 - avctx->width / 2;
         }
+    }
+    else if(pic->format == AV_PIX_FMT_YUV422P) {
+        const uint8_t *y = pic->data[0];
+        const uint8_t *u = pic->data[1];
+        const uint8_t *v = pic->data[2];
+        for (h = 0; h < avctx->height; h++) {
+            uint32_t val;
+            w = (avctx->width / 12) * 12;
+            s->pack_line_8(y, u, v, dst, w);
 
-        bytestream2_set_buffer(&p, 0, line_padding);
+            y += w;
+            u += w >> 1;
+            v += w >> 1;
+            dst += (w / 12) * 32;
 
-        y += pic->linesize[0] / 2 - avctx->width;
-        u += pic->linesize[1] / 2 - avctx->width / 2;
-        v += pic->linesize[2] / 2 - avctx->width / 2;
+            for( ; w < avctx->width-5; w += 6 ){
+                WRITE_PIXELS8(u, y, v);
+                WRITE_PIXELS8(y, u, y);
+                WRITE_PIXELS8(v, y, u);
+                WRITE_PIXELS8(y, v, y);
+            }
+            if (w < avctx->width - 1) {
+                WRITE_PIXELS8(u, y, v);
+
+                val = CLIP8(*y++) << 2;
+                if (w == avctx->width - 2) {
+                    AV_WL32(dst, val);
+                    dst += 4;
+                }
+            }
+            if (w < avctx->width - 3) {
+                val |= (CLIP8(*u++) << 12) | (CLIP8(*y++) << 22);
+                AV_WL32(dst, val);
+                dst += 4;
+
+                val = (CLIP8(*v++) << 2) | (CLIP8(*y++) << 12);
+                AV_WL32(dst, val);
+                dst += 4;
+            }
+
+            memset(dst, 0, line_padding);
+            dst += line_padding;
+
+            y += pic->linesize[0] - avctx->width;
+            u += pic->linesize[1] - avctx->width / 2;
+            v += pic->linesize[2] - avctx->width / 2;
+        }
     }
 
     pkt->flags |= AV_PKT_FLAG_KEY;
@@ -119,8 +227,9 @@
     .long_name      = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_V210,
+    .priv_data_size = sizeof(V210EncContext),
     .init           = encode_init,
     .encode2        = encode_frame,
     .close          = encode_close,
-    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE },
+    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE },
 };
diff --git a/libavcodec/v210enc.h b/libavcodec/v210enc.h
new file mode 100644
index 0000000..ea6ae41
--- /dev/null
+++ b/libavcodec/v210enc.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCOENC_V210ENC_H
+#define AVCOENC_V210ENC_H
+
+#include "libavutil/log.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixfmt.h"
+
+typedef struct {
+    void (*pack_line_8)(const uint8_t *y, const uint8_t *u, const uint8_t *v, uint8_t *dst, ptrdiff_t width);
+    void (*pack_line_10)(const uint16_t *y, const uint16_t *u, const uint16_t *v, uint8_t *dst, ptrdiff_t width);
+} V210EncContext;
+
+void ff_v210enc_init_x86(V210EncContext *s);
+
+#endif /* AVCOENC_V210ENC_H */
diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c
index 6f84228..aa62ec2 100644
--- a/libavcodec/vc1_block.c
+++ b/libavcodec/vc1_block.c
@@ -1635,11 +1635,9 @@
                 s->current_picture.motion_val[1][s->block_index[i]][0] = 0;
                 s->current_picture.motion_val[1][s->block_index[i]][1] = 0;
             }
-            s->current_picture.mb_type[mb_pos]                     = MB_TYPE_INTRA;
-            s->mb_intra = 1;
-            v->is_intra[s->mb_x] = 0x3F;
-            for (i = 0; i < 6; i++)
-                v->mb_type[0][s->block_index[i]] = 1;
+            v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1.
+            s->mb_intra          = 1;
+            s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA;
             fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb);
             mb_has_coeffs = get_bits1(gb);
             if (mb_has_coeffs)
@@ -1652,11 +1650,11 @@
             s->c_dc_scale = s->c_dc_scale_table[mquant];
             dst_idx = 0;
             for (i = 0; i < 6; i++) {
-                s->dc_val[0][s->block_index[i]] = 0;
+                v->a_avail = v->c_avail          = 0;
+                v->mb_type[0][s->block_index[i]] = 1;
+                s->dc_val[0][s->block_index[i]]  = 0;
                 dst_idx += i >> 2;
                 val = ((cbp >> (5 - i)) & 1);
-                v->mb_type[0][s->block_index[i]] = s->mb_intra;
-                v->a_avail = v->c_avail = 0;
                 if (i == 2 || i == 3 || !s->first_slice_line)
                     v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]];
                 if (i == 1 || i == 3 || s->mb_x)
@@ -1806,8 +1804,8 @@
 
     idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2);
     if (idx_mbmode <= 1) { // intra MB
-        s->mb_intra = 1;
-        v->is_intra[s->mb_x] = 0x3F;
+        v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1.
+        s->mb_intra          = 1;
         s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0;
         s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0;
         s->current_picture.mb_type[mb_pos + v->mb_off] = MB_TYPE_INTRA;
@@ -1822,11 +1820,11 @@
             cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2);
         dst_idx = 0;
         for (i = 0; i < 6; i++) {
-            s->dc_val[0][s->block_index[i]]  = 0;
+            v->a_avail = v->c_avail          = 0;
             v->mb_type[0][s->block_index[i]] = 1;
+            s->dc_val[0][s->block_index[i]]  = 0;
             dst_idx += i >> 2;
             val = ((cbp >> (5 - i)) & 1);
-            v->a_avail = v->c_avail = 0;
             if (i == 2 || i == 3 || !s->first_slice_line)
                 v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]];
             if (i == 1 || i == 3 || s->mb_x)
@@ -2084,8 +2082,8 @@
 
     idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2);
     if (idx_mbmode <= 1) { // intra MB
-        s->mb_intra = 1;
-        v->is_intra[s->mb_x] = 0x3F;
+        v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1.
+        s->mb_intra          = 1;
         s->current_picture.motion_val[1][s->block_index[0]][0] = 0;
         s->current_picture.motion_val[1][s->block_index[0]][1] = 0;
         s->current_picture.mb_type[mb_pos + v->mb_off]         = MB_TYPE_INTRA;
@@ -2100,11 +2098,11 @@
             cbp = 1 + get_vlc2(&v->s.gb, v->cbpcy_vlc->table, VC1_ICBPCY_VLC_BITS, 2);
         dst_idx = 0;
         for (i = 0; i < 6; i++) {
-            s->dc_val[0][s->block_index[i]] = 0;
+            v->a_avail = v->c_avail          = 0;
+            v->mb_type[0][s->block_index[i]] = 1;
+            s->dc_val[0][s->block_index[i]]  = 0;
             dst_idx += i >> 2;
             val = ((cbp >> (5 - i)) & 1);
-            v->mb_type[0][s->block_index[i]] = s->mb_intra;
-            v->a_avail                       = v->c_avail = 0;
             if (i == 2 || i == 3 || !s->first_slice_line)
                 v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]];
             if (i == 1 || i == 3 || s->mb_x)
@@ -2310,11 +2308,9 @@
             s->mv[1][i][0] = s->current_picture.motion_val[1][s->block_index[i]][0] = 0;
             s->mv[1][i][1] = s->current_picture.motion_val[1][s->block_index[i]][1] = 0;
         }
+        v->is_intra[s->mb_x] = 0x3f; // Set the bitfield to all 1.
+        s->mb_intra          = 1;
         s->current_picture.mb_type[mb_pos] = MB_TYPE_INTRA;
-        s->mb_intra = 1;
-        v->is_intra[s->mb_x] = 0x3F;
-        for (i = 0; i < 6; i++)
-            v->mb_type[0][s->block_index[i]] = 1;
         fieldtx = v->fieldtx_plane[mb_pos] = get_bits1(gb);
         mb_has_coeffs = get_bits1(gb);
         if (mb_has_coeffs)
@@ -2327,11 +2323,11 @@
         s->c_dc_scale = s->c_dc_scale_table[mquant];
         dst_idx = 0;
         for (i = 0; i < 6; i++) {
-            s->dc_val[0][s->block_index[i]] = 0;
+            v->a_avail = v->c_avail          = 0;
+            v->mb_type[0][s->block_index[i]] = 1;
+            s->dc_val[0][s->block_index[i]]  = 0;
             dst_idx += i >> 2;
             val = ((cbp >> (5 - i)) & 1);
-            v->mb_type[0][s->block_index[i]] = s->mb_intra;
-            v->a_avail = v->c_avail = 0;
             if (i == 2 || i == 3 || !s->first_slice_line)
                 v->a_avail = v->mb_type[0][s->block_index[i] - s->block_wrap[i]];
             if (i == 1 || i == 3 || s->mb_x)
diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c
index 3379932..09e8fac 100644
--- a/libavcodec/vc1_mc.c
+++ b/libavcodec/vc1_mc.c
@@ -802,11 +802,9 @@
     my   = s->mv[1][0][1];
     uvmx = (mx + ((mx & 3) == 3)) >> 1;
     uvmy = (my + ((my & 3) == 3)) >> 1;
-    if (v->field_mode) {
-        if (v->cur_field_type != v->ref_field_type[1]) {
-            my   = my   - 2 + 4 * v->cur_field_type;
-            uvmy = uvmy - 2 + 4 * v->cur_field_type;
-        }
+    if (v->field_mode && v->cur_field_type != v->ref_field_type[1]) {
+        my   = my   - 2 + 4 * v->cur_field_type;
+        uvmy = uvmy - 2 + 4 * v->cur_field_type;
     }
     if (v->fastuvmc) {
         uvmx = uvmx + ((uvmx < 0) ? -(uvmx & 1) : (uvmx & 1));
diff --git a/libavcodec/vc1_pred.c b/libavcodec/vc1_pred.c
index cf1dce6..d0908ef 100644
--- a/libavcodec/vc1_pred.c
+++ b/libavcodec/vc1_pred.c
@@ -648,7 +648,7 @@
                     av_assert1(c_valid);
                     px = C[0];
                     py = C[1];
-                } /*else px = py = 0;*/
+                }
             } else {
                 if (field_a && a_valid) {
                     px = A[0];
@@ -657,10 +657,7 @@
                     av_assert1(field_b && b_valid);
                     px = B[0];
                     py = B[1];
-                } /*else if (c_valid) {
-                    px = C[0];
-                    py = C[1];
-                }*/
+                }
             }
         } else if (total_valid == 1) {
             px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index d686ef4..1006779 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -157,7 +157,7 @@
  * display preemption).
  *
  * @note get_format() must return AV_PIX_FMT_VDPAU if this function completes
- * succesfully.
+ * successfully.
  *
  * @param avctx decoding context whose get_format() callback is invoked
  * @param device VDPAU device handle to use for hardware acceleration
diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c
index 2a036b6..9141bec 100644
--- a/libavcodec/vdpau_mpeg4.c
+++ b/libavcodec/vdpau_mpeg4.c
@@ -119,6 +119,9 @@
     case FF_PROFILE_MPEG4_SIMPLE:
         profile = VDP_DECODER_PROFILE_MPEG4_PART2_SP;
         break;
+    // As any ASP decoder must be able to decode SP, this
+    // should be a safe fallback if profile is unknown/unspecified.
+    case FF_PROFILE_UNKNOWN:
     case FF_PROFILE_MPEG4_ADVANCED_SIMPLE:
         profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP;
         break;
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 98ed869..23443ed 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 56
-#define LIBAVCODEC_VERSION_MINOR  10
+#define LIBAVCODEC_VERSION_MINOR  13
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavcodec/vorbis_parser.c b/libavcodec/vorbis_parser.c
index 1e2cab3..b99f115 100644
--- a/libavcodec/vorbis_parser.c
+++ b/libavcodec/vorbis_parser.c
@@ -25,34 +25,42 @@
  * Determines the duration for each packet.
  */
 
+#include "libavutil/log.h"
+
 #include "get_bits.h"
 #include "parser.h"
 #include "xiph.h"
-#include "vorbis_parser.h"
+#include "vorbis_parser_internal.h"
 
-static int parse_id_header(AVCodecContext *avctx, VorbisParseContext *s,
+static const AVClass vorbis_parser_class = {
+    .class_name = "Vorbis parser",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+static int parse_id_header(AVVorbisParseContext *s,
                            const uint8_t *buf, int buf_size)
 {
     /* Id header should be 30 bytes */
     if (buf_size < 30) {
-        av_log(avctx, AV_LOG_ERROR, "Id header is too short\n");
+        av_log(s, AV_LOG_ERROR, "Id header is too short\n");
         return AVERROR_INVALIDDATA;
     }
 
     /* make sure this is the Id header */
     if (buf[0] != 1) {
-        av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Id header\n");
+        av_log(s, AV_LOG_ERROR, "Wrong packet type in Id header\n");
         return AVERROR_INVALIDDATA;
     }
 
     /* check for header signature */
     if (memcmp(&buf[1], "vorbis", 6)) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Id header\n");
+        av_log(s, AV_LOG_ERROR, "Invalid packet signature in Id header\n");
         return AVERROR_INVALIDDATA;
     }
 
     if (!(buf[29] & 0x1)) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid framing bit in Id header\n");
+        av_log(s, AV_LOG_ERROR, "Invalid framing bit in Id header\n");
         return AVERROR_INVALIDDATA;
     }
 
@@ -62,7 +70,7 @@
     return 0;
 }
 
-static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s,
+static int parse_setup_header(AVVorbisParseContext *s,
                               const uint8_t *buf, int buf_size)
 {
     GetBitContext gb, gb0;
@@ -72,25 +80,25 @@
 
     /* avoid overread */
     if (buf_size < 7) {
-        av_log(avctx, AV_LOG_ERROR, "Setup header is too short\n");
+        av_log(s, AV_LOG_ERROR, "Setup header is too short\n");
         return AVERROR_INVALIDDATA;
     }
 
     /* make sure this is the Setup header */
     if (buf[0] != 5) {
-        av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Setup header\n");
+        av_log(s, AV_LOG_ERROR, "Wrong packet type in Setup header\n");
         return AVERROR_INVALIDDATA;
     }
 
     /* check for header signature */
     if (memcmp(&buf[1], "vorbis", 6)) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Setup header\n");
+        av_log(s, AV_LOG_ERROR, "Invalid packet signature in Setup header\n");
         return AVERROR_INVALIDDATA;
     }
 
     /* reverse bytes so we can easily read backwards with get_bits() */
     if (!(rev_buf = av_malloc(buf_size))) {
-        av_log(avctx, AV_LOG_ERROR, "Out of memory\n");
+        av_log(s, AV_LOG_ERROR, "Out of memory\n");
         return AVERROR(ENOMEM);
     }
     for (i = 0; i < buf_size; i++)
@@ -105,7 +113,7 @@
         }
     }
     if (!got_framing_bit) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n");
+        av_log(s, AV_LOG_ERROR, "Invalid Setup header\n");
         ret = AVERROR_INVALIDDATA;
         goto bad_header;
     }
@@ -132,7 +140,7 @@
         }
     }
     if (!got_mode_header) {
-        av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n");
+        av_log(s, AV_LOG_ERROR, "Invalid Setup header\n");
         ret = AVERROR_INVALIDDATA;
         goto bad_header;
     }
@@ -141,7 +149,7 @@
      * we may need to approach this the long way and parse the whole Setup
      * header, but I hope very much that it never comes to that. */
     if (last_mode_count > 2) {
-        avpriv_request_sample(avctx,
+        avpriv_request_sample(s,
                               "%d modes (either a false positive or a "
                               "sample from an unknown encoder)",
                               last_mode_count);
@@ -149,7 +157,7 @@
     /* We're limiting the mode count to 63 so that we know that the previous
      * block flag will be in the first packet byte. */
     if (last_mode_count > 63) {
-        av_log(avctx, AV_LOG_ERROR, "Unsupported mode count: %d\n",
+        av_log(s, AV_LOG_ERROR, "Unsupported mode count: %d\n",
                last_mode_count);
         ret = AVERROR_INVALIDDATA;
         goto bad_header;
@@ -173,26 +181,27 @@
     return ret;
 }
 
-int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s)
+static int vorbis_parse_init(AVVorbisParseContext *s,
+                             const uint8_t *extradata, int extradata_size)
 {
     uint8_t *header_start[3];
     int header_len[3];
     int ret;
 
-    s->avctx = avctx;
+    s->class = &vorbis_parser_class;
     s->extradata_parsed = 1;
 
-    if ((ret = avpriv_split_xiph_headers(avctx->extradata,
-                                         avctx->extradata_size, 30,
+    if ((ret = avpriv_split_xiph_headers(extradata,
+                                         extradata_size, 30,
                                          header_start, header_len)) < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Extradata corrupt.\n");
+        av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n");
         return ret;
     }
 
-    if ((ret = parse_id_header(avctx, s, header_start[0], header_len[0])) < 0)
+    if ((ret = parse_id_header(s, header_start[0], header_len[0])) < 0)
         return ret;
 
-    if ((ret = parse_setup_header(avctx, s, header_start[2], header_len[2])) < 0)
+    if ((ret = parse_setup_header(s, header_start[2], header_len[2])) < 0)
         return ret;
 
     s->valid_extradata = 1;
@@ -201,8 +210,8 @@
     return 0;
 }
 
-int avpriv_vorbis_parse_frame_flags(VorbisParseContext *s, const uint8_t *buf,
-                                    int buf_size, int *flags)
+int av_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf,
+                                int buf_size, int *flags)
 {
     int duration = 0;
 
@@ -227,7 +236,7 @@
             return 0;
 
 bad_packet:
-            av_log(s->avctx, AV_LOG_ERROR, "Invalid packet\n");
+            av_log(s, AV_LOG_ERROR, "Invalid packet\n");
             return AVERROR_INVALIDDATA;
         }
         if (s->mode_count == 1)
@@ -235,7 +244,7 @@
         else
             mode = (buf[0] & s->mode_mask) >> 1;
         if (mode >= s->mode_count) {
-            av_log(s->avctx, AV_LOG_ERROR, "Invalid mode in packet\n");
+            av_log(s, AV_LOG_ERROR, "Invalid mode in packet\n");
             return AVERROR_INVALIDDATA;
         }
         if(s->mode_blocksize[mode]){
@@ -250,19 +259,68 @@
     return duration;
 }
 
-int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf,
-                              int buf_size)
+int av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf,
+                          int buf_size)
 {
-    return avpriv_vorbis_parse_frame_flags(s, buf, buf_size, NULL);
+    return av_vorbis_parse_frame_flags(s, buf, buf_size, NULL);
 }
 
-void avpriv_vorbis_parse_reset(VorbisParseContext *s)
+void av_vorbis_parse_reset(AVVorbisParseContext *s)
 {
     if (s->valid_extradata)
         s->previous_blocksize = s->blocksize[0];
 }
 
+void av_vorbis_parse_free(AVVorbisParseContext **s)
+{
+    av_freep(s);
+}
+
+AVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata,
+                                           int extradata_size)
+{
+    AVVorbisParseContext *s = av_mallocz(sizeof(*s));
+    int ret;
+
+    if (!s)
+        return NULL;
+
+    ret = vorbis_parse_init(s, extradata, extradata_size);
+    if (ret < 0) {
+        av_vorbis_parse_free(&s);
+        return NULL;
+    }
+
+    return s;
+}
+
+#if LIBAVCODEC_VERSION_MAJOR < 57
+int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, AVVorbisParseContext *s)
+{
+    return vorbis_parse_init(s, avctx->extradata, avctx->extradata_size);
+}
+void avpriv_vorbis_parse_reset(AVVorbisParseContext *s)
+{
+    av_vorbis_parse_reset(s);
+}
+int avpriv_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf,
+                              int buf_size)
+{
+    return av_vorbis_parse_frame(s, buf, buf_size);
+}
+int avpriv_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf,
+                                    int buf_size, int *flags)
+{
+    return av_vorbis_parse_frame_flags(s, buf, buf_size, flags);
+}
+#endif
+
 #if CONFIG_VORBIS_PARSER
+
+typedef struct VorbisParseContext {
+    AVVorbisParseContext *vp;
+} VorbisParseContext;
+
 static int vorbis_parse(AVCodecParserContext *s1, AVCodecContext *avctx,
                         const uint8_t **poutbuf, int *poutbuf_size,
                         const uint8_t *buf, int buf_size)
@@ -270,11 +328,13 @@
     VorbisParseContext *s = s1->priv_data;
     int duration;
 
-    if (!s->extradata_parsed && avctx->extradata && avctx->extradata_size)
-        if (avpriv_vorbis_parse_extradata(avctx, s))
-            goto end;
+    if (!s->vp && avctx->extradata && avctx->extradata_size) {
+        s->vp = av_vorbis_parse_init(avctx->extradata, avctx->extradata_size);
+    }
+    if (!s->vp)
+        goto end;
 
-    if ((duration = avpriv_vorbis_parse_frame(s, buf, buf_size)) >= 0)
+    if ((duration = av_vorbis_parse_frame(s->vp, buf, buf_size)) >= 0)
         s1->duration = duration;
 
 end:
@@ -285,9 +345,16 @@
     return buf_size;
 }
 
+static void vorbis_parser_close(AVCodecParserContext *ctx)
+{
+    VorbisParseContext *s = ctx->priv_data;
+    av_vorbis_parse_free(&s->vp);
+}
+
 AVCodecParser ff_vorbis_parser = {
     .codec_ids      = { AV_CODEC_ID_VORBIS },
     .priv_data_size = sizeof(VorbisParseContext),
     .parser_parse   = vorbis_parse,
+    .parser_close   = vorbis_parser_close,
 };
 #endif /* CONFIG_VORBIS_PARSER */
diff --git a/libavcodec/vorbis_parser.h b/libavcodec/vorbis_parser.h
index 590101b..0f73537 100644
--- a/libavcodec/vorbis_parser.h
+++ b/libavcodec/vorbis_parser.h
@@ -1,5 +1,4 @@
 /*
- * Copyright (c) 2012 Justin Ruggles
  *
  * This file is part of FFmpeg.
  *
@@ -20,35 +19,31 @@
 
 /**
  * @file
- * Vorbis audio parser
+ * A public API for Vorbis parsing
  *
  * Determines the duration for each packet.
  */
 
-#ifndef AVCODEC_VORBIS_PARSER_H
-#define AVCODEC_VORBIS_PARSER_H
+#ifndef AVCODEC_VORBIS_PARSE_H
+#define AVCODEC_VORBIS_PARSE_H
 
-#include "avcodec.h"
+#include <stdint.h>
 
-typedef struct VorbisParseContext {
-    AVCodecContext *avctx;      ///< codec context
-    int extradata_parsed;       ///< we have attempted to parse extradata
-    int valid_extradata;        ///< extradata is valid, so we can calculate duration
-    int blocksize[2];           ///< short and long window sizes
-    int previous_blocksize;     ///< previous window size
-    int mode_blocksize[64];     ///< window size mapping for each mode
-    int mode_count;             ///< number of modes
-    int mode_mask;              ///< bitmask used to get the mode in each packet
-    int prev_mask;              ///< bitmask used to get the previous mode flag in each packet
-} VorbisParseContext;
+typedef struct AVVorbisParseContext AVVorbisParseContext;
 
 /**
- * Initialize the Vorbis parser using headers in the extradata.
+ * Allocate and initialize the Vorbis parser using headers in the extradata.
  *
  * @param avctx codec context
  * @param s     Vorbis parser context
  */
-int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s);
+AVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata,
+                                           int extradata_size);
+
+/**
+ * Free the parser and everything associated with it.
+ */
+void av_vorbis_parse_free(AVVorbisParseContext **s);
 
 #define VORBIS_FLAG_HEADER  0x00000001
 #define VORBIS_FLAG_COMMENT 0x00000002
@@ -56,8 +51,7 @@
 /**
  * Get the duration for a Vorbis packet.
  *
- * avpriv_vorbis_parse_extradata() must have been successfully called prior to
- * this in order for a correct duration to be returned. If @p flags is @c NULL,
+ * If @p flags is @c NULL,
  * special frames are considered invalid.
  *
  * @param s        Vorbis parser context
@@ -65,22 +59,19 @@
  * @param buf_size size of the buffer
  * @param flags    flags for special frames
  */
-int avpriv_vorbis_parse_frame_flags(VorbisParseContext *s, const uint8_t *buf,
-                                    int buf_size, int *flags);
+int av_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf,
+                                int buf_size, int *flags);
 
 /**
  * Get the duration for a Vorbis packet.
  *
- * avpriv_vorbis_parse_extradata() must have been successfully called prior to
- * this in order for a correct duration to be returned.
- *
  * @param s        Vorbis parser context
  * @param buf      buffer containing a Vorbis frame
  * @param buf_size size of the buffer
  */
-int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf,
-                              int buf_size);
+int av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf,
+                          int buf_size);
 
-void avpriv_vorbis_parse_reset(VorbisParseContext *s);
+void av_vorbis_parse_reset(AVVorbisParseContext *s);
 
-#endif /* AVCODEC_VORBIS_PARSER_H */
+#endif /* AVCODEC_VORBIS_PARSE_H */
diff --git a/libavcodec/vorbis_parser_internal.h b/libavcodec/vorbis_parser_internal.h
new file mode 100644
index 0000000..49481ee
--- /dev/null
+++ b/libavcodec/vorbis_parser_internal.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012 Justin Ruggles
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * Vorbis audio parser
+ *
+ * Determines the duration for each packet.
+ */
+
+#ifndef AVCODEC_VORBIS_PARSER_H
+#define AVCODEC_VORBIS_PARSER_H
+
+#include "avcodec.h"
+#include "vorbis_parser.h"
+
+struct AVVorbisParseContext {
+    const AVClass *class;
+    int extradata_parsed;       ///< we have attempted to parse extradata
+    int valid_extradata;        ///< extradata is valid, so we can calculate duration
+    int blocksize[2];           ///< short and long window sizes
+    int previous_blocksize;     ///< previous window size
+    int mode_blocksize[64];     ///< window size mapping for each mode
+    int mode_count;             ///< number of modes
+    int mode_mask;              ///< bitmask used to get the mode in each packet
+    int prev_mask;              ///< bitmask used to get the previous mode flag in each packet
+};
+
+#if LIBAVCODEC_VERSION_MAJOR < 57
+/**
+ * Initialize the Vorbis parser using headers in the extradata.
+ *
+ * @param avctx codec context
+ * @param s     Vorbis parser context
+ */
+int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, AVVorbisParseContext *s);
+
+/**
+ * Get the duration for a Vorbis packet.
+ *
+ * avpriv_vorbis_parse_extradata() must have been successfully called prior to
+ * this in order for a correct duration to be returned. If @p flags is @c NULL,
+ * special frames are considered invalid.
+ *
+ * @param s        Vorbis parser context
+ * @param buf      buffer containing a Vorbis frame
+ * @param buf_size size of the buffer
+ * @param flags    flags for special frames
+ */
+int avpriv_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf,
+                                    int buf_size, int *flags);
+
+/**
+ * Get the duration for a Vorbis packet.
+ *
+ * avpriv_vorbis_parse_extradata() must have been successfully called prior to
+ * this in order for a correct duration to be returned.
+ *
+ * @param s        Vorbis parser context
+ * @param buf      buffer containing a Vorbis frame
+ * @param buf_size size of the buffer
+ */
+int avpriv_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf,
+                              int buf_size);
+
+void avpriv_vorbis_parse_reset(AVVorbisParseContext *s);
+#endif
+
+#endif /* AVCODEC_VORBIS_PARSER_H */
diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c
index 2ad5b4f..fb16099 100644
--- a/libavcodec/vorbisdec.c
+++ b/libavcodec/vorbisdec.c
@@ -127,7 +127,7 @@
     AVCodecContext *avctx;
     GetBitContext gb;
     VorbisDSPContext dsp;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     FmtConvertContext fmt_conv;
 
     FFTContext mdct[2];
@@ -193,6 +193,7 @@
 
     av_freep(&vc->channel_residues);
     av_freep(&vc->saved);
+    av_freep(&vc->fdsp);
 
     if (vc->residues)
         for (i = 0; i < vc->residue_count; i++)
@@ -992,6 +993,9 @@
 
     ff_mdct_init(&vc->mdct[0], bl0, 1, -1.0);
     ff_mdct_init(&vc->mdct[1], bl1, 1, -1.0);
+    vc->fdsp = avpriv_float_dsp_alloc(vc->avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!vc->fdsp)
+        return AVERROR(ENOMEM);
 
     av_dlog(NULL, " vorbis version %d \n audio_channels %d \n audio_samplerate %d \n bitrate_max %d \n bitrate_nom %d \n bitrate_min %d \n blk_0 %d blk_1 %d \n ",
             vc->version, vc->audio_channels, vc->audio_samplerate, vc->bitrate_maximum, vc->bitrate_nominal, vc->bitrate_minimum, vc->blocksize[0], vc->blocksize[1]);
@@ -1020,7 +1024,6 @@
 
     vc->avctx = avctx;
     ff_vorbisdsp_init(&vc->dsp);
-    avpriv_float_dsp_init(&vc->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
     ff_fmt_convert_init(&vc->fmt_conv, avctx);
 
     avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
@@ -1688,7 +1691,7 @@
 
     for (j = vc->audio_channels-1;j >= 0; j--) {
         ch_res_ptr   = vc->channel_residues + res_chan[j] * blocksize / 2;
-        vc->fdsp.vector_fmul(floor_ptr[j], floor_ptr[j], ch_res_ptr, blocksize / 2);
+        vc->fdsp->vector_fmul(floor_ptr[j], floor_ptr[j], ch_res_ptr, blocksize / 2);
         mdct->imdct_half(mdct, ch_res_ptr, floor_ptr[j]);
     }
 
@@ -1705,13 +1708,13 @@
         const float *win  = vc->win[blockflag & previous_window];
 
         if (blockflag == previous_window) {
-            vc->fdsp.vector_fmul_window(ret, saved, buf, win, blocksize / 4);
+            vc->fdsp->vector_fmul_window(ret, saved, buf, win, blocksize / 4);
         } else if (blockflag > previous_window) {
-            vc->fdsp.vector_fmul_window(ret, saved, buf, win, bs0 / 4);
+            vc->fdsp->vector_fmul_window(ret, saved, buf, win, bs0 / 4);
             memcpy(ret+bs0/2, buf+bs0/4, ((bs1-bs0)/4) * sizeof(float));
         } else {
             memcpy(ret, saved, ((bs1 - bs0) / 4) * sizeof(float));
-            vc->fdsp.vector_fmul_window(ret + (bs1 - bs0) / 4, saved + (bs1 - bs0) / 4, buf, win, bs0 / 4);
+            vc->fdsp->vector_fmul_window(ret + (bs1 - bs0) / 4, saved + (bs1 - bs0) / 4, buf, win, bs0 / 4);
         }
         memcpy(saved, buf + blocksize / 4, blocksize / 4 * sizeof(float));
     }
diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c
index 0f78d95..c06093e 100644
--- a/libavcodec/vorbisenc.c
+++ b/libavcodec/vorbisenc.c
@@ -1094,8 +1094,9 @@
     if (frame) {
         if (frame->pts != AV_NOPTS_VALUE)
             avpkt->pts = ff_samples_to_time_base(avctx, frame->pts);
-    } else
+    } else {
         avpkt->pts = venc->next_pts;
+    }
     if (avpkt->pts != AV_NOPTS_VALUE)
         venc->next_pts = avpkt->pts + avpkt->duration;
 
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index a18b8ff..e97ef76 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -651,7 +651,7 @@
     if (s->alpha_context) {
         ff_vp56_free_context(s->alpha_context);
         vp6_decode_free_context(s->alpha_context);
-        av_free(s->alpha_context);
+        av_freep(&s->alpha_context);
     }
 
     return 0;
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 9cc57dc..024280b 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -1916,8 +1916,8 @@
                          mb->bmv[2 * y       * 4 + 2 * x + 1].y +
                          mb->bmv[(2 * y + 1) * 4 + 2 * x    ].y +
                          mb->bmv[(2 * y + 1) * 4 + 2 * x + 1].y;
-                uvmv.x = (uvmv.x + 2 + (uvmv.x >> (INT_BIT - 1))) >> 2;
-                uvmv.y = (uvmv.y + 2 + (uvmv.y >> (INT_BIT - 1))) >> 2;
+                uvmv.x = (uvmv.x + 2 + FF_SIGNBIT(uvmv.x)) >> 2;
+                uvmv.y = (uvmv.y + 2 + FF_SIGNBIT(uvmv.y)) >> 2;
                 if (s->profile == 3) {
                     uvmv.x &= ~7;
                     uvmv.y &= ~7;
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 7b7deb3..07df9ef 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -145,6 +145,7 @@
     uint8_t yac_qi;
     int8_t ydc_qdelta, uvdc_qdelta, uvac_qdelta;
     uint8_t lossless;
+#define MAX_SEGMENT 8
     struct {
         uint8_t enabled;
         uint8_t temporal;
@@ -160,7 +161,7 @@
             int8_t lf_val;
             int16_t qmul[2][2];
             uint8_t lflvl[4][2];
-        } feat[8];
+        } feat[MAX_SEGMENT];
     } segmentation;
     struct {
         unsigned log2_tile_cols, log2_tile_rows;
diff --git a/libavcodec/wma.c b/libavcodec/wma.c
index ecc7e41..51fda3f 100644
--- a/libavcodec/wma.c
+++ b/libavcodec/wma.c
@@ -86,7 +86,6 @@
         return -1;
 
     ff_fmt_convert_init(&s->fmt_conv, avctx);
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
 
     if (avctx->codec->id == AV_CODEC_ID_WMAV1)
         s->version = 1;
@@ -333,6 +332,10 @@
 #endif /* TRACE */
     }
 
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
+
     /* choose the VLC tables for the coefficients */
     coef_vlc_table = 2;
     if (avctx->sample_rate >= 32000) {
@@ -383,6 +386,7 @@
         av_freep(&s->level_table[i]);
         av_freep(&s->int_table[i]);
     }
+    av_freep(&s->fdsp);
 
     return 0;
 }
diff --git a/libavcodec/wma.h b/libavcodec/wma.h
index 6e5198a..a232b8a 100644
--- a/libavcodec/wma.h
+++ b/libavcodec/wma.h
@@ -132,7 +132,7 @@
     float lsp_pow_m_table1[(1 << LSP_POW_BITS)];
     float lsp_pow_m_table2[(1 << LSP_POW_BITS)];
     FmtConvertContext fmt_conv;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
 
 #ifdef TRACE
     int frame_count;
diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c
index 6c3f28f..d32ca6f 100644
--- a/libavcodec/wmadec.c
+++ b/libavcodec/wmadec.c
@@ -390,14 +390,14 @@
         block_len = s->block_len;
         bsize     = s->frame_len_bits - s->block_len_bits;
 
-        s->fdsp.vector_fmul_add(out, in, s->windows[bsize],
+        s->fdsp->vector_fmul_add(out, in, s->windows[bsize],
                                 out, block_len);
     } else {
         block_len = 1 << s->prev_block_len_bits;
         n         = (s->block_len - block_len) / 2;
         bsize     = s->frame_len_bits - s->prev_block_len_bits;
 
-        s->fdsp.vector_fmul_add(out + n, in + n, s->windows[bsize],
+        s->fdsp->vector_fmul_add(out + n, in + n, s->windows[bsize],
                                 out + n, block_len);
 
         memcpy(out + n + block_len, in + n + block_len, n * sizeof(float));
@@ -411,7 +411,7 @@
         block_len = s->block_len;
         bsize     = s->frame_len_bits - s->block_len_bits;
 
-        s->fdsp.vector_fmul_reverse(out, in, s->windows[bsize], block_len);
+        s->fdsp->vector_fmul_reverse(out, in, s->windows[bsize], block_len);
     } else {
         block_len = 1 << s->next_block_len_bits;
         n         = (s->block_len - block_len) / 2;
@@ -419,7 +419,7 @@
 
         memcpy(out, in, n * sizeof(float));
 
-        s->fdsp.vector_fmul_reverse(out + n, in + n, s->windows[bsize],
+        s->fdsp->vector_fmul_reverse(out + n, in + n, s->windows[bsize],
                                     block_len);
 
         memset(out + n + block_len, 0, n * sizeof(float));
@@ -738,7 +738,7 @@
             s->channel_coded[0] = 1;
         }
 
-        s->fdsp.butterflies_float(s->coefs[0], s->coefs[1], s->block_len);
+        s->fdsp->butterflies_float(s->coefs[0], s->coefs[1], s->block_len);
     }
 
 next:
diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c
index 6337779..08d45e9 100644
--- a/libavcodec/wmaenc.c
+++ b/libavcodec/wmaenc.c
@@ -107,10 +107,10 @@
 
     for (ch = 0; ch < avctx->channels; ch++) {
         memcpy(s->output, s->frame_out[ch], window_len * sizeof(*s->output));
-        s->fdsp.vector_fmul_scalar(s->frame_out[ch], audio[ch], n, len);
-        s->fdsp.vector_fmul_reverse(&s->output[window_len], s->frame_out[ch],
+        s->fdsp->vector_fmul_scalar(s->frame_out[ch], audio[ch], n, len);
+        s->fdsp->vector_fmul_reverse(&s->output[window_len], s->frame_out[ch],
                                     win, len);
-        s->fdsp.vector_fmul(s->frame_out[ch], s->frame_out[ch], win, len);
+        s->fdsp->vector_fmul(s->frame_out[ch], s->frame_out[ch], win, len);
         mdct->mdct_calc(mdct, s->coefs[ch], s->output);
     }
 }
diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c
index 8e2ac5f..e6e3476 100644
--- a/libavcodec/wmalosslessdec.c
+++ b/libavcodec/wmalosslessdec.c
@@ -200,8 +200,7 @@
             avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
         else if (s->bits_per_sample == 24) {
             avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
-            avpriv_report_missing_feature(avctx, "Bit-depth higher than 16");
-            return AVERROR_PATCHWELCOME;
+            avctx->bits_per_raw_sample = 24;
         } else {
             av_log(avctx, AV_LOG_ERROR, "Unknown bit-depth: %"PRIu8"\n",
                    s->bits_per_sample);
@@ -997,7 +996,7 @@
             if (s->bits_per_sample == 16) {
                 *s->samples_16[c]++ = (int16_t) s->channel_residues[c][j] << padding_zeroes;
             } else {
-                *s->samples_32[c]++ = s->channel_residues[c][j] << padding_zeroes;
+                *s->samples_32[c]++ = s->channel_residues[c][j] << (padding_zeroes + 8);
             }
         }
     }
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c
index f45e1fc..cc7ad0d 100644
--- a/libavcodec/wmaprodec.c
+++ b/libavcodec/wmaprodec.c
@@ -171,7 +171,7 @@
 typedef struct WMAProDecodeCtx {
     /* generic decoder variables */
     AVCodecContext*  avctx;                         ///< codec context for av_log
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     uint8_t          frame_data[MAX_FRAMESIZE +
                       FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data
     PutBitContext    pb;                            ///< context for filling the frame_data buffer
@@ -260,6 +260,8 @@
     WMAProDecodeCtx *s = avctx->priv_data;
     int i;
 
+    av_freep(&s->fdsp);
+
     for (i = 0; i < WMAPRO_BLOCK_SIZES; i++)
         ff_mdct_end(&s->mdct_ctx[i]);
 
@@ -286,7 +288,9 @@
     }
 
     s->avctx = avctx;
-    avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
+    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
 
     init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
 
@@ -422,6 +426,9 @@
             offset &= ~3;
             if (offset > s->sfb_offsets[i][band - 1])
                 s->sfb_offsets[i][band++] = offset;
+
+            if (offset >= subframe_len)
+                break;
         }
         s->sfb_offsets[i][band - 1] = subframe_len;
         s->num_sfb[i]               = band - 1;
@@ -1034,10 +1041,10 @@
                     }
                 } else if (s->avctx->channels == 2) {
                     int len = FFMIN(sfb[1], s->subframe_len) - sfb[0];
-                    s->fdsp.vector_fmul_scalar(ch_data[0] + sfb[0],
+                    s->fdsp->vector_fmul_scalar(ch_data[0] + sfb[0],
                                                ch_data[0] + sfb[0],
                                                181.0 / 128, len);
-                    s->fdsp.vector_fmul_scalar(ch_data[1] + sfb[0],
+                    s->fdsp->vector_fmul_scalar(ch_data[1] + sfb[0],
                                                ch_data[1] + sfb[0],
                                                181.0 / 128, len);
                 }
@@ -1068,7 +1075,7 @@
 
         winlen >>= 1;
 
-        s->fdsp.vector_fmul_window(start, start, start + winlen,
+        s->fdsp->vector_fmul_window(start, start, start + winlen,
                                    window, winlen);
 
         s->channel[c].prev_block_len = s->subframe_len;
@@ -1288,7 +1295,7 @@
                             s->channel[c].scale_factor_step;
                 const float quant = pow(10.0, exp / 20.0);
                 int start = s->cur_sfb_offsets[b];
-                s->fdsp.vector_fmul_scalar(s->tmp + start,
+                s->fdsp->vector_fmul_scalar(s->tmp + start,
                                            s->channel[c].coeffs + start,
                                            quant, end - start);
             }
diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile
index 2fa56b9..7c8e7aa 100644
--- a/libavcodec/x86/Makefile
+++ b/libavcodec/x86/Makefile
@@ -37,6 +37,7 @@
 
 # decoders/encoders
 OBJS-$(CONFIG_AAC_DECODER)             += x86/sbrdsp_init.o
+OBJS-$(CONFIG_APNG_DECODER)            += x86/pngdsp_init.o
 OBJS-$(CONFIG_CAVS_DECODER)            += x86/cavsdsp.o
 OBJS-$(CONFIG_DCA_DECODER)             += x86/dcadsp_init.o
 OBJS-$(CONFIG_DNXHD_ENCODER)           += x86/dnxhdenc_init.o
@@ -50,9 +51,10 @@
 OBJS-$(CONFIG_RV40_DECODER)            += x86/rv34dsp_init.o            \
                                           x86/rv40dsp_init.o
 OBJS-$(CONFIG_SVQ1_ENCODER)            += x86/svq1enc_init.o
-OBJS-$(CONFIG_V210_DECODER)            += x86/v210-init.o
-OBJS-$(CONFIG_TTA_DECODER)             += x86/ttadsp_init.o
 OBJS-$(CONFIG_TRUEHD_DECODER)          += x86/mlpdsp_init.o
+OBJS-$(CONFIG_TTA_DECODER)             += x86/ttadsp_init.o
+OBJS-$(CONFIG_V210_DECODER)            += x86/v210-init.o
+OBJS-$(CONFIG_V210_ENCODER)            += x86/v210enc_init.o
 OBJS-$(CONFIG_VC1_DECODER)             += x86/vc1dsp_init.o
 OBJS-$(CONFIG_VORBIS_DECODER)          += x86/vorbisdsp_init.o
 OBJS-$(CONFIG_VP6_DECODER)             += x86/vp6dsp_init.o
@@ -127,6 +129,7 @@
 
 # decoders/encoders
 YASM-OBJS-$(CONFIG_AAC_DECODER)        += x86/sbrdsp.o
+YASM-OBJS-$(CONFIG_APNG_DECODER)       += x86/pngdsp.o
 YASM-OBJS-$(CONFIG_DCA_DECODER)        += x86/dcadsp.o
 YASM-OBJS-$(CONFIG_HEVC_DECODER)       += x86/hevc_mc.o                 \
                                           x86/hevc_deblock.o            \
@@ -142,6 +145,7 @@
 YASM-OBJS-$(CONFIG_SVQ1_ENCODER)       += x86/svq1enc.o
 YASM-OBJS-$(CONFIG_TRUEHD_DECODER)     += x86/mlpdsp.o
 YASM-OBJS-$(CONFIG_TTA_DECODER)        += x86/ttadsp.o
+YASM-OBJS-$(CONFIG_V210_ENCODER)       += x86/v210enc.o
 YASM-OBJS-$(CONFIG_V210_DECODER)       += x86/v210.o
 YASM-OBJS-$(CONFIG_VC1_DECODER)        += x86/vc1dsp.o
 YASM-OBJS-$(CONFIG_VORBIS_DECODER)     += x86/vorbisdsp.o
diff --git a/libavcodec/x86/flacdsp.asm b/libavcodec/x86/flacdsp.asm
index 37ee87b..d60a6e4 100644
--- a/libavcodec/x86/flacdsp.asm
+++ b/libavcodec/x86/flacdsp.asm
@@ -2,6 +2,7 @@
 ;* FLAC DSP SIMD optimizations
 ;*
 ;* Copyright (C) 2014 Loren Merritt
+;* Copyright (C) 2014 James Almer
 ;*
 ;* This file is part of FFmpeg.
 ;*
@@ -72,3 +73,257 @@
 LPC_32 xop
 %endif
 LPC_32 sse4
+
+;----------------------------------------------------------------------------------
+;void ff_flac_decorrelate_[lrm]s_16_sse2(uint8_t **out, int32_t **in, int channels,
+;                                                   int len, int shift);
+;----------------------------------------------------------------------------------
+%macro FLAC_DECORRELATE_16 3-4
+cglobal flac_decorrelate_%1_16, 2, 4, 4, out, in0, in1, len
+%if ARCH_X86_32 || WIN64
+    movd       m3, r4m
+%if ARCH_X86_32
+    mov      lend, lenm
+%endif
+%else ; UNIX64
+    movd       m3, r4d
+%endif
+    shl      lend, 2
+    mov      in1q, [in0q + gprsize]
+    mov      in0q, [in0q]
+    mov      outq, [outq]
+    add      in1q, lenq
+    add      in0q, lenq
+    add      outq, lenq
+    neg      lenq
+
+align 16
+.loop:
+    mova       m0, [in0q + lenq]
+    mova       m1, [in1q + lenq]
+%ifidn %1, ms
+    psrad      m2, m1, 1
+    psubd      m0, m2
+%endif
+%ifnidn %1, indep2
+    p%4d       m2, m0, m1
+%endif
+    packssdw  m%2, m%2
+    packssdw  m%3, m%3
+    punpcklwd m%2, m%3
+    psllw     m%2, m3
+    mova [outq + lenq], m%2
+    add      lenq, 16
+    jl .loop
+    REP_RET
+%endmacro
+
+INIT_XMM sse2
+FLAC_DECORRELATE_16 ls, 0, 2, sub
+FLAC_DECORRELATE_16 rs, 2, 1, add
+FLAC_DECORRELATE_16 ms, 2, 0, add
+
+;----------------------------------------------------------------------------------
+;void ff_flac_decorrelate_[lrm]s_32_sse2(uint8_t **out, int32_t **in, int channels,
+;                                        int len, int shift);
+;----------------------------------------------------------------------------------
+%macro FLAC_DECORRELATE_32 5
+cglobal flac_decorrelate_%1_32, 2, 4, 4, out, in0, in1, len
+%if ARCH_X86_32 || WIN64
+    movd       m3, r4m
+%if ARCH_X86_32
+    mov      lend, lenm
+%endif
+%else ; UNIX64
+    movd       m3, r4d
+%endif
+    mov      in1q, [in0q + gprsize]
+    mov      in0q, [in0q]
+    mov      outq, [outq]
+    sub      in1q, in0q
+
+align 16
+.loop:
+    mova       m0, [in0q]
+    mova       m1, [in0q + in1q]
+%ifidn %1, ms
+    psrad      m2, m1, 1
+    psubd      m0, m2
+%endif
+    p%5d       m2, m0, m1
+    pslld     m%2, m3
+    pslld     m%3, m3
+
+    SBUTTERFLY dq, %2, %3, %4
+
+    mova  [outq         ], m%2
+    mova  [outq + mmsize], m%3
+
+    add      in0q, mmsize
+    add      outq, mmsize*2
+    sub      lend, mmsize/4
+    jg .loop
+    REP_RET
+%endmacro
+
+INIT_XMM sse2
+FLAC_DECORRELATE_32 ls, 0, 2, 1, sub
+FLAC_DECORRELATE_32 rs, 2, 1, 0, add
+FLAC_DECORRELATE_32 ms, 2, 0, 1, add
+
+;-----------------------------------------------------------------------------------------
+;void ff_flac_decorrelate_indep<ch>_<bps>_<opt>(uint8_t **out, int32_t **in, int channels,
+;                                            int len, int shift);
+;-----------------------------------------------------------------------------------------
+%macro TRANSPOSE8x4D 9
+    SBUTTERFLY dq,  %1, %2, %9
+    SBUTTERFLY dq,  %3, %4, %9
+    SBUTTERFLY dq,  %5, %6, %9
+    SBUTTERFLY dq,  %7, %8, %9
+    SBUTTERFLY qdq, %1, %3, %9
+    SBUTTERFLY qdq, %2, %4, %9
+    SBUTTERFLY qdq, %5, %7, %9
+    SBUTTERFLY qdq, %6, %8, %9
+    SWAP %2, %5
+    SWAP %4, %7
+%endmacro
+
+;%1 = bps
+;%2 = channels
+;%3 = last xmm reg used
+;%4 = word/dword (shift instruction)
+%macro FLAC_DECORRELATE_INDEP 4
+%define REPCOUNT %2/(32/%1) ; 16bits = channels / 2; 32bits = channels
+cglobal flac_decorrelate_indep%2_%1, 2, %2+2, %3+1, out, in0, in1, len, in2, in3, in4, in5, in6, in7
+%if ARCH_X86_32
+    movd      m%3, r4m
+%if %2 == 6
+    DEFINE_ARGS out, in0, in1, in2, in3, in4, in5
+    %define  lend  dword r3m
+%else
+    mov      lend, lenm
+%endif
+%elif WIN64
+    movd      m%3, r4m
+%else ; UNIX64
+    movd      m%3, r4d
+%endif
+
+%assign %%i 1
+%rep %2-1
+    mov      in %+ %%i %+ q, [in0q+%%i*gprsize]
+%assign %%i %%i+1
+%endrep
+
+    mov      in0q, [in0q]
+    mov      outq, [outq]
+
+%assign %%i 1
+%rep %2-1
+    sub      in %+ %%i %+ q, in0q
+%assign %%i %%i+1
+%endrep
+
+align 16
+.loop:
+    mova       m0, [in0q]
+
+%assign %%i 1
+%rep REPCOUNT-1
+    mova     m %+ %%i, [in0q + in %+ %%i %+ q]
+%assign %%i %%i+1
+%endrep
+
+%if %1 == 32
+
+%if %2 == 8
+    TRANSPOSE8x4D 0, 1, 2, 3, 4, 5, 6, 7, 8
+%elif %2 == 6
+    SBUTTERFLY dq, 0, 1, 6
+    SBUTTERFLY dq, 2, 3, 6
+    SBUTTERFLY dq, 4, 5, 6
+
+    punpcklqdq m6, m0, m2
+    punpckhqdq m2, m4
+    shufps     m4, m0, 0xe4
+    punpcklqdq m0, m1, m3
+    punpckhqdq m3, m5
+    shufps     m5, m1, 0xe4
+    SWAP 0,6,1,4,5,3
+%elif %2 == 4
+    TRANSPOSE4x4D 0, 1, 2, 3, 4
+%else ; %2 == 2
+    SBUTTERFLY dq, 0, 1, 2
+%endif
+
+%else ; %1 == 16
+
+%if %2 == 8
+    packssdw   m0, [in0q + in4q]
+    packssdw   m1, [in0q + in5q]
+    packssdw   m2, [in0q + in6q]
+    packssdw   m3, [in0q + in7q]
+    TRANSPOSE2x4x4W 0, 1, 2, 3, 4
+%elif %2 == 6
+    packssdw   m0, [in0q + in3q]
+    packssdw   m1, [in0q + in4q]
+    packssdw   m2, [in0q + in5q]
+    pshufd     m3, m0,     q1032
+    punpcklwd  m0, m1
+    punpckhwd  m1, m2
+    punpcklwd  m2, m3
+
+    shufps     m3, m0, m2, q2020
+    shufps     m0, m1,     q2031
+    shufps     m2, m1,     q3131
+    shufps     m1, m2, m3, q3120
+    shufps     m3, m0,     q0220
+    shufps     m0, m2,     q3113
+    SWAP 2, 0, 3
+%else ; %2 == 4
+    packssdw   m0, [in0q + in2q]
+    packssdw   m1, [in0q + in3q]
+    SBUTTERFLY wd, 0, 1, 2
+    SBUTTERFLY dq, 0, 1, 2
+%endif
+
+%endif
+
+%assign %%i 0
+%rep REPCOUNT
+    psll%4   m %+ %%i, m%3
+%assign %%i %%i+1
+%endrep
+
+%assign %%i 0
+%rep REPCOUNT
+    mova [outq + %%i*mmsize], m %+ %%i
+%assign %%i %%i+1
+%endrep
+
+    add      in0q, mmsize
+    add      outq, mmsize*REPCOUNT
+    sub      lend, mmsize/4
+    jg .loop
+    REP_RET
+%endmacro
+
+INIT_XMM sse2
+FLAC_DECORRELATE_16 indep2, 0, 1 ; Reuse stereo 16bits macro
+FLAC_DECORRELATE_INDEP 32, 2, 3, d
+FLAC_DECORRELATE_INDEP 16, 4, 3, w
+FLAC_DECORRELATE_INDEP 32, 4, 5, d
+FLAC_DECORRELATE_INDEP 16, 6, 4, w
+FLAC_DECORRELATE_INDEP 32, 6, 7, d
+%if ARCH_X86_64
+FLAC_DECORRELATE_INDEP 16, 8, 5, w
+FLAC_DECORRELATE_INDEP 32, 8, 9, d
+%endif
+
+INIT_XMM avx
+FLAC_DECORRELATE_INDEP 32, 4, 5, d
+FLAC_DECORRELATE_INDEP 32, 6, 7, d
+%if ARCH_X86_64
+FLAC_DECORRELATE_INDEP 16, 8, 5, w
+FLAC_DECORRELATE_INDEP 32, 8, 9, d
+%endif
diff --git a/libavcodec/x86/flacdsp_init.c b/libavcodec/x86/flacdsp_init.c
index ad88e5b..d04af45 100644
--- a/libavcodec/x86/flacdsp_init.c
+++ b/libavcodec/x86/flacdsp_init.c
@@ -29,21 +29,89 @@
 
 void ff_flac_enc_lpc_16_sse4(int32_t *, const int32_t *, int, int, const int32_t *,int);
 
-av_cold void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt,
+#define DECORRELATE_FUNCS(fmt, opt)                                                      \
+void ff_flac_decorrelate_ls_##fmt##_##opt(uint8_t **out, int32_t **in, int channels,     \
+                                          int len, int shift);                           \
+void ff_flac_decorrelate_rs_##fmt##_##opt(uint8_t **out, int32_t **in, int channels,     \
+                                          int len, int shift);                           \
+void ff_flac_decorrelate_ms_##fmt##_##opt(uint8_t **out, int32_t **in, int channels,     \
+                                          int len, int shift);                           \
+void ff_flac_decorrelate_indep2_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
+                                             int len, int shift);                        \
+void ff_flac_decorrelate_indep4_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
+                                              int len, int shift);                       \
+void ff_flac_decorrelate_indep6_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
+                                              int len, int shift);                       \
+void ff_flac_decorrelate_indep8_##fmt##_##opt(uint8_t **out, int32_t **in, int channels, \
+                                              int len, int shift)
+
+DECORRELATE_FUNCS(16, sse2);
+DECORRELATE_FUNCS(16,  avx);
+DECORRELATE_FUNCS(32, sse2);
+DECORRELATE_FUNCS(32,  avx);
+
+av_cold void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
                                  int bps)
 {
 #if HAVE_YASM
     int cpu_flags = av_get_cpu_flags();
 
+#if CONFIG_FLAC_DECODER
+    if (EXTERNAL_SSE2(cpu_flags)) {
+        if (fmt == AV_SAMPLE_FMT_S16) {
+            if (channels == 2)
+                c->decorrelate[0] = ff_flac_decorrelate_indep2_16_sse2;
+            else if (channels == 4)
+                c->decorrelate[0] = ff_flac_decorrelate_indep4_16_sse2;
+            else if (channels == 6)
+                c->decorrelate[0] = ff_flac_decorrelate_indep6_16_sse2;
+            else if (ARCH_X86_64 && channels == 8)
+                c->decorrelate[0] = ff_flac_decorrelate_indep8_16_sse2;
+            c->decorrelate[1] = ff_flac_decorrelate_ls_16_sse2;
+            c->decorrelate[2] = ff_flac_decorrelate_rs_16_sse2;
+            c->decorrelate[3] = ff_flac_decorrelate_ms_16_sse2;
+        } else if (fmt == AV_SAMPLE_FMT_S32) {
+            if (channels == 2)
+                c->decorrelate[0] = ff_flac_decorrelate_indep2_32_sse2;
+            else if (channels == 4)
+                c->decorrelate[0] = ff_flac_decorrelate_indep4_32_sse2;
+            else if (channels == 6)
+                c->decorrelate[0] = ff_flac_decorrelate_indep6_32_sse2;
+            else if (ARCH_X86_64 && channels == 8)
+                c->decorrelate[0] = ff_flac_decorrelate_indep8_32_sse2;
+            c->decorrelate[1] = ff_flac_decorrelate_ls_32_sse2;
+            c->decorrelate[2] = ff_flac_decorrelate_rs_32_sse2;
+            c->decorrelate[3] = ff_flac_decorrelate_ms_32_sse2;
+        }
+    }
     if (EXTERNAL_SSE4(cpu_flags)) {
-        if (bps > 16 && CONFIG_FLAC_DECODER)
+        if (bps > 16)
             c->lpc = ff_flac_lpc_32_sse4;
-        if (bps == 16 && CONFIG_FLAC_ENCODER && CONFIG_GPL)
-            c->lpc_encode = ff_flac_enc_lpc_16_sse4;
+    }
+    if (EXTERNAL_AVX(cpu_flags)) {
+        if (fmt == AV_SAMPLE_FMT_S16) {
+            if (ARCH_X86_64 && channels == 8)
+                c->decorrelate[0] = ff_flac_decorrelate_indep8_16_avx;
+        } else if (fmt == AV_SAMPLE_FMT_S32) {
+            if (channels == 4)
+                c->decorrelate[0] = ff_flac_decorrelate_indep4_32_avx;
+            else if (channels == 6)
+                c->decorrelate[0] = ff_flac_decorrelate_indep6_32_avx;
+            else if (ARCH_X86_64 && channels == 8)
+                c->decorrelate[0] = ff_flac_decorrelate_indep8_32_avx;
+        }
     }
     if (EXTERNAL_XOP(cpu_flags)) {
-        if (bps > 16 && CONFIG_FLAC_DECODER)
+        if (bps > 16)
             c->lpc = ff_flac_lpc_32_xop;
     }
 #endif
+
+#if CONFIG_FLAC_ENCODER
+    if (EXTERNAL_SSE4(cpu_flags)) {
+        if (CONFIG_GPL && bps == 16)
+            c->lpc_encode = ff_flac_enc_lpc_16_sse4;
+    }
+#endif
+#endif /* HAVE_YASM */
 }
diff --git a/libavcodec/x86/h264_i386.h b/libavcodec/x86/h264_i386.h
index ef65cf8..dcba42d 100644
--- a/libavcodec/x86/h264_i386.h
+++ b/libavcodec/x86/h264_i386.h
@@ -36,6 +36,12 @@
 
 #if HAVE_INLINE_ASM
 
+#if ARCH_X86_64
+#define REG64 "r"
+#else
+#define REG64 "m"
+#endif
+
 //FIXME use some macros to avoid duplicating get_cabac (cannot be done yet
 //as that would make optimization work hard)
 #if HAVE_7REGS && !BROKEN_COMPILER
@@ -140,7 +146,7 @@
         "3:                                     \n\t"
 
         "mov %10, %0                            \n\t"
-        "movzbl (%0, %6), %k6                   \n\t"
+        "movzb (%0, %6), %6                     \n\t"
         "add %9, %6                             \n\t"
 
         BRANCHLESS_GET_CABAC("%4", "%q4", "(%6)", "%3", "%w3",
@@ -151,14 +157,14 @@
                              AV_STRINGIFY(H264_MLPS_STATE_OFFSET),
                              "%15")
 
-        "mov %1, %k6                            \n\t"
+        "mov %1, %6                             \n\t"
         "test $1, %4                            \n\t"
         " jz 4f                                 \n\t"
 
 #ifdef BROKEN_RELOCATIONS
-        "movzbl %c14(%15, %q6), %k6\n\t"
+        "movzb %c14(%15, %q6), %6\n\t"
 #else
-        "movzbl "MANGLE(ff_h264_cabac_tables)"+%c14(%k6), %k6\n\t"
+        "movzb "MANGLE(ff_h264_cabac_tables)"+%c14(%6), %6\n\t"
 #endif
         "add %11, %6                            \n\t"
 
@@ -171,8 +177,8 @@
                              "%15")
 
         "mov %2, %0                             \n\t"
-        "mov %1, %k6                            \n\t"
-        "movl %k6, (%0)                         \n\t"
+        "mov %1, %6                             \n\t"
+        "mov %6, (%0)                           \n\t"
 
         "test $1, %4                            \n\t"
         " jnz 5f                                \n\t"
@@ -180,19 +186,19 @@
         "add"OPSIZE"  $4, %2                    \n\t"
 
         "4:                                     \n\t"
-        "addl $1, %k6                           \n\t"
-        "mov %k6, %1                            \n\t"
-        "cmpl $63, %k6                          \n\t"
+        "add $1, %6                             \n\t"
+        "mov %6, %1                             \n\t"
+        "cmp $63, %6                            \n\t"
         " jb 3b                                 \n\t"
         "mov %2, %0                             \n\t"
-        "movl %k6, (%0)                         \n\t"
+        "mov %6, (%0)                           \n\t"
         "5:                                     \n\t"
         "addl %8, %k0                           \n\t"
         "shr $2, %k0                            \n\t"
-        : "=&q"(coeff_count), "+m"(last), "+m"(index), "+&r"(c->low),
+        : "=&q"(coeff_count), "+"REG64(last), "+"REG64(index), "+&r"(c->low),
           "=&r"(bit), "+&r"(c->range), "=&r"(state)
         : "r"(c), "m"(minusindex), "m"(significant_coeff_ctx_base),
-          "m"(sig_off), "m"(last_coeff_ctx_base),
+          REG64(sig_off), REG64(last_coeff_ctx_base),
           "i"(offsetof(CABACContext, bytestream)),
           "i"(offsetof(CABACContext, bytestream_end)),
           "i"(H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET) TABLES_ARG
diff --git a/libavcodec/x86/lossless_audiodsp.asm b/libavcodec/x86/lossless_audiodsp.asm
index 64b769f..39395fe 100644
--- a/libavcodec/x86/lossless_audiodsp.asm
+++ b/libavcodec/x86/lossless_audiodsp.asm
@@ -26,6 +26,12 @@
 ; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3,
 ;                                     int order, int mul)
 cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul
+%if mmsize == 16
+    test orderq, 8
+        jnz scalarproduct_and_madd_int16_fallback
+%else
+    scalarproduct_and_madd_int16_fallback
+%endif
     shl orderq, 1
     movd    m7, mulm
 %if mmsize == 16
@@ -117,6 +123,8 @@
 ;                                     int order, int mul)
 INIT_XMM ssse3
 cglobal scalarproduct_and_madd_int16, 4,5,10, v1, v2, v3, order, mul
+    test orderq, 8
+        jnz scalarproduct_and_madd_int16_fallback
     shl orderq, 1
     movd    m7, mulm
     pshuflw m7, m7, 0
diff --git a/libavcodec/x86/me_cmp.asm b/libavcodec/x86/me_cmp.asm
index 95b99c4..0160dc3 100644
--- a/libavcodec/x86/me_cmp.asm
+++ b/libavcodec/x86/me_cmp.asm
@@ -215,7 +215,7 @@
 %elif cpuflag(mmx)
 ALIGN 16
 ; int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,
-;                               uint8_t *src2, int stride, int h)
+;                               uint8_t *src2, ptrdiff_t stride, int h)
 ; r0 = void *s = unused, int h = unused (always 8)
 ; note how r1, r2 and r3 are not clobbered in this function, so 16x16
 ; can simply call this 2x2x (and that's why we access rsp+gprsize
@@ -280,7 +280,7 @@
 HADAMARD8_DIFF 9
 
 ; int ff_sse*_*(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-;               int line_size, int h)
+;               ptrdiff_t line_size, int h)
 
 %macro SUM_SQUARED_ERRORS 1
 cglobal sse%1, 5,5,8, v, pix1, pix2, lsize, h
@@ -395,7 +395,7 @@
 SUM_ABS_DCTELEM 6, 2
 
 ;------------------------------------------------------------------------------
-; int ff_hf_noise*_mmx(uint8_t *pix1, int lsize, int h)
+; int ff_hf_noise*_mmx(uint8_t *pix1, ptrdiff_t lsize, int h)
 ;------------------------------------------------------------------------------
 ; %1 = 8/16. %2-5=m#
 %macro HF_NOISE_PART1 5
@@ -437,7 +437,6 @@
 ; %1 = 8/16
 %macro HF_NOISE 1
 cglobal hf_noise%1, 3,3,0, pix1, lsize, h
-    movsxdifnidn lsizeq, lsized
     sub        hd, 2
     pxor       m7, m7
     pxor       m6, m6
@@ -472,7 +471,7 @@
 HF_NOISE 16
 
 ;---------------------------------------------------------------------------------------
-;int ff_sad_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
+;int ff_sad_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h);
 ;---------------------------------------------------------------------------------------
 ;%1 = 8/16
 %macro SAD 1
@@ -527,7 +526,7 @@
 SAD 16
 
 ;------------------------------------------------------------------------------------------
-;int ff_sad_x2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
+;int ff_sad_x2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h);
 ;------------------------------------------------------------------------------------------
 ;%1 = 8/16
 %macro SAD_X2 1
@@ -604,7 +603,7 @@
 SAD_X2 16
 
 ;------------------------------------------------------------------------------------------
-;int ff_sad_y2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
+;int ff_sad_y2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h);
 ;------------------------------------------------------------------------------------------
 ;%1 = 8/16
 %macro SAD_Y2 1
@@ -674,7 +673,7 @@
 SAD_Y2 16
 
 ;-------------------------------------------------------------------------------------------
-;int ff_sad_approx_xy2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int stride, int h);
+;int ff_sad_approx_xy2_<opt>(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, ptrdiff_t stride, int h);
 ;-------------------------------------------------------------------------------------------
 ;%1 = 8/16
 %macro SAD_APPROX_XY2 1
@@ -776,7 +775,7 @@
 
 ;--------------------------------------------------------------------
 ;int ff_vsad_intra(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-;                  int line_size, int h);
+;                  ptrdiff_t line_size, int h);
 ;--------------------------------------------------------------------
 ; %1 = 8/16
 %macro VSAD_INTRA 1
@@ -837,7 +836,7 @@
 
 ;---------------------------------------------------------------------
 ;int ff_vsad_approx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-;                   int line_size, int h);
+;                   ptrdiff_t line_size, int h);
 ;---------------------------------------------------------------------
 ; %1 = 8/16
 %macro VSAD_APPROX 1
diff --git a/libavcodec/x86/me_cmp_init.c b/libavcodec/x86/me_cmp_init.c
index 6dc59f5..255df50 100644
--- a/libavcodec/x86/me_cmp_init.c
+++ b/libavcodec/x86/me_cmp_init.c
@@ -34,55 +34,55 @@
 int ff_sum_abs_dctelem_sse2(int16_t *block);
 int ff_sum_abs_dctelem_ssse3(int16_t *block);
 int ff_sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                int line_size, int h);
+                ptrdiff_t stride, int h);
 int ff_sse16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                 int line_size, int h);
+                 ptrdiff_t stride, int h);
 int ff_sse16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                  int line_size, int h);
-int ff_hf_noise8_mmx(uint8_t *pix1, int lsize, int h);
-int ff_hf_noise16_mmx(uint8_t *pix1, int lsize, int h);
+                  ptrdiff_t stride, int h);
+int ff_hf_noise8_mmx(uint8_t *pix1, ptrdiff_t stride, int h);
+int ff_hf_noise16_mmx(uint8_t *pix1, ptrdiff_t stride, int h);
 int ff_sad8_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                   int stride, int h);
+                   ptrdiff_t stride, int h);
 int ff_sad16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                    int stride, int h);
+                    ptrdiff_t stride, int h);
 int ff_sad16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                  int stride, int h);
+                  ptrdiff_t stride, int h);
 int ff_sad8_x2_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                      int stride, int h);
+                      ptrdiff_t stride, int h);
 int ff_sad16_x2_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                       int stride, int h);
+                       ptrdiff_t stride, int h);
 int ff_sad16_x2_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                     int stride, int h);
+                     ptrdiff_t stride, int h);
 int ff_sad8_y2_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                      int stride, int h);
+                      ptrdiff_t stride, int h);
 int ff_sad16_y2_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                       int stride, int h);
+                       ptrdiff_t stride, int h);
 int ff_sad16_y2_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                     int stride, int h);
+                     ptrdiff_t stride, int h);
 int ff_sad8_approx_xy2_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                              int stride, int h);
+                              ptrdiff_t stride, int h);
 int ff_sad16_approx_xy2_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                               int stride, int h);
+                               ptrdiff_t stride, int h);
 int ff_sad16_approx_xy2_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                             int stride, int h);
+                             ptrdiff_t stride, int h);
 int ff_vsad_intra8_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                          int line_size, int h);
+                          ptrdiff_t stride, int h);
 int ff_vsad_intra16_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                           int line_size, int h);
+                           ptrdiff_t stride, int h);
 int ff_vsad_intra16_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                         int line_size, int h);
+                         ptrdiff_t stride, int h);
 int ff_vsad8_approx_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                    int line_size, int h);
+                    ptrdiff_t stride, int h);
 int ff_vsad16_approx_mmxext(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                     int line_size, int h);
+                     ptrdiff_t stride, int h);
 int ff_vsad16_approx_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                   int line_size, int h);
+                   ptrdiff_t stride, int h);
 
-#define hadamard_func(cpu)                                              \
-    int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,     \
-                                  uint8_t *src2, int stride, int h);    \
-    int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1,   \
-                                    uint8_t *src2, int stride, int h);
+#define hadamard_func(cpu)                                                    \
+    int ff_hadamard8_diff_ ## cpu(MpegEncContext *s, uint8_t *src1,           \
+                                  uint8_t *src2, ptrdiff_t stride, int h);    \
+    int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1,         \
+                                    uint8_t *src2, ptrdiff_t stride, int h);
 
 hadamard_func(mmx)
 hadamard_func(mmxext)
@@ -91,16 +91,16 @@
 
 #if HAVE_YASM
 static int nsse16_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2,
-                      int line_size, int h)
+                      ptrdiff_t stride, int h)
 {
     int score1, score2;
 
     if (c)
-        score1 = c->mecc.sse[0](c, pix1, pix2, line_size, h);
+        score1 = c->mecc.sse[0](c, pix1, pix2, stride, h);
     else
-        score1 = ff_sse16_mmx(c, pix1, pix2, line_size, h);
-    score2 = ff_hf_noise16_mmx(pix1, line_size, h) + ff_hf_noise8_mmx(pix1+8, line_size, h)
-           - ff_hf_noise16_mmx(pix2, line_size, h) - ff_hf_noise8_mmx(pix2+8, line_size, h);
+        score1 = ff_sse16_mmx(c, pix1, pix2, stride, h);
+    score2 = ff_hf_noise16_mmx(pix1, stride, h) + ff_hf_noise8_mmx(pix1+8, stride, h)
+           - ff_hf_noise16_mmx(pix2, stride, h) - ff_hf_noise8_mmx(pix2+8, stride, h);
 
     if (c)
         return score1 + FFABS(score2) * c->avctx->nsse_weight;
@@ -109,11 +109,11 @@
 }
 
 static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2,
-                     int line_size, int h)
+                     ptrdiff_t stride, int h)
 {
-    int score1 = ff_sse8_mmx(c, pix1, pix2, line_size, h);
-    int score2 = ff_hf_noise8_mmx(pix1, line_size, h) -
-                 ff_hf_noise8_mmx(pix2, line_size, h);
+    int score1 = ff_sse8_mmx(c, pix1, pix2, stride, h);
+    int score2 = ff_hf_noise8_mmx(pix1, stride, h) -
+                 ff_hf_noise8_mmx(pix2, stride, h);
 
     if (c)
         return score1 + FFABS(score2) * c->avctx->nsse_weight;
@@ -126,12 +126,12 @@
 #if HAVE_INLINE_ASM
 
 static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy,
-                            int line_size, int h)
+                            ptrdiff_t stride, int h)
 {
     int tmp;
 
     av_assert2((((int) pix) & 7) == 0);
-    av_assert2((line_size & 7) == 0);
+    av_assert2((stride & 7) == 0);
 
 #define SUM(in0, in1, out0, out1)               \
     "movq (%0), %%mm2\n"                        \
@@ -182,7 +182,7 @@
         "paddw %%mm6, %%mm0\n"
         "movd  %%mm0, %1\n"
         : "+r" (pix), "=r" (tmp)
-        : "r" ((x86_reg) line_size), "m" (h)
+        : "r" (stride), "m" (h)
         : "%ecx");
 
     return tmp & 0xFFFF;
@@ -190,13 +190,13 @@
 #undef SUM
 
 static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
-                      int line_size, int h)
+                      ptrdiff_t stride, int h)
 {
     int tmp;
 
     av_assert2((((int) pix1) & 7) == 0);
     av_assert2((((int) pix2) & 7) == 0);
-    av_assert2((line_size & 7) == 0);
+    av_assert2((stride & 7) == 0);
 
 #define SUM(in0, in1, out0, out1)       \
     "movq (%0), %%mm2\n"                \
@@ -263,7 +263,7 @@
         "paddw %%mm6, %%mm0\n"
         "movd %%mm0, %2\n"
         : "+r" (pix1), "+r" (pix2), "=r" (tmp)
-        : "r" ((x86_reg) line_size), "m" (h)
+        : "r" (stride), "m" (h)
         : "%ecx");
 
     return tmp & 0x7FFF;
@@ -276,9 +276,10 @@
     0x0002000200020002ULL,
 };
 
-static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2,
+                              ptrdiff_t stride, int h)
 {
-    x86_reg len = -(x86_reg)stride * h;
+    x86_reg len = -stride * h;
     __asm__ volatile (
         ".p2align 4                     \n\t"
         "1:                             \n\t"
@@ -308,13 +309,13 @@
         "add %3, %%"REG_a"              \n\t"
         " js 1b                         \n\t"
         : "+a" (len)
-        : "r" (blk1 - len), "r" (blk2 - len), "r" ((x86_reg) stride));
+        : "r" (blk1 - len), "r" (blk2 - len), "r" (stride));
 }
 
 static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2,
-                              int stride, int h)
+                              ptrdiff_t stride, int h)
 {
-    x86_reg len = -(x86_reg)stride * h;
+    x86_reg len = -stride * h;
     __asm__ volatile (
         ".p2align 4                     \n\t"
         "1:                             \n\t"
@@ -347,12 +348,13 @@
         " js 1b                         \n\t"
         : "+a" (len)
         : "r" (blk1a - len), "r" (blk1b - len), "r" (blk2 - len),
-          "r" ((x86_reg) stride));
+          "r" (stride));
 }
 
-static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2,
+                              ptrdiff_t stride, int h)
 {
-    x86_reg len = -(x86_reg)stride * h;
+    x86_reg len = -stride * h;
     __asm__ volatile (
         "movq  (%1, %%"REG_a"), %%mm0   \n\t"
         "movq 1(%1, %%"REG_a"), %%mm2   \n\t"
@@ -400,7 +402,7 @@
         " js 1b                         \n\t"
         : "+a" (len)
         : "r" (blk1 - len), "r" (blk1 - len + stride), "r" (blk2 - len),
-          "r" ((x86_reg) stride), "m" (round_tab[2]));
+          "r" (stride), "m" (round_tab[2]));
 }
 
 static inline int sum_mmx(void)
@@ -418,19 +420,21 @@
     return ret & 0xFFFF;
 }
 
-static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2,
+                                ptrdiff_t stride, int h)
 {
     sad8_2_mmx(blk1, blk1 + 1, blk2, stride, h);
 }
 
-static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, int stride, int h)
+static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2,
+                                ptrdiff_t stride, int h)
 {
     sad8_2_mmx(blk1, blk1 + stride, blk2, stride, h);
 }
 
 #define PIX_SAD(suf)                                                    \
 static int sad8_ ## suf(MpegEncContext *v, uint8_t *blk2,               \
-                        uint8_t *blk1, int stride, int h)               \
+                        uint8_t *blk1, ptrdiff_t stride, int h)         \
 {                                                                       \
     av_assert2(h == 8);                                                     \
     __asm__ volatile (                                                  \
@@ -444,7 +448,7 @@
 }                                                                       \
                                                                         \
 static int sad8_x2_ ## suf(MpegEncContext *v, uint8_t *blk2,            \
-                           uint8_t *blk1, int stride, int h)            \
+                           uint8_t *blk1, ptrdiff_t stride, int h)      \
 {                                                                       \
     av_assert2(h == 8);                                                     \
     __asm__ volatile (                                                  \
@@ -459,7 +463,7 @@
 }                                                                       \
                                                                         \
 static int sad8_y2_ ## suf(MpegEncContext *v, uint8_t *blk2,            \
-                           uint8_t *blk1, int stride, int h)            \
+                           uint8_t *blk1, ptrdiff_t stride, int h)      \
 {                                                                       \
     av_assert2(h == 8);                                                     \
     __asm__ volatile (                                                  \
@@ -474,7 +478,7 @@
 }                                                                       \
                                                                         \
 static int sad8_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2,           \
-                            uint8_t *blk1, int stride, int h)           \
+                            uint8_t *blk1, ptrdiff_t stride, int h)     \
 {                                                                       \
     av_assert2(h == 8);                                                     \
     __asm__ volatile (                                                  \
@@ -488,7 +492,7 @@
 }                                                                       \
                                                                         \
 static int sad16_ ## suf(MpegEncContext *v, uint8_t *blk2,              \
-                         uint8_t *blk1, int stride, int h)              \
+                         uint8_t *blk1, ptrdiff_t stride, int h)        \
 {                                                                       \
     __asm__ volatile (                                                  \
         "pxor %%mm7, %%mm7     \n\t"                                    \
@@ -502,7 +506,7 @@
 }                                                                       \
                                                                         \
 static int sad16_x2_ ## suf(MpegEncContext *v, uint8_t *blk2,           \
-                            uint8_t *blk1, int stride, int h)           \
+                            uint8_t *blk1, ptrdiff_t stride, int h)     \
 {                                                                       \
     __asm__ volatile (                                                  \
         "pxor %%mm7, %%mm7     \n\t"                                    \
@@ -517,7 +521,7 @@
 }                                                                       \
                                                                         \
 static int sad16_y2_ ## suf(MpegEncContext *v, uint8_t *blk2,           \
-                            uint8_t *blk1, int stride, int h)           \
+                            uint8_t *blk1, ptrdiff_t stride, int h)     \
 {                                                                       \
     __asm__ volatile (                                                  \
         "pxor %%mm7, %%mm7     \n\t"                                    \
@@ -532,7 +536,7 @@
 }                                                                       \
                                                                         \
 static int sad16_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2,          \
-                             uint8_t *blk1, int stride, int h)          \
+                             uint8_t *blk1, ptrdiff_t stride, int h)    \
 {                                                                       \
     __asm__ volatile (                                                  \
         "pxor %%mm7, %%mm7     \n\t"                                    \
diff --git a/libavcodec/x86/v210enc.asm b/libavcodec/x86/v210enc.asm
new file mode 100644
index 0000000..3245de3
--- /dev/null
+++ b/libavcodec/x86/v210enc.asm
@@ -0,0 +1,145 @@
+;******************************************************************************
+;* V210 SIMD pack
+;* Copyright (c) 2014 Kieran Kunhya <kierank@obe.tv>
+;*
+;* This file is part of FFmpeg.
+;*
+;* FFmpeg is free software; you can redistribute it and/or
+;* modify it under the terms of the GNU Lesser General Public
+;* License as published by the Free Software Foundation; either
+;* version 2.1 of the License, or (at your option) any later version.
+;*
+;* FFmpeg is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;* Lesser General Public License for more details.
+;*
+;* You should have received a copy of the GNU Lesser General Public
+;* License along with FFmpeg; if not, write to the Free Software
+;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+;******************************************************************************
+
+%include "libavutil/x86/x86util.asm"
+
+SECTION_RODATA
+
+v210_enc_min_10: times 8 dw 0x4
+v210_enc_max_10: times 8 dw 0x3fb
+
+v210_enc_luma_mult_10: dw 4,1,16,4,1,16,0,0
+v210_enc_luma_shuf_10: db -1,0,1,-1,2,3,4,5,-1,6,7,-1,8,9,10,11
+
+v210_enc_chroma_mult_10: dw 1,4,16,0,16,1,4,0
+v210_enc_chroma_shuf_10: db 0,1,8,9,-1,2,3,-1,10,11,4,5,-1,12,13,-1
+
+v210_enc_min_8: times 16 db 0x1
+v210_enc_max_8: times 16 db 0xfe
+
+v210_enc_luma_shuf_8: db 6,-1,7,-1,8,-1,9,-1,10,-1,11,-1,-1,-1,-1,-1
+v210_enc_luma_mult_8: dw 16,4,64,16,4,64,0,0
+
+v210_enc_chroma_shuf1_8: db 0,-1,1,-1,2,-1,3,-1,8,-1,9,-1,10,-1,11,-1
+v210_enc_chroma_shuf2_8: db 3,-1,4,-1,5,-1,7,-1,11,-1,12,-1,13,-1,15,-1
+
+v210_enc_chroma_mult_8: dw 4,16,64,0,64,4,16,0
+
+SECTION .text
+
+%macro v210_planar_pack_10 0
+
+; v210_planar_pack_10(const uint16_t *y, const uint16_t *u, const uint16_t *v, uint8_t *dst, ptrdiff_t width)
+cglobal v210_planar_pack_10, 5, 5, 4, y, u, v, dst, width
+    lea     r0, [yq+2*widthq]
+    add     uq, widthq
+    add     vq, widthq
+    neg     widthq
+
+    mova    m2, [v210_enc_min_10]
+    mova    m3, [v210_enc_max_10]
+
+.loop
+    movu    m0, [yq+2*widthq]
+    CLIPW   m0, m2, m3
+
+    movq    m1, [uq+widthq]
+    movhps  m1, [vq+widthq]
+    CLIPW   m1, m2, m3
+
+    pmullw  m0, [v210_enc_luma_mult_10]
+    pshufb  m0, [v210_enc_luma_shuf_10]
+
+    pmullw  m1, [v210_enc_chroma_mult_10]
+    pshufb  m1, [v210_enc_chroma_shuf_10]
+
+    por     m0, m1
+
+    movu    [dstq], m0
+
+    add     dstq, mmsize
+    add     widthq, 6
+    jl .loop
+
+    RET
+%endmacro
+
+INIT_XMM ssse3
+v210_planar_pack_10
+
+%macro v210_planar_pack_8 0
+
+; v210_planar_pack_8(const uint8_t *y, const uint8_t *u, const uint8_t *v, uint8_t *dst, ptrdiff_t width)
+cglobal v210_planar_pack_8, 5, 5, 7, y, u, v, dst, width
+    add     yq, widthq
+    shr     widthq, 1
+    add     uq, widthq
+    add     vq, widthq
+    neg     widthq
+
+    mova    m4, [v210_enc_min_8]
+    mova    m5, [v210_enc_max_8]
+    pxor    m6, m6
+
+.loop
+    movu    m1, [yq+2*widthq]
+    CLIPUB  m1, m4, m5
+
+    punpcklbw m0, m1, m6
+    ; can't unpack high bytes in the same way because we process
+    ; only six bytes at a time
+    pshufb  m1, [v210_enc_luma_shuf_8]
+
+    pmullw  m0, [v210_enc_luma_mult_8]
+    pmullw  m1, [v210_enc_luma_mult_8]
+    pshufb  m0, [v210_enc_luma_shuf_10]
+    pshufb  m1, [v210_enc_luma_shuf_10]
+
+    movq    m3, [uq+widthq]
+    movhps  m3, [vq+widthq]
+    CLIPUB  m3, m4, m5
+
+    ; shuffle and multiply to get the same packing as in 10-bit
+    pshufb  m2, m3, [v210_enc_chroma_shuf1_8]
+    pshufb  m3, [v210_enc_chroma_shuf2_8]
+
+    pmullw  m2, [v210_enc_chroma_mult_8]
+    pmullw  m3, [v210_enc_chroma_mult_8]
+    pshufb  m2, [v210_enc_chroma_shuf_10]
+    pshufb  m3, [v210_enc_chroma_shuf_10]
+
+    por     m0, m2
+    por     m1, m3
+
+    movu    [dstq], m0
+    movu    [dstq+mmsize], m1
+
+    add     dstq, 2*mmsize
+    add     widthq, 6
+    jl .loop
+
+    RET
+%endmacro
+
+INIT_XMM ssse3
+v210_planar_pack_8
+INIT_XMM avx
+v210_planar_pack_8
diff --git a/libavcodec/x86/v210enc_init.c b/libavcodec/x86/v210enc_init.c
new file mode 100644
index 0000000..3ac498a
--- /dev/null
+++ b/libavcodec/x86/v210enc_init.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/x86/cpu.h"
+#include "libavcodec/v210enc.h"
+
+void ff_v210_planar_pack_8_ssse3(const uint8_t *y, const uint8_t *u, const uint8_t *v, uint8_t *dst, ptrdiff_t width);
+void ff_v210_planar_pack_8_avx(const uint8_t *y, const uint8_t *u, const uint8_t *v, uint8_t *dst, ptrdiff_t width);
+void ff_v210_planar_pack_10_ssse3(const uint16_t *y, const uint16_t *u, const uint16_t *v, uint8_t *dst, ptrdiff_t width);
+
+av_cold void ff_v210enc_init_x86(V210EncContext *s)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if( EXTERNAL_SSSE3(cpu_flags) ) {
+        s->pack_line_8 = ff_v210_planar_pack_8_ssse3;
+        s->pack_line_10 = ff_v210_planar_pack_10_ssse3;
+    }
+
+    if( EXTERNAL_AVX(cpu_flags) )
+        s->pack_line_8 = ff_v210_planar_pack_8_avx;
+}
diff --git a/libavcodec/xface.h b/libavcodec/xface.h
index cd59ba0..63df5d3 100644
--- a/libavcodec/xface.h
+++ b/libavcodec/xface.h
@@ -40,11 +40,12 @@
 
 /*
  * Image is encoded as a big integer, using characters from '~' to
- * '!', for a total of 92 symbols. In order to express 48x48=2304
- * bits, we need a total of 354 digits, as given by:
- * ceil(lg_92(2^2304)) = 354
+ * '!', for a total of 94 symbols. In order to express
+ * 48x48*2=8*XFACE_MAX_WORDS=4608
+ * bits, we need a total of 704 digits, as given by:
+ * ceil(lg_94(2^4608)) = 704
  */
-#define XFACE_MAX_DIGITS 354
+#define XFACE_MAX_DIGITS 704
 
 #define XFACE_BITSPERWORD 8
 #define XFACE_WORDCARRY (1 << XFACE_BITSPERWORD)
@@ -84,8 +85,8 @@
  * The probability of the data determines the range of possible encodings.
  * Offset gives the first possible encoding of the range. */
 typedef struct {
-    int range;
-    int offset;
+    uint8_t range;
+    uint8_t offset;
 } ProbRange;
 
 extern const ProbRange ff_xface_probranges_per_level[4][3];
diff --git a/libavcodec/xfaceenc.c b/libavcodec/xfaceenc.c
index e213c9d..7edef1e 100644
--- a/libavcodec/xfaceenc.c
+++ b/libavcodec/xfaceenc.c
@@ -27,6 +27,7 @@
 #include "xface.h"
 #include "avcodec.h"
 #include "internal.h"
+#include "libavutil/avassert.h"
 
 typedef struct XFaceContext {
     AVClass *class;
@@ -73,7 +74,7 @@
 }
 
 typedef struct {
-    const ProbRange *prob_ranges[XFACE_PIXELS*2];
+    ProbRange prob_ranges[XFACE_PIXELS*2];
     int prob_ranges_idx;
 } ProbRangesQueue;
 
@@ -81,7 +82,7 @@
 {
     if (pq->prob_ranges_idx >= XFACE_PIXELS * 2 - 1)
         return -1;
-    pq->prob_ranges[pq->prob_ranges_idx++] = p;
+    pq->prob_ranges[pq->prob_ranges_idx++] = *p;
     return 0;
 }
 
@@ -146,7 +147,7 @@
                               const AVFrame *frame, int *got_packet)
 {
     XFaceContext *xface = avctx->priv_data;
-    ProbRangesQueue pq = {{ 0 }, 0};
+    ProbRangesQueue pq = {{{ 0 }}, 0};
     uint8_t bitmap_copy[XFACE_PIXELS];
     BigInt b = {0};
     int i, j, k, ret = 0;
@@ -192,13 +193,15 @@
     encode_block(xface->bitmap + XFACE_WIDTH * 32 + 32, 16, 16, 0, &pq);
 
     while (pq.prob_ranges_idx > 0)
-        push_integer(&b, pq.prob_ranges[--pq.prob_ranges_idx]);
+        push_integer(&b, &pq.prob_ranges[--pq.prob_ranges_idx]);
 
     /* write the inverted big integer in b to intbuf */
     i = 0;
+    av_assert0(b.nb_words < XFACE_MAX_WORDS);
     while (b.nb_words) {
         uint8_t r;
         ff_big_div(&b, XFACE_PRINTS, &r);
+        av_assert0(i < sizeof(intbuf));
         intbuf[i++] = r + XFACE_FIRST_PRINT;
     }
 
diff --git a/libavcodec/xiph.c b/libavcodec/xiph.c
index e63cec8..49b978d 100644
--- a/libavcodec/xiph.c
+++ b/libavcodec/xiph.c
@@ -21,7 +21,7 @@
 #include "libavutil/intreadwrite.h"
 #include "xiph.h"
 
-int avpriv_split_xiph_headers(uint8_t *extradata, int extradata_size,
+int avpriv_split_xiph_headers(const uint8_t *extradata, int extradata_size,
                           int first_header_size, uint8_t *header_start[3],
                           int header_len[3])
 {
diff --git a/libavcodec/xiph.h b/libavcodec/xiph.h
index 5c4dcc4..b8ddbbe 100644
--- a/libavcodec/xiph.h
+++ b/libavcodec/xiph.h
@@ -36,7 +36,7 @@
  * @param[out] header_len The sizes of each of the three headers.
  * @return On error a negative value is returned, on success zero.
  */
-int avpriv_split_xiph_headers(uint8_t *extradata, int extradata_size,
+int avpriv_split_xiph_headers(const uint8_t *extradata, int extradata_size,
                               int first_header_size, uint8_t *header_start[3],
                               int header_len[3]);
 
diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index e44c88a..6b8ab2e 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -35,7 +35,7 @@
 OBJS-$(CONFIG_OSS_INDEV)                 += oss_audio.o oss_audio_dec.o
 OBJS-$(CONFIG_OSS_OUTDEV)                += oss_audio.o oss_audio_enc.o
 OBJS-$(CONFIG_PULSE_INDEV)               += pulse_audio_dec.o \
-                                            pulse_audio_common.o
+                                            pulse_audio_common.o timefilter.o
 OBJS-$(CONFIG_PULSE_OUTDEV)              += pulse_audio_enc.o \
                                             pulse_audio_common.o
 OBJS-$(CONFIG_QTKIT_INDEV)               += qtkit.o
diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa-audio-common.c
index 4e63397..749897f 100644
--- a/libavdevice/alsa-audio-common.c
+++ b/libavdevice/alsa-audio-common.c
@@ -343,3 +343,55 @@
     s->reorder_buf_size = size;
     return 0;
 }
+
+/* ported from alsa-utils/aplay.c */
+int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type)
+{
+    int ret = 0;
+    void **hints, **n;
+    char *name = NULL, *descr = NULL, *io = NULL, *tmp;
+    AVDeviceInfo *new_device = NULL;
+    const char *filter = stream_type == SND_PCM_STREAM_PLAYBACK ? "Output" : "Input";
+
+    if (snd_device_name_hint(-1, "pcm", &hints) < 0)
+        return AVERROR_EXTERNAL;
+    n = hints;
+    while (*n && !ret) {
+        name = snd_device_name_get_hint(*n, "NAME");
+        descr = snd_device_name_get_hint(*n, "DESC");
+        io = snd_device_name_get_hint(*n, "IOID");
+        if (!io || !strcmp(io, filter)) {
+            new_device = av_mallocz(sizeof(AVDeviceInfo));
+            if (!new_device) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            new_device->device_name = av_strdup(name);
+            if ((tmp = strrchr(descr, '\n')) && tmp[1])
+                new_device->device_description = av_strdup(&tmp[1]);
+            else
+                new_device->device_description = av_strdup(descr);
+            if (!new_device->device_description || !new_device->device_name) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            if ((ret = av_dynarray_add_nofree(&device_list->devices,
+                                              &device_list->nb_devices, new_device)) < 0) {
+                goto fail;
+            }
+            new_device = NULL;
+        }
+      fail:
+        free(io);
+        free(name);
+        free(descr);
+        n++;
+    }
+    if (new_device) {
+        av_free(new_device->device_description);
+        av_free(new_device->device_name);
+        av_free(new_device);
+    }
+    snd_device_name_free_hint(hints);
+    return ret;
+}
diff --git a/libavdevice/alsa-audio-dec.c b/libavdevice/alsa-audio-dec.c
index 2cdf356..7f8f8cd 100644
--- a/libavdevice/alsa-audio-dec.c
+++ b/libavdevice/alsa-audio-dec.c
@@ -132,6 +132,11 @@
     return 0;
 }
 
+static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
+{
+    return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_CAPTURE);
+}
+
 static const AVOption options[] = {
     { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
     { "channels",    "", offsetof(AlsaData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
@@ -153,6 +158,7 @@
     .read_header    = audio_read_header,
     .read_packet    = audio_read_packet,
     .read_close     = ff_alsa_close,
+    .get_device_list = audio_get_device_list,
     .flags          = AVFMT_NOFILE,
     .priv_class     = &alsa_demuxer_class,
 };
diff --git a/libavdevice/alsa-audio-enc.c b/libavdevice/alsa-audio-enc.c
index e42cc8f..43d097d 100644
--- a/libavdevice/alsa-audio-enc.c
+++ b/libavdevice/alsa-audio-enc.c
@@ -142,6 +142,11 @@
     *dts = s->timestamp - delay;
 }
 
+static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
+{
+    return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_PLAYBACK);
+}
+
 static const AVClass alsa_muxer_class = {
     .class_name     = "ALSA muxer",
     .item_name      = av_default_item_name,
@@ -159,6 +164,7 @@
     .write_packet   = audio_write_packet,
     .write_trailer  = ff_alsa_close,
     .write_uncoded_frame = audio_write_frame,
+    .get_device_list = audio_get_device_list,
     .get_output_timestamp = audio_get_output_timestamp,
     .flags          = AVFMT_NOFILE,
     .priv_class     = &alsa_muxer_class,
diff --git a/libavdevice/alsa-audio.h b/libavdevice/alsa-audio.h
index 583c911..cf0e942 100644
--- a/libavdevice/alsa-audio.h
+++ b/libavdevice/alsa-audio.h
@@ -99,4 +99,6 @@
 
 int ff_alsa_extend_reorder_buf(AlsaData *s, int size);
 
+int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type);
+
 #endif /* AVDEVICE_ALSA_AUDIO_H */
diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c
index 6a75bd7..755f251 100644
--- a/libavdevice/avdevice.c
+++ b/libavdevice/avdevice.c
@@ -219,11 +219,11 @@
     for (i = 0; i < list->nb_devices; i++) {
         dev = list->devices[i];
         if (dev) {
-            av_free(dev->device_name);
-            av_free(dev->device_description);
+            av_freep(&dev->device_name);
+            av_freep(&dev->device_description);
             av_free(dev);
         }
     }
-    av_free(list->devices);
+    av_freep(&list->devices);
     av_freep(device_list);
 }
diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 5e5f70b..1a7eb5b 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -30,6 +30,7 @@
 
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
+#include "libavutil/avstring.h"
 #include "libavformat/internal.h"
 #include "libavutil/internal.h"
 #include "libavutil/time.h"
@@ -80,7 +81,6 @@
 {
     AVClass*        class;
 
-    float           frame_rate;
     int             frames_captured;
     int             audio_frames_captured;
     int64_t         first_pts;
@@ -253,12 +253,13 @@
 {
     AVFContext *ctx = (AVFContext*)s->priv_data;
     char *tmp = av_strdup(s->filename);
+    char *save;
 
     if (tmp[0] != ':') {
-        ctx->video_filename = strtok(tmp,  ":");
-        ctx->audio_filename = strtok(NULL, ":");
+        ctx->video_filename = av_strtok(tmp,  ":", &save);
+        ctx->audio_filename = av_strtok(NULL, ":", &save);
     } else {
-        ctx->audio_filename = strtok(tmp,  ":");
+        ctx->audio_filename = av_strtok(tmp,  ":", &save);
     }
 }
 
@@ -603,7 +604,10 @@
             goto fail;
         }
     } else if (ctx->video_filename &&
-               strncmp(ctx->video_filename, "default", 7)) {
+               strncmp(ctx->video_filename, "none", 4)) {
+        if (!strncmp(ctx->video_filename, "default", 7)) {
+            video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
+        } else {
         // looking for video inputs
         for (AVCaptureDevice *device in video_devices) {
             if (!strncmp(ctx->video_filename, [[device localizedName] UTF8String], strlen(ctx->video_filename))) {
@@ -625,13 +629,12 @@
             }
         }
 #endif
+        }
 
         if (!video_device) {
             av_log(ctx, AV_LOG_ERROR, "Video device not found\n");
             goto fail;
         }
-    } else {
-        video_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
     }
 
     // get audio device
@@ -645,7 +648,10 @@
 
         audio_device = [devices objectAtIndex:ctx->audio_device_index];
     } else if (ctx->audio_filename &&
-               strncmp(ctx->audio_filename, "default", 7)) {
+               strncmp(ctx->audio_filename, "none", 4)) {
+        if (!strncmp(ctx->audio_filename, "default", 7)) {
+            audio_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
+        } else {
         NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio];
 
         for (AVCaptureDevice *device in devices) {
@@ -654,13 +660,12 @@
                 break;
             }
         }
+        }
 
         if (!audio_device) {
             av_log(ctx, AV_LOG_ERROR, "Audio device not found\n");
              goto fail;
         }
-    } else {
-        audio_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
     }
 
     // Video nor Audio capture device not found, looking for AVMediaTypeVideo/Audio
@@ -821,7 +826,6 @@
 }
 
 static const AVOption options[] = {
-    { "frame_rate", "set frame rate", offsetof(AVFContext, frame_rate), AV_OPT_TYPE_FLOAT, { .dbl = 30.0 }, 0.1, 30.0, AV_OPT_TYPE_VIDEO_RATE, NULL },
     { "list_devices", "list available devices", offsetof(AVFContext, list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
     { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
     { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h
index 544da27..96912a7 100644
--- a/libavdevice/decklink_common.h
+++ b/libavdevice/decklink_common.h
@@ -84,7 +84,6 @@
 #ifdef _WIN32
 typedef unsigned long buffercount_type;
 IDeckLinkIterator *CreateDeckLinkIteratorInstance(void);
-char *dup_wchar_to_utf8(wchar_t *w);
 #else
 typedef uint32_t buffercount_type;
 #endif
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index a543249..59d0818 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -19,13 +19,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "dshow_capture.h"
 #include "libavutil/parseutils.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/opt.h"
 #include "libavformat/internal.h"
 #include "libavformat/riff.h"
 #include "avdevice.h"
-#include "dshow_capture.h"
 #include "libavcodec/raw.h"
 
 struct dshow_ctx {
diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h
index e4b4dce..0252070 100644
--- a/libavdevice/dshow_capture.h
+++ b/libavdevice/dshow_capture.h
@@ -27,6 +27,7 @@
 #include "avdevice.h"
 
 #define COBJMACROS
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #define NO_DSHOW_STRSAFE
 #include <dshow.h>
diff --git a/libavdevice/fbdev_common.c b/libavdevice/fbdev_common.c
index 713e4fd..98f96de 100644
--- a/libavdevice/fbdev_common.c
+++ b/libavdevice/fbdev_common.c
@@ -121,8 +121,8 @@
 
       fail_device:
         if (device) {
-            av_free(device->device_name);
-            av_free(device->device_description);
+            av_freep(&device->device_name);
+            av_freep(&device->device_description);
             av_freep(&device);
         }
         if (fd >= 0)
diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c
index 6d5ec4a..0900ffa 100644
--- a/libavdevice/iec61883.c
+++ b/libavdevice/iec61883.c
@@ -219,8 +219,8 @@
         size = avpriv_mpegts_parse_packet(dv->mpeg_demux, pkt, packet->buf,
                                           packet->len);
         dv->queue_first = packet->next;
-        av_free(packet->buf);
-        av_free(packet);
+        av_freep(&packet->buf);
+        av_freep(&packet);
         dv->packets--;
 
         if (size > 0)
@@ -455,8 +455,8 @@
     while (dv->queue_first) {
         DVPacket *packet = dv->queue_first;
         dv->queue_first = packet->next;
-        av_free(packet->buf);
-        av_free(packet);
+        av_freep(&packet->buf);
+        av_freep(&packet);
     }
 
     iec61883_cmp_disconnect(dv->raw1394, dv->node, dv->output_port,
diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c
index 5f5b800..434ae97 100644
--- a/libavdevice/opengl_enc.c
+++ b/libavdevice/opengl_enc.c
@@ -31,6 +31,7 @@
 #include "config.h"
 
 #if HAVE_WINDOWS_H
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 #if HAVE_OPENGL_GL3_H
diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c
index 4eb6a50..1f8b5e7 100644
--- a/libavdevice/oss_audio.c
+++ b/libavdevice/oss_audio.c
@@ -49,14 +49,13 @@
     int audio_fd;
     int tmp, err;
     char *flip = getenv("AUDIO_FLIP_LEFT");
-    char errbuff[128];
 
     if (is_output)
         audio_fd = avpriv_open(audio_device, O_WRONLY);
     else
         audio_fd = avpriv_open(audio_device, O_RDONLY);
     if (audio_fd < 0) {
-        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
+        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, av_err2str(AVERROR(errno)));
         return AVERROR(EIO);
     }
 
@@ -67,7 +66,7 @@
     /* non blocking mode */
     if (!is_output) {
         if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
-            av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, strerror(errno));
+            av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, av_err2str(AVERROR(errno)));
         }
     }
 
@@ -75,8 +74,7 @@
 
 #define CHECK_IOCTL_ERROR(event)                                              \
     if (err < 0) {                                                            \
-        av_strerror(AVERROR(errno), errbuff, sizeof(errbuff));                \
-        av_log(s1, AV_LOG_ERROR, #event ": %s\n", errbuff);                   \
+        av_log(s1, AV_LOG_ERROR, #event ": %s\n", av_err2str(AVERROR(errno)));\
         goto fail;                                                            \
     }
 
@@ -86,7 +84,7 @@
      * fail anyway. */
     err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
     if (err < 0) {
-        av_log(s1, AV_LOG_WARNING, "SNDCTL_DSP_GETFMTS: %s\n", strerror(errno));
+        av_log(s1, AV_LOG_WARNING, "SNDCTL_DSP_GETFMTS: %s\n", av_err2str(AVERROR(errno)));
     }
 
 #if HAVE_BIGENDIAN
diff --git a/libavdevice/pulse_audio_common.c b/libavdevice/pulse_audio_common.c
index 5a2568b..4046641 100644
--- a/libavdevice/pulse_audio_common.c
+++ b/libavdevice/pulse_audio_common.c
@@ -163,8 +163,8 @@
     return;
 
   fail:
-    av_free(new_device->device_description);
-    av_free(new_device->device_name);
+    av_freep(&new_device->device_description);
+    av_freep(&new_device->device_name);
     av_free(new_device);
 
 }
diff --git a/libavdevice/v4l2-common.c b/libavdevice/v4l2-common.c
index 966b9a1..196c09b 100644
--- a/libavdevice/v4l2-common.c
+++ b/libavdevice/v4l2-common.c
@@ -46,6 +46,9 @@
 #ifdef V4L2_PIX_FMT_H264
     { AV_PIX_FMT_NONE,    AV_CODEC_ID_H264,     V4L2_PIX_FMT_H264    },
 #endif
+#ifdef V4L2_PIX_FMT_MPEG4
+    { AV_PIX_FMT_NONE,    AV_CODEC_ID_MPEG4,    V4L2_PIX_FMT_MPEG4   },
+#endif
 #ifdef V4L2_PIX_FMT_CPIA1
     { AV_PIX_FMT_NONE,    AV_CODEC_ID_CPIA,     V4L2_PIX_FMT_CPIA1   },
 #endif
diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c
index bd72d3d..8695645 100644
--- a/libavdevice/v4l2.c
+++ b/libavdevice/v4l2.c
@@ -67,7 +67,7 @@
 struct video_data {
     AVClass *class;
     int fd;
-    int frame_format; /* V4L2_PIX_FMT_* */
+    int pixelformat; /* V4L2_PIX_FMT_* */
     int width, height;
     int frame_size;
     int interlaced;
@@ -108,7 +108,7 @@
     struct video_data *s = ctx->priv_data;
     struct v4l2_capability cap;
     int fd;
-    int ret;
+    int err;
     int flags = O_RDWR;
 
 #define SET_WRAPPERS(prefix) do {       \
@@ -146,16 +146,16 @@
 
     fd = v4l2_open(ctx->filename, flags, 0);
     if (fd < 0) {
-        ret = AVERROR(errno);
+        err = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s: %s\n",
-               ctx->filename, av_err2str(ret));
-        return ret;
+               ctx->filename, av_err2str(err));
+        return err;
     }
 
     if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
-        ret = AVERROR(errno);
+        err = AVERROR(errno);
         av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n",
-               av_err2str(ret));
+               av_err2str(err));
         goto fail;
     }
 
@@ -164,14 +164,14 @@
 
     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
         av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n");
-        ret = AVERROR(ENODEV);
+        err = AVERROR(ENODEV);
         goto fail;
     }
 
     if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
         av_log(ctx, AV_LOG_ERROR,
                "The device does not support the streaming I/O method.\n");
-        ret = AVERROR(ENOSYS);
+        err = AVERROR(ENOSYS);
         goto fail;
     }
 
@@ -179,22 +179,23 @@
 
 fail:
     v4l2_close(fd);
-    return ret;
+    return err;
 }
 
 static int device_init(AVFormatContext *ctx, int *width, int *height,
-                       uint32_t pix_fmt)
+                       uint32_t pixelformat)
 {
     struct video_data *s = ctx->priv_data;
     struct v4l2_format fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE };
-    struct v4l2_pix_format *pix = &fmt.fmt.pix;
     int res = 0;
 
-    pix->width = *width;
-    pix->height = *height;
-    pix->pixelformat = pix_fmt;
-    pix->field = V4L2_FIELD_ANY;
+    fmt.fmt.pix.width = *width;
+    fmt.fmt.pix.height = *height;
+    fmt.fmt.pix.pixelformat = pixelformat;
+    fmt.fmt.pix.field = V4L2_FIELD_ANY;
 
+    /* Some drivers will fail and return EINVAL when the pixelformat
+       is not supported (even if type field is valid and supported) */
     if (v4l2_ioctl(s->fd, VIDIOC_S_FMT, &fmt) < 0)
         res = AVERROR(errno);
 
@@ -206,11 +207,11 @@
         *height = fmt.fmt.pix.height;
     }
 
-    if (pix_fmt != fmt.fmt.pix.pixelformat) {
+    if (pixelformat != fmt.fmt.pix.pixelformat) {
         av_log(ctx, AV_LOG_DEBUG,
                "The V4L2 driver changed the pixel format "
                "from 0x%08X to 0x%08X\n",
-               pix_fmt, fmt.fmt.pix.pixelformat);
+               pixelformat, fmt.fmt.pix.pixelformat);
         res = AVERROR(EINVAL);
     }
 
@@ -505,7 +506,8 @@
             return AVERROR(EAGAIN);
         }
         res = AVERROR(errno);
-        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", av_err2str(res));
+        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n",
+               av_err2str(res));
         return res;
     }
 
@@ -601,7 +603,8 @@
 
         if (v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf) < 0) {
             res = AVERROR(errno);
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", av_err2str(res));
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n",
+                   av_err2str(res));
             return res;
         }
     }
@@ -610,7 +613,8 @@
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     if (v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type) < 0) {
         res = AVERROR(errno);
-        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", av_err2str(res));
+        av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n",
+               av_err2str(res));
         return res;
     }
 
@@ -727,7 +731,8 @@
 
             if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) < 0) {
                 ret = AVERROR(errno);
-                av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_S_PARM): %s\n", av_err2str(ret));
+                av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_S_PARM): %s\n",
+                       av_err2str(ret));
                 return ret;
             }
 
@@ -880,9 +885,6 @@
 
     avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
 
-    if ((res = v4l2_set_parameters(ctx)) < 0)
-        goto fail;
-
     if (s->pixel_format) {
         AVCodec *codec = avcodec_find_decoder_by_name(s->pixel_format);
 
@@ -907,7 +909,8 @@
                "Querying the device for the current frame size\n");
         if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) {
             res = AVERROR(errno);
-            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", av_err2str(res));
+            av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n",
+                   av_err2str(res));
             goto fail;
         }
 
@@ -931,7 +934,10 @@
     if ((res = av_image_check_size(s->width, s->height, 0, ctx)) < 0)
         goto fail;
 
-    s->frame_format = desired_format;
+    s->pixelformat = desired_format;
+
+    if ((res = v4l2_set_parameters(ctx)) < 0)
+        goto fail;
 
     st->codec->pix_fmt = ff_fmt_v4l2ff(desired_format, codec_id);
     s->frame_size =
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 630f654..3e427f0 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -28,7 +28,7 @@
 #include "libavutil/version.h"
 
 #define LIBAVDEVICE_VERSION_MAJOR 56
-#define LIBAVDEVICE_VERSION_MINOR  2
+#define LIBAVDEVICE_VERSION_MINOR  3
 #define LIBAVDEVICE_VERSION_MICRO 100
 
 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c
index 4909588..df8de20 100644
--- a/libavdevice/xcbgrab.c
+++ b/libavdevice/xcbgrab.c
@@ -33,6 +33,10 @@
 #include <xcb/shm.h>
 #endif
 
+#if CONFIG_LIBXCB_SHAPE
+#include <xcb/shape.h>
+#endif
+
 #include "libavformat/avformat.h"
 #include "libavformat/internal.h"
 
@@ -47,7 +51,9 @@
     xcb_connection_t *conn;
     xcb_screen_t *screen;
     xcb_window_t window;
+#if CONFIG_LIBXCB_SHM
     xcb_shm_seg_t segment;
+#endif
 
     int64_t time_frame;
     AVRational time_base;
@@ -489,7 +495,6 @@
 {
     XCBGrabContext *c = s->priv_data;
     AVStream *st      = avformat_new_stream(s, NULL);
-    const char *opts  = strchr(s->filename, '+');
     xcb_get_geometry_cookie_t gc;
     xcb_get_geometry_reply_t *geo;
     int ret;
@@ -505,9 +510,6 @@
     if (ret < 0)
         return ret;
 
-    if (opts)
-        sscanf(opts, "%d,%d", &c->x, &c->y);
-
     avpriv_set_pts_info(st, 64, 1, 1000000);
 
     gc  = xcb_get_geometry(c->conn, c->screen->root);
@@ -578,11 +580,13 @@
                       XCB_COPY_FROM_PARENT,
                       mask, values);
 
+#if CONFIG_LIBXCB_SHAPE
     xcb_shape_rectangles(c->conn, XCB_SHAPE_SO_SUBTRACT,
                          XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
                          c->window,
                          c->region_border, c->region_border,
                          1, &rect);
+#endif
 
     xcb_map_window(c->conn, c->window);
 
@@ -594,11 +598,21 @@
     XCBGrabContext *c = s->priv_data;
     int screen_num, ret;
     const xcb_setup_t *setup;
+    char *display_name = av_strdup(s->filename);
 
-    c->conn = xcb_connect(s->filename, &screen_num);
+    if (!display_name)
+        return AVERROR(ENOMEM);
+
+    if (!sscanf(s->filename, "%[^+]+%d,%d", display_name, &c->x, &c->y)) {
+        *display_name = 0;
+        sscanf(s->filename, "+%d,%d", &c->x, &c->y);
+    }
+
+    c->conn = xcb_connect(display_name, &screen_num);
+    av_freep(&display_name);
     if ((ret = xcb_connection_has_error(c->conn))) {
         av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n",
-               s->filename ? s->filename : "default", ret);
+               (*s->filename) ? s->filename : "default", ret);
         return AVERROR(EIO);
     }
     setup = xcb_get_setup(c->conn);
@@ -611,7 +625,9 @@
         return AVERROR(EIO);
     }
 
+#if CONFIG_LIBXCB_SHM
     c->segment = xcb_generate_id(c->conn);
+#endif
 
     ret = create_stream(s);
 
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 6d868e7..2c56e38 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -198,6 +198,7 @@
 OBJS-$(CONFIG_VIDSTABTRANSFORM_FILTER)       += vidstabutils.o vf_vidstabtransform.o
 OBJS-$(CONFIG_VIGNETTE_FILTER)               += vf_vignette.o
 OBJS-$(CONFIG_W3FDIF_FILTER)                 += vf_w3fdif.o
+OBJS-$(CONFIG_XBR_FILTER)                    += vf_xbr.o
 OBJS-$(CONFIG_YADIF_FILTER)                  += vf_yadif.o
 OBJS-$(CONFIG_ZMQ_FILTER)                    += f_zmq.o
 OBJS-$(CONFIG_ZOOMPAN_FILTER)                += vf_zoompan.o
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c
index 47cbb45..e40969f 100644
--- a/libavfilter/af_amix.c
+++ b/libavfilter/af_amix.c
@@ -155,7 +155,7 @@
 
 typedef struct MixContext {
     const AVClass *class;       /**< class for AVOptions */
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
 
     int nb_inputs;              /**< number of inputs */
     int active_inputs;          /**< number of input currently active */
@@ -298,7 +298,7 @@
             plane_size = FFALIGN(plane_size, 16);
 
             for (p = 0; p < planes; p++) {
-                s->fdsp.vector_fmac_scalar((float *)out_buf->extended_data[p],
+                s->fdsp->vector_fmac_scalar((float *)out_buf->extended_data[p],
                                            (float *) in_buf->extended_data[p],
                                            s->input_scale[i], plane_size);
             }
@@ -501,7 +501,9 @@
         ff_insert_inpad(ctx, i, &pad);
     }
 
-    avpriv_float_dsp_init(&s->fdsp, 0);
+    s->fdsp = avpriv_float_dsp_alloc(0);
+    if (!s->fdsp)
+        return AVERROR(ENOMEM);
 
     return 0;
 }
@@ -520,6 +522,7 @@
     av_freep(&s->frame_list);
     av_freep(&s->input_state);
     av_freep(&s->input_scale);
+    av_freep(&s->fdsp);
 
     for (i = 0; i < ctx->nb_inputs; i++)
         av_freep(&ctx->input_pads[i].name);
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index 8a8b386..57ac397 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -41,6 +41,7 @@
     struct SwrContext *swr;
     int64_t next_pts;
     int req_fullfilled;
+    int more_data;
 } AResampleContext;
 
 static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts)
@@ -186,7 +187,7 @@
 
     delay = swr_get_delay(aresample->swr, outlink->sample_rate);
     if (delay > 0)
-        n_out += delay;
+        n_out += FFMIN(delay, FFMAX(4096, n_out));
 
     outsamplesref = ff_get_audio_buffer(outlink, n_out);
 
@@ -215,6 +216,8 @@
         return 0;
     }
 
+    aresample->more_data = outsamplesref->nb_samples == n_out; // Indicate that there is probably more data in our buffers
+
     outsamplesref->nb_samples  = n_out;
 
     ret = ff_filter_frame(outlink, outsamplesref);
@@ -223,40 +226,65 @@
     return ret;
 }
 
-static int request_frame(AVFilterLink *outlink)
+static int flush_frame(AVFilterLink *outlink, int final, AVFrame **outsamplesref_ret)
 {
     AVFilterContext *ctx = outlink->src;
     AResampleContext *aresample = ctx->priv;
     AVFilterLink *const inlink = outlink->src->inputs[0];
+    AVFrame *outsamplesref;
+    int n_out = 4096;
+    int64_t pts;
+
+    outsamplesref = ff_get_audio_buffer(outlink, n_out);
+    *outsamplesref_ret = outsamplesref;
+    if (!outsamplesref)
+        return AVERROR(ENOMEM);
+
+    pts = swr_next_pts(aresample->swr, INT64_MIN);
+    pts = ROUNDED_DIV(pts, inlink->sample_rate);
+
+    n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, final ? NULL : (void*)outsamplesref->extended_data, 0);
+    if (n_out <= 0) {
+        av_frame_free(&outsamplesref);
+        return (n_out == 0) ? AVERROR_EOF : n_out;
+    }
+
+    outsamplesref->sample_rate = outlink->sample_rate;
+    outsamplesref->nb_samples  = n_out;
+
+    outsamplesref->pts = pts;
+
+    return 0;
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AResampleContext *aresample = ctx->priv;
     int ret;
 
+    // First try to get data from the internal buffers
+    if (aresample->more_data) {
+        AVFrame *outsamplesref;
+
+        if (flush_frame(outlink, 0, &outsamplesref) >= 0) {
+            return ff_filter_frame(outlink, outsamplesref);
+        }
+    }
+    aresample->more_data = 0;
+
+    // Second request more data from the input
     aresample->req_fullfilled = 0;
     do{
         ret = ff_request_frame(ctx->inputs[0]);
     }while(!aresample->req_fullfilled && ret>=0);
 
+    // Third if we hit the end flush
     if (ret == AVERROR_EOF) {
         AVFrame *outsamplesref;
-        int n_out = 4096;
-        int64_t pts;
 
-        outsamplesref = ff_get_audio_buffer(outlink, n_out);
-        if (!outsamplesref)
-            return AVERROR(ENOMEM);
-
-        pts = swr_next_pts(aresample->swr, INT64_MIN);
-        pts = ROUNDED_DIV(pts, inlink->sample_rate);
-
-        n_out = swr_convert(aresample->swr, outsamplesref->extended_data, n_out, 0, 0);
-        if (n_out <= 0) {
-            av_frame_free(&outsamplesref);
-            return (n_out == 0) ? AVERROR_EOF : n_out;
-        }
-
-        outsamplesref->sample_rate = outlink->sample_rate;
-        outsamplesref->nb_samples  = n_out;
-
-        outsamplesref->pts = pts;
+        if ((ret = flush_frame(outlink, 1, &outsamplesref)) < 0)
+            return ret;
 
         return ff_filter_frame(outlink, outsamplesref);
     }
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 9900d22..4809ae7 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -111,6 +111,11 @@
 static av_cold int init(AVFilterContext *ctx)
 {
     VolumeContext *vol = ctx->priv;
+
+    vol->fdsp = avpriv_float_dsp_alloc(0);
+    if (!vol->fdsp)
+        return AVERROR(ENOMEM);
+
     return set_expr(&vol->volume_pexpr, vol->volume_expr, ctx);
 }
 
@@ -119,6 +124,7 @@
     VolumeContext *vol = ctx->priv;
     av_expr_free(vol->volume_pexpr);
     av_opt_free(vol);
+    av_freep(&vol->fdsp);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -233,11 +239,9 @@
         vol->scale_samples = scale_samples_s32;
         break;
     case AV_SAMPLE_FMT_FLT:
-        avpriv_float_dsp_init(&vol->fdsp, 0);
         vol->samples_align = 4;
         break;
     case AV_SAMPLE_FMT_DBL:
-        avpriv_float_dsp_init(&vol->fdsp, 0);
         vol->samples_align = 8;
         break;
     }
@@ -428,13 +432,13 @@
             }
         } else if (av_get_packed_sample_fmt(vol->sample_fmt) == AV_SAMPLE_FMT_FLT) {
             for (p = 0; p < vol->planes; p++) {
-                vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p],
+                vol->fdsp->vector_fmul_scalar((float *)out_buf->extended_data[p],
                                              (const float *)buf->extended_data[p],
                                              vol->volume, plane_samples);
             }
         } else {
             for (p = 0; p < vol->planes; p++) {
-                vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p],
+                vol->fdsp->vector_dmul_scalar((double *)out_buf->extended_data[p],
                                              (const double *)buf->extended_data[p],
                                              vol->volume, plane_samples);
             }
diff --git a/libavfilter/af_volume.h b/libavfilter/af_volume.h
index e78e042..53a328e 100644
--- a/libavfilter/af_volume.h
+++ b/libavfilter/af_volume.h
@@ -67,7 +67,7 @@
 
 typedef struct VolumeContext {
     const AVClass *class;
-    AVFloatDSPContext fdsp;
+    AVFloatDSPContext *fdsp;
     enum PrecisionType precision;
     enum EvalMode eval_mode;
     const char *volume_expr;
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index d88a9ad..2352d44 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -213,6 +213,7 @@
     REGISTER_FILTER(VIDSTABTRANSFORM, vidstabtransform, vf);
     REGISTER_FILTER(VIGNETTE,       vignette,       vf);
     REGISTER_FILTER(W3FDIF,         w3fdif,         vf);
+    REGISTER_FILTER(XBR,            xbr,            vf);
     REGISTER_FILTER(YADIF,          yadif,          vf);
     REGISTER_FILTER(ZMQ,            zmq,            vf);
     REGISTER_FILTER(ZOOMPAN,        zoompan,        vf);
diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c
index 266bb36..088d782 100644
--- a/libavfilter/avf_concat.c
+++ b/libavfilter/avf_concat.c
@@ -409,7 +409,7 @@
     }
     for (i = 0; i < ctx->nb_outputs; i++)
         av_freep(&ctx->output_pads[i].name);
-    av_free(cat->in);
+    av_freep(&cat->in);
 }
 
 AVFilter ff_avf_concat = {
diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c
index 4cd225a..fa34a52 100644
--- a/libavfilter/avf_showwaves.c
+++ b/libavfilter/avf_showwaves.c
@@ -157,7 +157,7 @@
         showwaves->req_fullfilled = 1;
     showwaves->outpicref = NULL;
     showwaves->buf_idx = 0;
-    for (i = 0; i <= nb_channels; i++)
+    for (i = 0; i < nb_channels; i++)
         showwaves->buf_idy[i] = 0;
     return ret;
 }
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 8160429..eb3b87a 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -314,14 +314,18 @@
 #define ADD_FORMAT(f, fmt, type, list, nb)                  \
 do {                                                        \
     type *fmts;                                             \
+    void *oldf = *f;                                        \
                                                             \
     if (!(*f) && !(*f = av_mallocz(sizeof(**f))))           \
         return AVERROR(ENOMEM);                             \
                                                             \
     fmts = av_realloc((*f)->list,                           \
                       sizeof(*(*f)->list) * ((*f)->nb + 1));\
-    if (!fmts)                                              \
+    if (!fmts) {                                            \
+        if (!oldf)                                          \
+            av_freep(f);                                    \
         return AVERROR(ENOMEM);                             \
+    }                                                       \
                                                             \
     (*f)->list = fmts;                                      \
     (*f)->list[(*f)->nb++] = fmt;                           \
@@ -490,7 +494,7 @@
 }
 
 #define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
-{                                                                   \
+if (fmts) {                                                         \
     int count = 0, i;                                               \
                                                                     \
     for (i = 0; i < ctx->nb_inputs; i++) {                          \
diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c
index 7e25282..5180bd5 100644
--- a/libavfilter/graphparser.c
+++ b/libavfilter/graphparser.c
@@ -241,8 +241,8 @@
 
         if (p->filter_ctx) {
             ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx);
-            av_free(p->name);
-            av_free(p);
+            av_freep(&p->name);
+            av_freep(&p);
             if (ret < 0)
                 return ret;
         } else {
@@ -344,10 +344,10 @@
                 av_free(name);
                 return ret;
             }
-            av_free(match->name);
-            av_free(name);
-            av_free(match);
-            av_free(input);
+            av_freep(&match->name);
+            av_freep(&name);
+            av_freep(&match);
+            av_freep(&input);
         } else {
             /* Not in the list, so add the first input as a open_output */
             input->name = name;
diff --git a/libavfilter/interlace.h b/libavfilter/interlace.h
new file mode 100644
index 0000000..44f1e06
--- /dev/null
+++ b/libavfilter/interlace.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @file
+ * progressive to interlaced content filter, inspired by heavy debugging of
+ * tinterlace filter.
+ */
+
+#ifndef AVFILTER_INTERLACE_H
+#define AVFILTER_INTERLACE_H
+
+#include "libavutil/common.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/opt.h"
+
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+#include "video.h"
+
+enum ScanMode {
+    MODE_TFF = 0,
+    MODE_BFF = 1,
+};
+
+enum FieldType {
+    FIELD_UPPER = 0,
+    FIELD_LOWER = 1,
+};
+
+typedef struct InterlaceContext {
+    const AVClass *class;
+    enum ScanMode scan;    // top or bottom field first scanning
+    int lowpass;           // enable or disable low pass filterning
+    AVFrame *cur, *next;   // the two frames from which the new one is obtained
+    void (*lowpass_line)(uint8_t *dstp, ptrdiff_t linesize, const uint8_t *srcp,
+                         const uint8_t *srcp_above, const uint8_t *srcp_below);
+} InterlaceContext;
+
+void ff_interlace_init_x86(InterlaceContext *interlace);
+
+#endif /* AVFILTER_INTERLACE_H */
diff --git a/libavfilter/libmpcodecs/vf_eq.c b/libavfilter/libmpcodecs/vf_eq.c
index f8efa84..7be1674 100644
--- a/libavfilter/libmpcodecs/vf_eq.c
+++ b/libavfilter/libmpcodecs/vf_eq.c
@@ -37,7 +37,7 @@
         int contrast;
 };
 
-#if HAVE_MMX && HAVE_6REGS
+#if HAVE_MMX_INLINE && HAVE_6REGS
 static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride,
                     int w, int h, int brightness, int contrast)
 {
@@ -224,7 +224,7 @@
     if (args) sscanf(args, "%d:%d", &vf->priv->brightness, &vf->priv->contrast);
 
         process = process_C;
-#if HAVE_MMX && HAVE_6REGS
+#if HAVE_MMX_INLINE && HAVE_6REGS
         if(ff_gCpuCaps.hasMMX) process = process_MMX;
 #endif
 
diff --git a/libavfilter/libmpcodecs/vf_eq2.c b/libavfilter/libmpcodecs/vf_eq2.c
index 0356813..d0a2b92 100644
--- a/libavfilter/libmpcodecs/vf_eq2.c
+++ b/libavfilter/libmpcodecs/vf_eq2.c
@@ -120,7 +120,7 @@
   par->lut_clean = 1;
 }
 
-#if HAVE_MMX && HAVE_6REGS
+#if HAVE_MMX_INLINE && HAVE_6REGS
 static
 void affine_1d_MMX (eq2_param_t *par, unsigned char *dst, unsigned char *src,
   unsigned w, unsigned h, unsigned dstride, unsigned sstride)
@@ -289,7 +289,7 @@
   if ((par->c == 1.0) && (par->b == 0.0) && (par->g == 1.0)) {
     par->adjust = NULL;
   }
-#if HAVE_MMX && HAVE_6REGS
+#if HAVE_MMX_INLINE && HAVE_6REGS
   else if (par->g == 1.0 && ff_gCpuCaps.hasMMX) {
     par->adjust = &affine_1d_MMX;
   }
diff --git a/libavfilter/libmpcodecs/vf_fspp.c b/libavfilter/libmpcodecs/vf_fspp.c
index c4a36ef..d457859 100644
--- a/libavfilter/libmpcodecs/vf_fspp.c
+++ b/libavfilter/libmpcodecs/vf_fspp.c
@@ -101,7 +101,7 @@
 };
 
 
-#if !HAVE_MMX
+#if !HAVE_MMX_INLINE
 
 //This func reads from 1 slice, 1 and clears 0 & 1
 static void store_slice_c(uint8_t *dst, int16_t *src, int dst_stride, int src_stride, int width, int height, int log2_scale)
@@ -177,7 +177,7 @@
 #define row_idct_s row_idct_c
 #define row_fdct_s row_fdct_c
 
-#else /* HAVE_MMX */
+#else /* HAVE_MMX_INLINE */
 
 //This func reads from 1 slice, 1 and clears 0 & 1
 static void store_slice_mmx(uint8_t *dst, int16_t *src, long dst_stride, long src_stride, long width, long height, long log2_scale)
@@ -404,7 +404,7 @@
 #define column_fidct_s column_fidct_mmx
 #define row_idct_s row_idct_mmx
 #define row_fdct_s row_fdct_mmx
-#endif // HAVE_MMX
+#endif // HAVE_MMX_INLINE
 
 static void filter(struct vf_priv_s *p, uint8_t *dst, uint8_t *src,
                    int dst_stride, int src_stride,
@@ -563,10 +563,10 @@
         }
     }
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
     if(ff_gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
 #endif
-#if HAVE_MMX2
+#if HAVE_MMXEXT_INLINE
     if(ff_gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
     return ff_vf_next_put_image(vf,dmpi, pts);
@@ -707,7 +707,7 @@
 #define THRESHOLD(r,x,t) if(((unsigned)((x)+t))>t*2) r=(x);else r=0;
 #define DESCALE(x,n)  (((x) + (1 << ((n)-1))) >> n)
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
 
 DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_382683433)=FIX64(0.382683433, 14);
 DECLARE_ALIGNED(8, uint64_t, ff_MM_FIX_0_541196100)=FIX64(0.541196100, 14);
@@ -728,7 +728,7 @@
 DECLARE_ASM_CONST(8, uint64_t, MM_DESCALE_RND)=C64(4);
 DECLARE_ASM_CONST(8, uint64_t, MM_2)=C64(2);
 
-#else /* !HAVE_MMX */
+#else /* !HAVE_MMX_INLINE */
 
 typedef int32_t int_simd16_t;
 static const int16_t FIX_0_382683433=FIX(0.382683433, 14);
@@ -743,7 +743,7 @@
 
 #endif
 
-#if !HAVE_MMX
+#if !HAVE_MMX_INLINE
 
 static void column_fidct_c(int16_t* thr_adr, int16_t *data, int16_t *output, int cnt)
 {
@@ -868,7 +868,7 @@
     }
 }
 
-#else /* HAVE_MMX */
+#else /* HAVE_MMX_INLINE */
 
 static void column_fidct_mmx(int16_t* thr_adr,  int16_t *data,  int16_t *output,  int cnt)
 {
@@ -1605,9 +1605,9 @@
         );
 }
 
-#endif // HAVE_MMX
+#endif // HAVE_MMX_INLINE
 
-#if !HAVE_MMX
+#if !HAVE_MMX_INLINE
 
 static void row_idct_c(int16_t* workspace,
                        int16_t* output_adr, int output_stride, int cnt)
@@ -1672,7 +1672,7 @@
     }
 }
 
-#else /* HAVE_MMX */
+#else /* HAVE_MMX_INLINE */
 
 static void row_idct_mmx (int16_t* workspace,
                           int16_t* output_adr,  int output_stride,  int cnt)
@@ -1876,9 +1876,9 @@
         );
 }
 
-#endif // HAVE_MMX
+#endif // HAVE_MMX_INLINE
 
-#if !HAVE_MMX
+#if !HAVE_MMX_INLINE
 
 static void row_fdct_c(int16_t *data, const uint8_t *pixels, int line_size, int cnt)
 {
@@ -1941,7 +1941,7 @@
     }
 }
 
-#else /* HAVE_MMX */
+#else /* HAVE_MMX_INLINE */
 
 static void row_fdct_mmx(int16_t *data,  const uint8_t *pixels,  int line_size,  int cnt)
 {
@@ -2121,4 +2121,4 @@
         : "%"REG_d);
 }
 
-#endif // HAVE_MMX
+#endif // HAVE_MMX_INLINE
diff --git a/libavfilter/libmpcodecs/vf_ilpack.c b/libavfilter/libmpcodecs/vf_ilpack.c
index fbf5817..d92b0ae 100644
--- a/libavfilter/libmpcodecs/vf_ilpack.c
+++ b/libavfilter/libmpcodecs/vf_ilpack.c
@@ -78,7 +78,7 @@
     }
 }
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
 static void pack_nn_MMX(unsigned char *dst, unsigned char *y,
     unsigned char *u, unsigned char *v, int w,
     int av_unused us, int av_unused vs)
@@ -420,7 +420,7 @@
     pack_nn = pack_nn_C;
     pack_li_0 = pack_li_0_C;
     pack_li_1 = pack_li_1_C;
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
     if(ff_gCpuCaps.hasMMX) {
         pack_nn = pack_nn_MMX;
 #if HAVE_EBX_AVAILABLE
diff --git a/libavfilter/libmpcodecs/vf_pp7.c b/libavfilter/libmpcodecs/vf_pp7.c
index 89ed4fe..0283e5d 100644
--- a/libavfilter/libmpcodecs/vf_pp7.c
+++ b/libavfilter/libmpcodecs/vf_pp7.c
@@ -155,7 +155,7 @@
     }
 }
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
 static void dctB_mmx(int16_t *dst, int16_t *src){
     __asm__ volatile (
         "movq  (%0), %%mm0      \n\t"
@@ -397,10 +397,10 @@
         memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->w>>mpi->chroma_x_shift, mpi->h>>mpi->chroma_y_shift, dmpi->stride[2], mpi->stride[2]);
     }
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
     if(ff_gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
 #endif
-#if HAVE_MMX2
+#if HAVE_MMXEXT_INLINE
     if(ff_gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
 
@@ -464,7 +464,7 @@
         case 2: requantize= mediumthresh_c; break;
     }
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
     if(ff_gCpuCaps.hasMMX){
         dctB= dctB_mmx;
     }
diff --git a/libavfilter/libmpcodecs/vf_uspp.c b/libavfilter/libmpcodecs/vf_uspp.c
index c9d9c1f..fb4329d 100644
--- a/libavfilter/libmpcodecs/vf_uspp.c
+++ b/libavfilter/libmpcodecs/vf_uspp.c
@@ -297,10 +297,10 @@
         }
     }
 
-#if HAVE_MMX
+#if HAVE_MMX_INLINE
     if(ff_gCpuCaps.hasMMX) __asm__ volatile ("emms\n\t");
 #endif
-#if HAVE_MMX2
+#if HAVE_MMXEXT_INLINE
     if(ff_gCpuCaps.hasMMX2) __asm__ volatile ("sfence\n\t");
 #endif
 
@@ -375,7 +375,7 @@
     if(vf->priv->qp < 0)
         vf->priv->qp = 0;
 
-// #if HAVE_MMX
+// #if HAVE_MMX_INLINE
 //     if(ff_gCpuCaps.hasMMX){
 //         store_slice= store_slice_mmx;
 //     }
diff --git a/libavfilter/tinterlace.h b/libavfilter/tinterlace.h
new file mode 100644
index 0000000..41b78c5
--- /dev/null
+++ b/libavfilter/tinterlace.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 Stefano Sabatini
+ * Copyright (c) 2010 Baptiste Coudurier
+ * Copyright (c) 2003 Michael Zucchi <notzed@ximian.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @file
+ * temporal field interlace filter, ported from MPlayer/libmpcodecs
+ */
+#ifndef AVFILTER_TINTERLACE_H
+#define AVFILTER_TINTERLACE_H
+
+#include "libavutil/opt.h"
+#include "avfilter.h"
+
+enum TInterlaceMode {
+    MODE_MERGE = 0,
+    MODE_DROP_EVEN,
+    MODE_DROP_ODD,
+    MODE_PAD,
+    MODE_INTERLEAVE_TOP,
+    MODE_INTERLEAVE_BOTTOM,
+    MODE_INTERLACEX2,
+    MODE_NB,
+};
+
+typedef struct {
+    const AVClass *class;
+    enum TInterlaceMode mode;   ///< interlace mode selected
+    int flags;                  ///< flags affecting interlacing algorithm
+    int frame;                  ///< number of the output frame
+    int vsub;                   ///< chroma vertical subsampling
+    AVFrame *cur;
+    AVFrame *next;
+    uint8_t *black_data[4];     ///< buffer used to fill padded lines
+    int black_linesize[4];
+    void (*lowpass_line)(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
+                         const uint8_t *srcp_above, const uint8_t *srcp_below);
+} TInterlaceContext;
+
+void ff_tinterlace_init_x86(TInterlaceContext *interlace);
+
+#endif /* AVFILTER_TINTERLACE_H */
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 2fa15eb..6f61aee 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
 
 #define LIBAVFILTER_VERSION_MAJOR  5
 #define LIBAVFILTER_VERSION_MINOR  2
-#define LIBAVFILTER_VERSION_MICRO 100
+#define LIBAVFILTER_VERSION_MICRO 103
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                LIBAVFILTER_VERSION_MINOR, \
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index 857dee6..d20f805 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -855,7 +855,7 @@
     if (tag == 'L')
         localtime_r(&now, &tm);
     else
-        tm = *gmtime(&now);
+        tm = *gmtime_r(&now, &tm);
     av_bprint_strftime(bp, fmt, &tm);
     return 0;
 }
diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c
index b9c4070..9a25042 100644
--- a/libavfilter/vf_idet.c
+++ b/libavfilter/vf_idet.c
@@ -32,6 +32,8 @@
 static const AVOption idet_options[] = {
     { "intl_thres", "set interlacing threshold", OFFSET(interlace_threshold),   AV_OPT_TYPE_FLOAT, {.dbl = 1.04}, -1, FLT_MAX, FLAGS },
     { "prog_thres", "set progressive threshold", OFFSET(progressive_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 1.5},  -1, FLT_MAX, FLAGS },
+    { "rep_thres",  "set repeat threshold",      OFFSET(repeat_threshold),      AV_OPT_TYPE_FLOAT, {.dbl = 3.0},  -1, FLT_MAX, FLAGS },
+    { "half_life", "half life of cumulative statistics", OFFSET(half_life),     AV_OPT_TYPE_FLOAT, {.dbl = 0.0},  -1, INT_MAX, FLAGS },
     { NULL }
 };
 
@@ -40,10 +42,43 @@
 static const char *type2str(Type type)
 {
     switch(type) {
-        case TFF          : return "Top Field First   ";
-        case BFF          : return "Bottom Field First";
-        case PROGRESSIVE  : return "Progressive       ";
-        case UNDETERMINED : return "Undetermined      ";
+        case TFF          : return "tff";
+        case BFF          : return "bff";
+        case PROGRESSIVE  : return "progressive";
+        case UNDETERMINED : return "undetermined";
+    }
+    return NULL;
+}
+
+#define PRECISION 1048576
+
+static uint64_t uintpow(uint64_t b,unsigned int e)
+{
+    uint64_t r=1;
+    while(e--) r*=b;
+    return r;
+}
+
+static int av_dict_set_fxp(AVDictionary **pm, const char *key, uint64_t value, unsigned int digits,
+                int flags)
+{
+    char valuestr[44];
+    uint64_t print_precision = uintpow(10, digits);
+
+    value = av_rescale(value, print_precision, PRECISION);
+
+    snprintf(valuestr, sizeof(valuestr), "%"PRId64".%0*"PRId64,
+             value / print_precision, digits, value % print_precision);
+
+    return av_dict_set(pm, key, valuestr, flags);
+}
+
+static const char *rep2str(RepeatedField repeated_field)
+{
+    switch(repeated_field) {
+        case REPEAT_NONE    : return "neither";
+        case REPEAT_TOP     : return "top";
+        case REPEAT_BOTTOM  : return "bottom";
     }
     return NULL;
 }
@@ -80,8 +115,11 @@
     int y, i;
     int64_t alpha[2]={0};
     int64_t delta=0;
+    int64_t gamma[2]={0};
     Type type, best_type;
+    RepeatedField repeat;
     int match = 0;
+    AVDictionary **metadata = avpriv_frame_get_metadatap(idet->cur);
 
     for (i = 0; i < idet->csp->nb_components; i++) {
         int w = idet->cur->width;
@@ -100,6 +138,7 @@
             alpha[ y   &1] += idet->filter_line(cur-refs, prev, cur+refs, w);
             alpha[(y^1)&1] += idet->filter_line(cur-refs, next, cur+refs, w);
             delta          += idet->filter_line(cur-refs,  cur, cur+refs, w);
+            gamma[(y^1)&1] += idet->filter_line(cur     , prev, cur     , w);
         }
     }
 
@@ -113,6 +152,14 @@
         type = UNDETERMINED;
     }
 
+    if ( gamma[0] > idet->repeat_threshold * gamma[1] ){
+        repeat = REPEAT_TOP;
+    } else if ( gamma[1] > idet->repeat_threshold * gamma[0] ){
+        repeat = REPEAT_BOTTOM;
+    } else {
+        repeat = REPEAT_NONE;
+    }
+
     memmove(idet->history+1, idet->history, HIST_SIZE-1);
     idet->history[0] = type;
     best_type = UNDETERMINED;
@@ -145,16 +192,48 @@
         idet->cur->interlaced_frame = 0;
     }
 
-    idet->prestat [           type] ++;
-    idet->poststat[idet->last_type] ++;
-    av_log(ctx, AV_LOG_DEBUG, "Single frame:%s, Multi frame:%s\n", type2str(type), type2str(idet->last_type));
+    for(i=0; i<3; i++)
+        idet->repeats[i]  = av_rescale(idet->repeats [i], idet->decay_coefficient, PRECISION);
+
+    for(i=0; i<4; i++){
+        idet->prestat [i] = av_rescale(idet->prestat [i], idet->decay_coefficient, PRECISION);
+        idet->poststat[i] = av_rescale(idet->poststat[i], idet->decay_coefficient, PRECISION);
+    }
+
+    idet->total_repeats [         repeat] ++;
+    idet->repeats       [         repeat] += PRECISION;
+
+    idet->total_prestat [           type] ++;
+    idet->prestat       [           type] += PRECISION;
+
+    idet->total_poststat[idet->last_type] ++;
+    idet->poststat      [idet->last_type] += PRECISION;
+
+    av_log(ctx, AV_LOG_DEBUG, "Repeated Field:%12s, Single frame:%12s, Multi frame:%12s\n",
+           rep2str(repeat), type2str(type), type2str(idet->last_type));
+
+    av_dict_set    (metadata, "lavfi.idet.repeated.current_frame", rep2str(repeat), 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.repeated.neither",       idet->repeats[REPEAT_NONE], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.repeated.top",           idet->repeats[REPEAT_TOP], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.repeated.bottom",        idet->repeats[REPEAT_BOTTOM], 2, 0);
+
+    av_dict_set    (metadata, "lavfi.idet.single.current_frame",   type2str(type), 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.single.tff",             idet->prestat[TFF], 2 , 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.single.bff",             idet->prestat[BFF], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.single.progressive",     idet->prestat[PROGRESSIVE], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.single.undetermined",    idet->prestat[UNDETERMINED], 2, 0);
+
+    av_dict_set    (metadata, "lavfi.idet.multiple.current_frame", type2str(idet->last_type), 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.multiple.tff",           idet->poststat[TFF], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.multiple.bff",           idet->poststat[BFF], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.multiple.progressive",   idet->poststat[PROGRESSIVE], 2, 0);
+    av_dict_set_fxp(metadata, "lavfi.idet.multiple.undetermined",  idet->poststat[UNDETERMINED], 2, 0);
 }
 
 static int filter_frame(AVFilterLink *link, AVFrame *picref)
 {
     AVFilterContext *ctx = link->dst;
     IDETContext *idet = ctx->priv;
-    AVDictionary **metadata = avpriv_frame_get_metadatap(picref);
 
     if (idet->prev)
         av_frame_free(&idet->prev);
@@ -162,11 +241,12 @@
     idet->cur  = idet->next;
     idet->next = picref;
 
-    if (!idet->cur)
-        return 0;
+    if (!idet->cur &&
+        !(idet->cur = av_frame_clone(idet->next)))
+        return AVERROR(ENOMEM);
 
     if (!idet->prev)
-        idet->prev = av_frame_clone(idet->cur);
+        return 0;
 
     if (!idet->csp)
         idet->csp = av_pix_fmt_desc_get(link->format);
@@ -178,16 +258,6 @@
 
     filter(ctx);
 
-    av_dict_set_int(metadata, "lavfi.idet.single.tff", idet->prestat[TFF], 0);
-    av_dict_set_int(metadata, "lavfi.idet.single.bff", idet->prestat[BFF], 0);
-    av_dict_set_int(metadata, "lavfi.idet.single.progressive", idet->prestat[PROGRESSIVE], 0);
-    av_dict_set_int(metadata, "lavfi.idet.single.undetermined", idet->prestat[UNDETERMINED], 0);
-
-    av_dict_set_int(metadata, "lavfi.idet.multiple.tff", idet->poststat[TFF], 0);
-    av_dict_set_int(metadata, "lavfi.idet.multiple.bff", idet->poststat[BFF], 0);
-    av_dict_set_int(metadata, "lavfi.idet.multiple.progressive", idet->poststat[PROGRESSIVE], 0);
-    av_dict_set_int(metadata, "lavfi.idet.multiple.undetermined", idet->poststat[UNDETERMINED], 0);
-
     return ff_filter_frame(ctx->outputs[0], av_frame_clone(idet->cur));
 }
 
@@ -215,7 +285,7 @@
         } else if (ret < 0) {
             return ret;
         }
-    } while (!idet->cur);
+    } while (!idet->prev);
 
     return 0;
 }
@@ -224,18 +294,23 @@
 {
     IDETContext *idet = ctx->priv;
 
-    av_log(ctx, AV_LOG_INFO, "Single frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
-           idet->prestat[TFF],
-           idet->prestat[BFF],
-           idet->prestat[PROGRESSIVE],
-           idet->prestat[UNDETERMINED]
-    );
-    av_log(ctx, AV_LOG_INFO, "Multi frame detection: TFF:%d BFF:%d Progressive:%d Undetermined:%d\n",
-           idet->poststat[TFF],
-           idet->poststat[BFF],
-           idet->poststat[PROGRESSIVE],
-           idet->poststat[UNDETERMINED]
-    );
+    av_log(ctx, AV_LOG_INFO, "Repeated Fields: Neither:%6"PRId64" Top:%6"PRId64" Bottom:%6"PRId64"\n",
+           idet->total_repeats[REPEAT_NONE],
+           idet->total_repeats[REPEAT_TOP],
+           idet->total_repeats[REPEAT_BOTTOM]
+        );
+    av_log(ctx, AV_LOG_INFO, "Single frame detection: TFF:%6"PRId64" BFF:%6"PRId64" Progressive:%6"PRId64" Undetermined:%6"PRId64"\n",
+           idet->total_prestat[TFF],
+           idet->total_prestat[BFF],
+           idet->total_prestat[PROGRESSIVE],
+           idet->total_prestat[UNDETERMINED]
+        );
+    av_log(ctx, AV_LOG_INFO, "Multi frame detection: TFF:%6"PRId64" BFF:%6"PRId64" Progressive:%6"PRId64" Undetermined:%6"PRId64"\n",
+           idet->total_poststat[TFF],
+           idet->total_poststat[BFF],
+           idet->total_poststat[PROGRESSIVE],
+           idet->total_poststat[UNDETERMINED]
+        );
 
     av_frame_free(&idet->prev);
     av_frame_free(&idet->cur );
@@ -286,6 +361,11 @@
     idet->last_type = UNDETERMINED;
     memset(idet->history, UNDETERMINED, HIST_SIZE);
 
+    if( idet->half_life > 0 )
+        idet->decay_coefficient = (uint64_t) round( PRECISION * exp2(-1.0 / idet->half_life) );
+    else
+        idet->decay_coefficient = PRECISION;
+
     idet->filter_line = ff_idet_filter_line_c;
 
     if (ARCH_X86)
@@ -294,7 +374,6 @@
     return 0;
 }
 
-
 static const AVFilterPad idet_inputs[] = {
     {
         .name         = "default",
diff --git a/libavfilter/vf_idet.h b/libavfilter/vf_idet.h
index 57332df..af759b4 100644
--- a/libavfilter/vf_idet.h
+++ b/libavfilter/vf_idet.h
@@ -33,14 +33,28 @@
     UNDETERMINED,
 } Type;
 
+typedef enum {
+    REPEAT_NONE,
+    REPEAT_TOP,
+    REPEAT_BOTTOM,
+} RepeatedField;
+
 typedef struct {
     const AVClass *class;
     float interlace_threshold;
     float progressive_threshold;
+    float repeat_threshold;
+    float half_life;
+    uint64_t decay_coefficient;
 
     Type last_type;
-    int prestat[4];
-    int poststat[4];
+
+    uint64_t repeats[3];
+    uint64_t prestat[4];
+    uint64_t poststat[4];
+    uint64_t total_repeats[3];
+    uint64_t total_prestat[4];
+    uint64_t total_poststat[4];
 
     uint8_t history[HIST_SIZE];
 
diff --git a/libavfilter/vf_interlace.c b/libavfilter/vf_interlace.c
index e07963f..a63f915 100644
--- a/libavfilter/vf_interlace.c
+++ b/libavfilter/vf_interlace.c
@@ -33,26 +33,10 @@
 
 #include "formats.h"
 #include "avfilter.h"
+#include "interlace.h"
 #include "internal.h"
 #include "video.h"
 
-enum ScanMode {
-    MODE_TFF = 0,
-    MODE_BFF = 1,
-};
-
-enum FieldType {
-    FIELD_UPPER = 0,
-    FIELD_LOWER = 1,
-};
-
-typedef struct InterlaceContext {
-    const AVClass *class;
-    enum ScanMode scan;    // top or bottom field first scanning
-    int lowpass;           // enable or disable low pass filterning
-    AVFrame *cur, *next;   // the two frames from which the new one is obtained
-} InterlaceContext;
-
 #define OFFSET(x) offsetof(InterlaceContext, x)
 #define V AV_OPT_FLAG_VIDEO_PARAM
 static const AVOption interlace_options[] = {
@@ -69,6 +53,20 @@
 
 AVFILTER_DEFINE_CLASS(interlace);
 
+static void lowpass_line_c(uint8_t *dstp, ptrdiff_t linesize,
+                           const uint8_t *srcp,
+                           const uint8_t *srcp_above,
+                           const uint8_t *srcp_below)
+{
+    int i;
+    for (i = 0; i < linesize; i++) {
+        // this calculation is an integer representation of
+        // '0.5 * current + 0.25 * above + 0.25 * below'
+        // '1 +' is for rounding.
+        dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
+    }
+}
+
 static const enum AVPixelFormat formats_supported[] = {
     AV_PIX_FMT_YUV420P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV444P,
     AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV410P,  AV_PIX_FMT_YUVA420P,
@@ -111,27 +109,34 @@
     outlink->time_base = inlink->time_base;
     outlink->frame_rate = inlink->frame_rate;
     // half framerate
-    outlink->time_base.num *= 2;
     outlink->frame_rate.den *= 2;
     outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
 
+
+    if (s->lowpass) {
+        s->lowpass_line = lowpass_line_c;
+        if (ARCH_X86)
+            ff_interlace_init_x86(s);
+    }
+
     av_log(ctx, AV_LOG_VERBOSE, "%s interlacing %s lowpass filter\n",
            s->scan == MODE_TFF ? "tff" : "bff", (s->lowpass) ? "with" : "without");
 
     return 0;
 }
 
-static void copy_picture_field(AVFrame *src_frame, AVFrame *dst_frame,
+static void copy_picture_field(InterlaceContext *s,
+                               AVFrame *src_frame, AVFrame *dst_frame,
                                AVFilterLink *inlink, enum FieldType field_type,
                                int lowpass)
 {
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
     int vsub = desc->log2_chroma_h;
-    int plane, i, j;
+    int plane, j;
 
     for (plane = 0; plane < desc->nb_components; plane++) {
         int lines = (plane == 1 || plane == 2) ? FF_CEIL_RSHIFT(inlink->h, vsub) : inlink->h;
-        int linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
+        ptrdiff_t linesize = av_image_get_linesize(inlink->format, inlink->w, plane);
         uint8_t *dstp = dst_frame->data[plane];
         const uint8_t *srcp = src_frame->data[plane];
 
@@ -152,12 +157,7 @@
                     srcp_above = srcp; // there is no line above
                 if (j == 1)
                     srcp_below = srcp; // there is no line below
-                for (i = 0; i < linesize; i++) {
-                    // this calculation is an integer representation of
-                    // '0.5 * current + 0.25 * above + 0.25 * below'
-                    // '1 +' is for rounding.
-                    dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
-                }
+                s->lowpass_line(dstp, linesize, srcp, srcp_above, srcp_below);
                 dstp += dstp_linesize;
                 srcp += srcp_linesize;
             }
@@ -204,14 +204,13 @@
     av_frame_copy_props(out, s->cur);
     out->interlaced_frame = 1;
     out->top_field_first  = tff;
-    out->pts             /= 2;  // adjust pts to new framerate
 
     /* copy upper/lower field from cur */
-    copy_picture_field(s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass);
+    copy_picture_field(s, s->cur, out, inlink, tff ? FIELD_UPPER : FIELD_LOWER, s->lowpass);
     av_frame_free(&s->cur);
 
     /* copy lower/upper field from next */
-    copy_picture_field(s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER, s->lowpass);
+    copy_picture_field(s, s->next, out, inlink, tff ? FIELD_LOWER : FIELD_UPPER, s->lowpass);
     av_frame_free(&s->next);
 
     ret = ff_filter_frame(outlink, out);
diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c
index fff5a2b..0b7a2ca 100644
--- a/libavfilter/vf_lut.c
+++ b/libavfilter/vf_lut.c
@@ -161,15 +161,32 @@
     return pow((val-minval)/(maxval-minval), gamma) * (maxval-minval)+minval;
 }
 
+/**
+ * Compute Rec.709 gama correction of value val
+ */
+static double compute_gammaval709(void *opaque, double gamma)
+{
+    LutContext *s = opaque;
+    double val    = s->var_values[VAR_CLIPVAL];
+    double minval = s->var_values[VAR_MINVAL];
+    double maxval = s->var_values[VAR_MAXVAL];
+    double level = (val - minval) / (maxval - minval);
+    level = level < 0.018 ? 4.5 * level
+                          : 1.099 * pow(level, 1.0 / gamma) - 0.099;
+    return level * (maxval - minval) + minval;
+}
+
 static double (* const funcs1[])(void *, double) = {
     (void *)clip,
     (void *)compute_gammaval,
+    (void *)compute_gammaval709,
     NULL
 };
 
 static const char * const funcs1_names[] = {
     "clip",
     "gammaval",
+    "gammaval709",
     NULL
 };
 
diff --git a/libavfilter/vf_signalstats.c b/libavfilter/vf_signalstats.c
index 47545aa..4b2792f 100644
--- a/libavfilter/vf_signalstats.c
+++ b/libavfilter/vf_signalstats.c
@@ -43,22 +43,36 @@
     enum FilterMode outfilter;
     int filters;
     AVFrame *frame_prev;
-    char *vrep_line;
     uint8_t rgba_color[4];
     int yuv_color[3];
+    int nb_jobs;
+    int *jobs_rets;
+
+    AVFrame *frame_sat;
+    AVFrame *frame_hue;
 } SignalstatsContext;
 
+typedef struct ThreadData {
+    const AVFrame *in;
+    AVFrame *out;
+} ThreadData;
+
+typedef struct ThreadDataHueSatMetrics {
+    const AVFrame *src;
+    AVFrame *dst_sat, *dst_hue;
+} ThreadDataHueSatMetrics;
+
 #define OFFSET(x) offsetof(SignalstatsContext, x)
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
 
 static const AVOption signalstats_options[] = {
     {"stat", "set statistics filters", OFFSET(filters), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, INT_MAX, FLAGS, "filters"},
         {"tout", "analyze pixels for temporal outliers",                0, AV_OPT_TYPE_CONST, {.i64=1<<FILTER_TOUT}, 0, 0, FLAGS, "filters"},
-        {"vrep", "analyze video lines for vertical line repitition",    0, AV_OPT_TYPE_CONST, {.i64=1<<FILTER_VREP}, 0, 0, FLAGS, "filters"},
+        {"vrep", "analyze video lines for vertical line repetition",    0, AV_OPT_TYPE_CONST, {.i64=1<<FILTER_VREP}, 0, 0, FLAGS, "filters"},
         {"brng", "analyze for pixels outside of broadcast range",       0, AV_OPT_TYPE_CONST, {.i64=1<<FILTER_BRNG}, 0, 0, FLAGS, "filters"},
     {"out", "set video filter", OFFSET(outfilter), AV_OPT_TYPE_INT, {.i64=FILTER_NONE}, -1, FILT_NUMB-1, FLAGS, "out"},
         {"tout", "highlight pixels that depict temporal outliers",              0, AV_OPT_TYPE_CONST, {.i64=FILTER_TOUT}, 0, 0, FLAGS, "out"},
-        {"vrep", "highlight video lines that depict vertical line repitition",  0, AV_OPT_TYPE_CONST, {.i64=FILTER_VREP}, 0, 0, FLAGS, "out"},
+        {"vrep", "highlight video lines that depict vertical line repetition",  0, AV_OPT_TYPE_CONST, {.i64=FILTER_VREP}, 0, 0, FLAGS, "out"},
         {"brng", "highlight pixels that are outside of broadcast range",        0, AV_OPT_TYPE_CONST, {.i64=FILTER_BRNG}, 0, 0, FLAGS, "out"},
     {"c",     "set highlight color", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str="yellow"}, .flags=FLAGS},
     {"color", "set highlight color", OFFSET(rgba_color), AV_OPT_TYPE_COLOR, {.str="yellow"}, .flags=FLAGS},
@@ -88,7 +102,9 @@
 {
     SignalstatsContext *s = ctx->priv;
     av_frame_free(&s->frame_prev);
-    av_freep(&s->vrep_line);
+    av_frame_free(&s->frame_sat);
+    av_frame_free(&s->frame_hue);
+    av_freep(&s->jobs_rets);
 }
 
 static int query_formats(AVFilterContext *ctx)
@@ -106,6 +122,22 @@
     return 0;
 }
 
+static AVFrame *alloc_frame(enum AVPixelFormat pixfmt, int w, int h)
+{
+    AVFrame *frame = av_frame_alloc();
+    if (!frame)
+        return NULL;
+
+    frame->format = pixfmt;
+    frame->width  = w;
+    frame->height = h;
+
+    if (av_frame_get_buffer(frame, 32) < 0)
+        return NULL;
+
+    return frame;
+}
+
 static int config_props(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
@@ -124,16 +156,20 @@
     s->fs = inlink->w * inlink->h;
     s->cfs = s->chromaw * s->chromah;
 
-    if (s->filters & 1<<FILTER_VREP) {
-        s->vrep_line = av_malloc(inlink->h * sizeof(*s->vrep_line));
-        if (!s->vrep_line)
-            return AVERROR(ENOMEM);
-    }
+    s->nb_jobs   = FFMAX(1, FFMIN(inlink->h, ctx->graph->nb_threads));
+    s->jobs_rets = av_malloc_array(s->nb_jobs, sizeof(*s->jobs_rets));
+    if (!s->jobs_rets)
+        return AVERROR(ENOMEM);
+
+    s->frame_sat = alloc_frame(AV_PIX_FMT_GRAY8,  inlink->w, inlink->h);
+    s->frame_hue = alloc_frame(AV_PIX_FMT_GRAY16, inlink->w, inlink->h);
+    if (!s->frame_sat || !s->frame_hue)
+        return AVERROR(ENOMEM);
 
     return 0;
 }
 
-static void burn_frame(SignalstatsContext *s, AVFrame *f, int x, int y)
+static void burn_frame(const SignalstatsContext *s, AVFrame *f, int x, int y)
 {
     const int chromax = x >> s->hsub;
     const int chromay = y >> s->vsub;
@@ -142,25 +178,36 @@
     f->data[2][chromay * f->linesize[2] + chromax] = s->yuv_color[2];
 }
 
-static int filter_brng(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h)
+static int filter_brng(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
-    int x, score = 0;
-    const int yc = y >> s->vsub;
-    const uint8_t *pluma    = &in->data[0][y  * in->linesize[0]];
-    const uint8_t *pchromau = &in->data[1][yc * in->linesize[1]];
-    const uint8_t *pchromav = &in->data[2][yc * in->linesize[2]];
+    ThreadData *td = arg;
+    const SignalstatsContext *s = ctx->priv;
+    const AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    const int w = in->width;
+    const int h = in->height;
+    const int slice_start = (h *  jobnr   ) / nb_jobs;
+    const int slice_end   = (h * (jobnr+1)) / nb_jobs;
+    int x, y, score = 0;
 
-    for (x = 0; x < w; x++) {
-        const int xc = x >> s->hsub;
-        const int luma    = pluma[x];
-        const int chromau = pchromau[xc];
-        const int chromav = pchromav[xc];
-        const int filt = luma    < 16 || luma    > 235 ||
-                         chromau < 16 || chromau > 240 ||
-                         chromav < 16 || chromav > 240;
-        score += filt;
-        if (out && filt)
-            burn_frame(s, out, x, y);
+    for (y = slice_start; y < slice_end; y++) {
+        const int yc = y >> s->vsub;
+        const uint8_t *pluma    = &in->data[0][y  * in->linesize[0]];
+        const uint8_t *pchromau = &in->data[1][yc * in->linesize[1]];
+        const uint8_t *pchromav = &in->data[2][yc * in->linesize[2]];
+
+        for (x = 0; x < w; x++) {
+            const int xc = x >> s->hsub;
+            const int luma    = pluma[x];
+            const int chromau = pchromau[xc];
+            const int chromav = pchromav[xc];
+            const int filt = luma    < 16 || luma    > 235 ||
+                chromau < 16 || chromau > 240 ||
+                chromav < 16 || chromav > 240;
+            score += filt;
+            if (out && filt)
+                burn_frame(s, out, x, y);
+        }
     }
     return score;
 }
@@ -170,38 +217,49 @@
     return ((abs(x - y) + abs (z - y)) / 2) - abs(z - x) > 4; // make 4 configurable?
 }
 
-static int filter_tout(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h)
+static int filter_tout(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
+    ThreadData *td = arg;
+    const SignalstatsContext *s = ctx->priv;
+    const AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    const int w = in->width;
+    const int h = in->height;
+    const int slice_start = (h *  jobnr   ) / nb_jobs;
+    const int slice_end   = (h * (jobnr+1)) / nb_jobs;
     const uint8_t *p = in->data[0];
     int lw = in->linesize[0];
-    int x, score = 0, filt;
+    int x, y, score = 0, filt;
 
-    if (y - 1 < 0 || y + 1 >= h)
-        return 0;
+    for (y = slice_start; y < slice_end; y++) {
 
-    // detect two pixels above and below (to eliminate interlace artefacts)
-    // should check that video format is infact interlaced.
+        if (y - 1 < 0 || y + 1 >= h)
+            continue;
+
+        // detect two pixels above and below (to eliminate interlace artefacts)
+        // should check that video format is infact interlaced.
 
 #define FILTER(i, j) \
-filter_tout_outlier(p[(y-j) * lw + x + i], \
-                    p[    y * lw + x + i], \
-                    p[(y+j) * lw + x + i])
+        filter_tout_outlier(p[(y-j) * lw + x + i], \
+                            p[    y * lw + x + i], \
+                            p[(y+j) * lw + x + i])
 
 #define FILTER3(j) (FILTER(-1, j) && FILTER(0, j) && FILTER(1, j))
 
-    if (y - 2 >= 0 && y + 2 < h) {
-        for (x = 1; x < w - 1; x++) {
-            filt = FILTER3(2) && FILTER3(1);
-            score += filt;
-            if (filt && out)
-                burn_frame(s, out, x, y);
-        }
-    } else {
-        for (x = 1; x < w - 1; x++) {
-            filt = FILTER3(1);
-            score += filt;
-            if (filt && out)
-                burn_frame(s, out, x, y);
+        if (y - 2 >= 0 && y + 2 < h) {
+            for (x = 1; x < w - 1; x++) {
+                filt = FILTER3(2) && FILTER3(1);
+                score += filt;
+                if (filt && out)
+                    burn_frame(s, out, x, y);
+            }
+        } else {
+            for (x = 1; x < w - 1; x++) {
+                filt = FILTER3(1);
+                score += filt;
+                if (filt && out)
+                    burn_frame(s, out, x, y);
+            }
         }
     }
     return score;
@@ -209,63 +267,99 @@
 
 #define VREP_START 4
 
-static void filter_init_vrep(SignalstatsContext *s, const AVFrame *p, int w, int h)
+static int filter_vrep(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
 {
-    int i, y;
-    int lw = p->linesize[0];
+    ThreadData *td = arg;
+    const SignalstatsContext *s = ctx->priv;
+    const AVFrame *in = td->in;
+    AVFrame *out = td->out;
+    const int w = in->width;
+    const int h = in->height;
+    const int slice_start = (h *  jobnr   ) / nb_jobs;
+    const int slice_end   = (h * (jobnr+1)) / nb_jobs;
+    const uint8_t *p = in->data[0];
+    const int lw = in->linesize[0];
+    int x, y, score = 0;
 
-    for (y = VREP_START; y < h; y++) {
-        int totdiff = 0;
-        int y2lw = (y - VREP_START) * lw;
-        int ylw = y * lw;
+    for (y = slice_start; y < slice_end; y++) {
+        const int y2lw = (y - VREP_START) * lw;
+        const int ylw  =  y               * lw;
+        int filt, totdiff = 0;
 
-        for (i = 0; i < w; i++)
-            totdiff += abs(p->data[0][y2lw + i] - p->data[0][ylw + i]);
+        if (y < VREP_START)
+            continue;
 
-        /* this value should be definable */
-        s->vrep_line[y] = totdiff < w;
-    }
-}
+        for (x = 0; x < w; x++)
+            totdiff += abs(p[y2lw + x] - p[ylw + x]);
+        filt = totdiff < w;
 
-static int filter_vrep(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h)
-{
-    int x, score = 0;
-
-    if (y < VREP_START)
-        return 0;
-
-    for (x = 0; x < w; x++) {
-        if (s->vrep_line[y]) {
-            score++;
-            if (out)
+        score += filt;
+        if (filt && out)
+            for (x = 0; x < w; x++)
                 burn_frame(s, out, x, y);
-        }
     }
-    return score;
+    return score * w;
 }
 
 static const struct {
     const char *name;
-    void (*init)(SignalstatsContext *s, const AVFrame *p, int w, int h);
-    int (*process)(SignalstatsContext *s, const AVFrame *in, AVFrame *out, int y, int w, int h);
+    int (*process)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
 } filters_def[] = {
-    {"TOUT", NULL,              filter_tout},
-    {"VREP", filter_init_vrep,  filter_vrep},
-    {"BRNG", NULL,              filter_brng},
+    {"TOUT", filter_tout},
+    {"VREP", filter_vrep},
+    {"BRNG", filter_brng},
     {NULL}
 };
 
 #define DEPTH 256
 
+static int compute_sat_hue_metrics(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
+{
+    int i, j;
+    ThreadDataHueSatMetrics *td = arg;
+    const SignalstatsContext *s = ctx->priv;
+    const AVFrame *src = td->src;
+    AVFrame *dst_sat = td->dst_sat;
+    AVFrame *dst_hue = td->dst_hue;
+
+    const int slice_start = (s->chromah *  jobnr   ) / nb_jobs;
+    const int slice_end   = (s->chromah * (jobnr+1)) / nb_jobs;
+
+    const int lsz_u = src->linesize[1];
+    const int lsz_v = src->linesize[2];
+    const uint8_t *p_u = src->data[1] + slice_start * lsz_u;
+    const uint8_t *p_v = src->data[2] + slice_start * lsz_v;
+
+    const int lsz_sat = dst_sat->linesize[0];
+    const int lsz_hue = dst_hue->linesize[0];
+    uint8_t *p_sat = dst_sat->data[0] + slice_start * lsz_sat;
+    uint8_t *p_hue = dst_hue->data[0] + slice_start * lsz_hue;
+
+    for (j = slice_start; j < slice_end; j++) {
+        for (i = 0; i < s->chromaw; i++) {
+            const int yuvu = p_u[i];
+            const int yuvv = p_v[i];
+            p_sat[i] = hypot(yuvu - 128, yuvv - 128); // int or round?
+            ((int16_t*)p_hue)[i] = floor((180 / M_PI) * atan2f(yuvu-128, yuvv-128) + 180);
+        }
+        p_u   += lsz_u;
+        p_v   += lsz_v;
+        p_sat += lsz_sat;
+        p_hue += lsz_hue;
+    }
+
+    return 0;
+}
+
 static int filter_frame(AVFilterLink *link, AVFrame *in)
 {
-    SignalstatsContext *s = link->dst->priv;
-    AVFilterLink *outlink = link->dst->outputs[0];
+    AVFilterContext *ctx = link->dst;
+    SignalstatsContext *s = ctx->priv;
+    AVFilterLink *outlink = ctx->outputs[0];
     AVFrame *out = in;
     int i, j;
     int  w = 0,  cw = 0, // in
         pw = 0, cpw = 0; // prev
-    int yuv, yuvu, yuvv;
     int fil;
     char metabuf[128];
     unsigned int histy[DEPTH] = {0},
@@ -289,24 +383,37 @@
     int filtot[FILT_NUMB] = {0};
     AVFrame *prev;
 
+    AVFrame *sat = s->frame_sat;
+    AVFrame *hue = s->frame_hue;
+    const uint8_t *p_sat = sat->data[0];
+    const uint8_t *p_hue = hue->data[0];
+    const int lsz_sat = sat->linesize[0];
+    const int lsz_hue = hue->linesize[0];
+    ThreadDataHueSatMetrics td_huesat = {
+        .src     = in,
+        .dst_sat = sat,
+        .dst_hue = hue,
+    };
+
     if (!s->frame_prev)
         s->frame_prev = av_frame_clone(in);
 
     prev = s->frame_prev;
 
-    if (s->outfilter != FILTER_NONE)
+    if (s->outfilter != FILTER_NONE) {
         out = av_frame_clone(in);
+        av_frame_make_writable(out);
+    }
 
-    for (fil = 0; fil < FILT_NUMB; fil ++)
-        if ((s->filters & 1<<fil) && filters_def[fil].init)
-            filters_def[fil].init(s, in, link->w, link->h);
+    ctx->internal->execute(ctx, compute_sat_hue_metrics, &td_huesat,
+                           NULL, FFMIN(s->chromah, ctx->graph->nb_threads));
 
     // Calculate luma histogram and difference with previous frame or field.
     for (j = 0; j < link->h; j++) {
         for (i = 0; i < link->w; i++) {
-            yuv = in->data[0][w + i];
+            const int yuv = in->data[0][w + i];
             histy[yuv]++;
-            dify += abs(in->data[0][w + i] - prev->data[0][pw + i]);
+            dify += abs(yuv - prev->data[0][pw + i]);
         }
         w  += in->linesize[0];
         pw += prev->linesize[0];
@@ -315,31 +422,33 @@
     // Calculate chroma histogram and difference with previous frame or field.
     for (j = 0; j < s->chromah; j++) {
         for (i = 0; i < s->chromaw; i++) {
-            int sat, hue;
-
-            yuvu = in->data[1][cw+i];
-            yuvv = in->data[2][cw+i];
+            const int yuvu = in->data[1][cw+i];
+            const int yuvv = in->data[2][cw+i];
             histu[yuvu]++;
-            difu += abs(in->data[1][cw+i] - prev->data[1][cpw+i]);
+            difu += abs(yuvu - prev->data[1][cpw+i]);
             histv[yuvv]++;
-            difv += abs(in->data[2][cw+i] - prev->data[2][cpw+i]);
+            difv += abs(yuvv - prev->data[2][cpw+i]);
 
-            // int or round?
-            sat = hypot(yuvu - 128, yuvv - 128);
-            histsat[sat]++;
-            hue = floor((180 / M_PI) * atan2f(yuvu-128, yuvv-128) + 180);
-            histhue[hue]++;
+            histsat[p_sat[i]]++;
+            histhue[((int16_t*)p_hue)[i]]++;
         }
         cw  += in->linesize[1];
         cpw += prev->linesize[1];
+        p_sat += lsz_sat;
+        p_hue += lsz_hue;
     }
 
-    for (j = 0; j < link->h; j++) {
-        for (fil = 0; fil < FILT_NUMB; fil ++) {
-            if (s->filters & 1<<fil) {
-                AVFrame *dbg = out != in && s->outfilter == fil ? out : NULL;
-                filtot[fil] += filters_def[fil].process(s, in, dbg, j, link->w, link->h);
-            }
+    for (fil = 0; fil < FILT_NUMB; fil ++) {
+        if (s->filters & 1<<fil) {
+            ThreadData td = {
+                .in = in,
+                .out = out != in && s->outfilter == fil ? out : NULL,
+            };
+            memset(s->jobs_rets, 0, s->nb_jobs * sizeof(*s->jobs_rets));
+            ctx->internal->execute(ctx, filters_def[fil].process,
+                                   &td, s->jobs_rets, s->nb_jobs);
+            for (i = 0; i < s->nb_jobs; i++)
+                filtot[fil] += s->jobs_rets[i];
         }
     }
 
@@ -478,4 +587,5 @@
     .inputs        = signalstats_inputs,
     .outputs       = signalstats_outputs,
     .priv_class    = &signalstats_class,
+    .flags         = AVFILTER_FLAG_SLICE_THREADS,
 };
diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
index 6bc55b5..133f073 100644
--- a/libavfilter/vf_tinterlace.c
+++ b/libavfilter/vf_tinterlace.c
@@ -30,29 +30,7 @@
 #include "libavutil/avassert.h"
 #include "avfilter.h"
 #include "internal.h"
-
-enum TInterlaceMode {
-    MODE_MERGE = 0,
-    MODE_DROP_EVEN,
-    MODE_DROP_ODD,
-    MODE_PAD,
-    MODE_INTERLEAVE_TOP,
-    MODE_INTERLEAVE_BOTTOM,
-    MODE_INTERLACEX2,
-    MODE_NB,
-};
-
-typedef struct {
-    const AVClass *class;
-    enum TInterlaceMode mode;   ///< interlace mode selected
-    int flags;                  ///< flags affecting interlacing algorithm
-    int frame;                  ///< number of the output frame
-    int vsub;                   ///< chroma vertical subsampling
-    AVFrame *cur;
-    AVFrame *next;
-    uint8_t *black_data[4];     ///< buffer used to fill padded lines
-    int black_linesize[4];
-} TInterlaceContext;
+#include "tinterlace.h"
 
 #define OFFSET(x) offsetof(TInterlaceContext, x)
 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
@@ -99,6 +77,18 @@
     return 0;
 }
 
+static void lowpass_line_c(uint8_t *dstp, ptrdiff_t width, const uint8_t *srcp,
+                           const uint8_t *srcp_above, const uint8_t *srcp_below)
+{
+    int i;
+    for (i = 0; i < width; i++) {
+        // this calculation is an integer representation of
+        // '0.5 * current + 0.25 * above + 0.25 * below'
+        // '1 +' is for rounding.
+        dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
+    }
+}
+
 static av_cold void uninit(AVFilterContext *ctx)
 {
     TInterlaceContext *tinterlace = ctx->priv;
@@ -149,6 +139,14 @@
         outlink->time_base.num = inlink->time_base.num;
         outlink->time_base.den = inlink->time_base.den * 2;
         outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2,1});
+    } else if (tinterlace->mode != MODE_PAD) {
+        outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){1,2});
+    }
+
+    if (tinterlace->flags & TINTERLACE_FLAG_VLPF) {
+        tinterlace->lowpass_line = lowpass_line_c;
+        if (ARCH_X86)
+            ff_tinterlace_init_x86(tinterlace);
     }
 
     av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n",
@@ -172,7 +170,8 @@
  * @param flags context flags
  */
 static inline
-void copy_picture_field(uint8_t *dst[4], int dst_linesize[4],
+void copy_picture_field(TInterlaceContext *tinterlace,
+                        uint8_t *dst[4], int dst_linesize[4],
                         const uint8_t *src[4], int src_linesize[4],
                         enum AVPixelFormat format, int w, int src_h,
                         int src_field, int interleave, int dst_field,
@@ -181,10 +180,11 @@
     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
     int plane, vsub = desc->log2_chroma_h;
     int k = src_field == FIELD_UPPER_AND_LOWER ? 1 : 2;
-    int h, i;
+    int h;
 
     for (plane = 0; plane < desc->nb_components; plane++) {
         int lines = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(src_h, vsub) : src_h;
+        int cols  = plane == 1 || plane == 2 ? FF_CEIL_RSHIFT(    w, desc->log2_chroma_w) : w;
         int linesize = av_image_get_linesize(format, w, plane);
         uint8_t *dstp = dst[plane];
         const uint8_t *srcp = src[plane];
@@ -208,12 +208,8 @@
                 const uint8_t *srcp_below = srcp + src_linesize[plane];
                 if (h == lines) srcp_above = srcp; // there is no line above
                 if (h == 1) srcp_below = srcp;     // there is no line below
-                for (i = 0; i < linesize; i++) {
-                    // this calculation is an integer representation of
-                    // '0.5 * current + 0.25 * above + 0.25 * below'
-                    // '1 +' is for rounding. */
-                    dstp[i] = (1 + srcp[i] + srcp[i] + srcp_above[i] + srcp_below[i]) >> 2;
-                }
+
+                tinterlace->lowpass_line(dstp, cols, srcp, srcp_above, srcp_below);
                 dstp += dstp_linesize;
                 srcp += srcp_linesize;
             }
@@ -254,12 +250,12 @@
         out->top_field_first = 1;
 
         /* write odd frame lines into the upper field of the new frame */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)cur->data, cur->linesize,
                            inlink->format, inlink->w, inlink->h,
                            FIELD_UPPER_AND_LOWER, 1, FIELD_UPPER, tinterlace->flags);
         /* write even frame lines into the lower field of the new frame */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)next->data, next->linesize,
                            inlink->format, inlink->w, inlink->h,
                            FIELD_UPPER_AND_LOWER, 1, FIELD_LOWER, tinterlace->flags);
@@ -284,12 +280,12 @@
 
         field = (1 + tinterlace->frame) & 1 ? FIELD_UPPER : FIELD_LOWER;
         /* copy upper and lower fields */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)cur->data, cur->linesize,
                            inlink->format, inlink->w, inlink->h,
                            FIELD_UPPER_AND_LOWER, 1, field, tinterlace->flags);
         /* pad with black the other field */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)tinterlace->black_data, tinterlace->black_linesize,
                            inlink->format, inlink->w, inlink->h,
                            FIELD_UPPER_AND_LOWER, 1, !field, tinterlace->flags);
@@ -308,13 +304,13 @@
         out->top_field_first = tff;
 
         /* copy upper/lower field from cur */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)cur->data, cur->linesize,
                            inlink->format, inlink->w, inlink->h,
                            tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
                            tinterlace->flags);
         /* copy lower/upper field from next */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)next->data, next->linesize,
                            inlink->format, inlink->w, inlink->h,
                            tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
@@ -340,19 +336,20 @@
             return AVERROR(ENOMEM);
         av_frame_copy_props(out, next);
         out->interlaced_frame = 1;
+        out->top_field_first = !tff;
 
         if (next->pts != AV_NOPTS_VALUE && cur->pts != AV_NOPTS_VALUE)
             out->pts = cur->pts + next->pts;
         else
             out->pts = AV_NOPTS_VALUE;
         /* write current frame second field lines into the second field of the new frame */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)cur->data, cur->linesize,
                            inlink->format, inlink->w, inlink->h,
                            tff ? FIELD_LOWER : FIELD_UPPER, 1, tff ? FIELD_LOWER : FIELD_UPPER,
                            tinterlace->flags);
         /* write next frame first field lines into the first field of the new frame */
-        copy_picture_field(out->data, out->linesize,
+        copy_picture_field(tinterlace, out->data, out->linesize,
                            (const uint8_t **)next->data, next->linesize,
                            inlink->format, inlink->w, inlink->h,
                            tff ? FIELD_UPPER : FIELD_LOWER, 1, tff ? FIELD_UPPER : FIELD_LOWER,
diff --git a/libavfilter/vf_xbr.c b/libavfilter/vf_xbr.c
new file mode 100644
index 0000000..47e4b76
--- /dev/null
+++ b/libavfilter/vf_xbr.c
@@ -0,0 +1,440 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * Copyright (c) 2011, 2012 Hyllian/Jararaca <sergiogdb@gmail.com>
+ * Copyright (c) 2014 Arwa Arif <arwaarif1994@gmail.com>
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * XBR Filter is used for depixelization of image.
+ * This is based on Hyllian's xBR shader.
+ *
+ * @see http://www.libretro.com/forums/viewtopic.php?f=6&t=134
+ * @see https://github.com/yoyofr/iFBA/blob/master/fba_src/src/intf/video/scalers/xbr.cpp
+ */
+
+#include "libavutil/opt.h"
+#include "libavutil/avassert.h"
+#include "libavutil/pixdesc.h"
+#include "internal.h"
+
+#define RGB_MASK      0x00FFFFFF
+#define LB_MASK       0x00FEFEFE
+#define RED_BLUE_MASK 0x00FF00FF
+#define GREEN_MASK    0x0000FF00
+
+typedef int (*xbrfunc_t)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
+
+typedef struct {
+    const AVClass *class;
+    int n;
+    xbrfunc_t func;
+    uint32_t rgbtoyuv[1<<24];
+} XBRContext;
+
+typedef struct ThreadData {
+    AVFrame *in, *out;
+    const uint32_t *rgbtoyuv;
+} ThreadData;
+
+#define OFFSET(x) offsetof(XBRContext, x)
+#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
+static const AVOption xbr_options[] = {
+    { "n", "set scale factor", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 3}, 2, 4, .flags = FLAGS },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(xbr);
+
+static uint32_t pixel_diff(uint32_t x, uint32_t y, const uint32_t *r2y)
+{
+#define YMASK 0xff0000
+#define UMASK 0x00ff00
+#define VMASK 0x0000ff
+
+    uint32_t yuv1 = r2y[x & 0xffffff];
+    uint32_t yuv2 = r2y[y & 0xffffff];
+
+    return (abs((yuv1 & YMASK) - (yuv2 & YMASK)) >> 16) +
+           (abs((yuv1 & UMASK) - (yuv2 & UMASK)) >>  8) +
+           abs((yuv1 & VMASK) - (yuv2 & VMASK));
+}
+
+#define ALPHA_BLEND_128_W(dst, src) dst = ((src & LB_MASK) >> 1) + ((dst & LB_MASK) >> 1)
+
+#define ALPHA_BLEND_32_W(dst, src) \
+    dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
+          (dst & RED_BLUE_MASK))) >> 3))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
+          ((((src & GREEN_MASK) - (dst & GREEN_MASK))) >> 3))))
+
+#define ALPHA_BLEND_64_W(dst, src) \
+    dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
+          (dst & RED_BLUE_MASK))) >> 2))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
+          ((((src & GREEN_MASK) - (dst & GREEN_MASK))) >> 2))))
+
+#define ALPHA_BLEND_192_W(dst, src) \
+    dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
+          (dst & RED_BLUE_MASK)) * 3) >> 2))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
+          ((((src & GREEN_MASK) - (dst & GREEN_MASK)) * 3) >> 2))))
+
+#define ALPHA_BLEND_224_W(dst, src) \
+    dst = ((RED_BLUE_MASK & ((dst & RED_BLUE_MASK) + ((((src & RED_BLUE_MASK) - \
+          (dst & RED_BLUE_MASK)) * 7) >> 3))) | (GREEN_MASK & ((dst & GREEN_MASK) + \
+          ((((src & GREEN_MASK) - (dst & GREEN_MASK)) * 7) >> 3))))
+
+#define df(A, B) pixel_diff(A, B, r2y)
+#define eq(A, B) (df(A, B) < 155)
+
+#define FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1,   \
+              N0, N1, N2, N3) do {                                                                  \
+    if (PE != PH && PE != PF) {                                                                     \
+        const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2);          \
+        const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2);          \
+        if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI)                                         \
+                      && (!eq(PF,I4) && !eq(PH,I5))                                                 \
+                      || eq(PE,PG) || eq(PE,PC))) {                                                 \
+            const unsigned ke = df(PF,PG);                                                          \
+            const unsigned ki = df(PH,PC);                                                          \
+            const int left    = ke<<1 <= ki && PE != PG && PD != PG;                                \
+            const int up      = ke >= ki<<1 && PE != PC && PB != PC;                                \
+            const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH;                                   \
+            if (left && up) {                                                                       \
+                ALPHA_BLEND_224_W(E[N3], px);                                                       \
+                ALPHA_BLEND_64_W( E[N2], px);                                                       \
+                E[N1] = E[N2];                                                                      \
+            } else if (left) {                                                                      \
+                ALPHA_BLEND_192_W(E[N3], px);                                                       \
+                ALPHA_BLEND_64_W( E[N2], px);                                                       \
+            } else if (up) {                                                                        \
+                ALPHA_BLEND_192_W(E[N3], px);                                                       \
+                ALPHA_BLEND_64_W( E[N1], px);                                                       \
+            } else { /* diagonal */                                                                 \
+                ALPHA_BLEND_128_W(E[N3], px);                                                       \
+            }                                                                                       \
+        } else if (e <= i) {                                                                        \
+            ALPHA_BLEND_128_W( E[N3], ((df(PE,PF) <= df(PE,PH)) ? PF : PH));                        \
+        }                                                                                           \
+    }                                                                                               \
+} while (0)
+
+#define FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1,   \
+              N0, N1, N2, N3, N4, N5, N6, N7, N8) do {                                              \
+    if (PE != PH && PE != PF) {                                                                     \
+        const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2);          \
+        const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2);          \
+        if (e < i && (!eq(PF,PB) && !eq(PF,PC) || !eq(PH,PD) && !eq(PH,PG) || eq(PE,PI)             \
+                      && (!eq(PF,F4) && !eq(PF,I4) || !eq(PH,H5) && !eq(PH,I5))                     \
+                      || eq(PE,PG) || eq(PE,PC))) {                                                 \
+            const unsigned ke = df(PF,PG);                                                          \
+            const unsigned ki = df(PH,PC);                                                          \
+            const int left    = ke<<1 <= ki && PE != PG && PD != PG;                                \
+            const int up      = ke >= ki<<1 && PE != PC && PB != PC;                                \
+            const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH;                                   \
+            if (left && up) {                                                                       \
+                ALPHA_BLEND_192_W(E[N7], px);                                                       \
+                ALPHA_BLEND_64_W( E[N6], px);                                                       \
+                E[N5] = E[N7];                                                                      \
+                E[N2] = E[N6];                                                                      \
+                E[N8] = px;                                                                         \
+            } else if (left) {                                                                      \
+                ALPHA_BLEND_192_W(E[N7], px);                                                       \
+                ALPHA_BLEND_64_W( E[N5], px);                                                       \
+                ALPHA_BLEND_64_W( E[N6], px);                                                       \
+                E[N8] = px;                                                                         \
+            } else if (up) {                                                                        \
+                ALPHA_BLEND_192_W(E[N5], px);                                                       \
+                ALPHA_BLEND_64_W( E[N7], px);                                                       \
+                ALPHA_BLEND_64_W( E[N2], px);                                                       \
+                E[N8] = px;                                                                         \
+            } else { /* diagonal */                                                                 \
+                ALPHA_BLEND_224_W(E[N8], px);                                                       \
+                ALPHA_BLEND_32_W( E[N5], px);                                                       \
+                ALPHA_BLEND_32_W( E[N7], px);                                                       \
+            }                                                                                       \
+        } else if (e <= i) {                                                                        \
+            ALPHA_BLEND_128_W(E[N8], ((df(PE,PF) <= df(PE,PH)) ? PF : PH));                         \
+        }                                                                                           \
+    }                                                                                               \
+} while (0)
+
+#define FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1,   \
+              N15, N14, N11, N3, N7, N10, N13, N12, N9, N6, N2, N1, N5, N8, N4, N0) do {            \
+    if (PE != PH && PE != PF) {                                                                     \
+        const unsigned e = df(PE,PC) + df(PE,PG) + df(PI,H5) + df(PI,F4) + (df(PH,PF)<<2);          \
+        const unsigned i = df(PH,PD) + df(PH,I5) + df(PF,I4) + df(PF,PB) + (df(PE,PI)<<2);          \
+        if (e < i && (!eq(PF,PB) && !eq(PH,PD) || eq(PE,PI)                                         \
+                      && (!eq(PF,I4) && !eq(PH,I5))                                                 \
+                      || eq(PE,PG) || eq(PE,PC))) {                                                 \
+            const unsigned ke = df(PF,PG);                                                          \
+            const unsigned ki = df(PH,PC);                                                          \
+            const int left    = ke<<1 <= ki && PE != PG && PD != PG;                                \
+            const int up      = ke >= ki<<1 && PE != PC && PB != PC;                                \
+            const unsigned px = df(PE,PF) <= df(PE,PH) ? PF : PH;                                   \
+            if (left && up) {                                                                       \
+                ALPHA_BLEND_192_W(E[N13], px);                                                      \
+                ALPHA_BLEND_64_W( E[N12], px);                                                      \
+                E[N15] = E[N14] = E[N11] = px;                                                      \
+                E[N10] = E[N3]  = E[N12];                                                           \
+                E[N7]  = E[N13];                                                                    \
+            } else if (left) {                                                                      \
+                ALPHA_BLEND_192_W(E[N11], px);                                                      \
+                ALPHA_BLEND_192_W(E[N13], px);                                                      \
+                ALPHA_BLEND_64_W( E[N10], px);                                                      \
+                ALPHA_BLEND_64_W( E[N12], px);                                                      \
+                E[N14] = px;                                                                        \
+                E[N15] = px;                                                                        \
+            } else if (up) {                                                                        \
+                ALPHA_BLEND_192_W(E[N14], px);                                                      \
+                ALPHA_BLEND_192_W(E[N7 ], px);                                                      \
+                ALPHA_BLEND_64_W( E[N10], px);                                                      \
+                ALPHA_BLEND_64_W( E[N3 ], px);                                                      \
+                E[N11] = px;                                                                        \
+                E[N15] = px;                                                                        \
+            } else { /* diagonal */                                                                 \
+                ALPHA_BLEND_128_W(E[N11], px);                                                      \
+                ALPHA_BLEND_128_W(E[N14], px);                                                      \
+                E[N15] = px;                                                                        \
+            }                                                                                       \
+        } else if (e <= i) {                                                                        \
+            ALPHA_BLEND_128_W( E[N15], ((df(PE,PF) <= df(PE,PH)) ? PF : PH));                       \
+        }                                                                                           \
+    }                                                                                               \
+} while (0)
+
+static av_always_inline void xbr_filter(const ThreadData *td, int jobnr, int nb_jobs, int n)
+{
+    int x, y;
+    const AVFrame *input = td->in;
+    AVFrame *output = td->out;
+    const uint32_t *r2y = td->rgbtoyuv;
+    const int slice_start = (input->height *  jobnr   ) / nb_jobs;
+    const int slice_end   = (input->height * (jobnr+1)) / nb_jobs;
+    const int nl = output->linesize[0] >> 2;
+    const int nl1 = nl + nl;
+    const int nl2 = nl1 + nl;
+
+    for (y = slice_start; y < slice_end; y++) {
+
+        uint32_t *E = (uint32_t *)(output->data[0] + y * output->linesize[0] * n);
+        const uint32_t *sa2 = (uint32_t *)(input->data[0] + y * input->linesize[0] - 8); /* center */
+        const uint32_t *sa1 = sa2 - (input->linesize[0]>>2); /* up x1 */
+        const uint32_t *sa0 = sa1 - (input->linesize[0]>>2); /* up x2 */
+        const uint32_t *sa3 = sa2 + (input->linesize[0]>>2); /* down x1 */
+        const uint32_t *sa4 = sa3 + (input->linesize[0]>>2); /* down x2 */
+
+        if (y <= 1) {
+            sa0 = sa1;
+            if (y == 0) {
+                sa0 = sa1 = sa2;
+            }
+        }
+
+        if (y >= input->height - 2) {
+            sa4 = sa3;
+            if (y == input->height - 1) {
+                sa4 = sa3 = sa2;
+            }
+        }
+
+        for (x = 0; x < input->width; x++) {
+            const uint32_t B1 = sa0[2];
+            const uint32_t PB = sa1[2];
+            const uint32_t PE = sa2[2];
+            const uint32_t PH = sa3[2];
+            const uint32_t H5 = sa4[2];
+
+            const int pprev = 2 - (x > 0);
+            const uint32_t A1 = sa0[pprev];
+            const uint32_t PA = sa1[pprev];
+            const uint32_t PD = sa2[pprev];
+            const uint32_t PG = sa3[pprev];
+            const uint32_t G5 = sa4[pprev];
+
+            const int pprev2 = pprev - (x > 1);
+            const uint32_t A0 = sa1[pprev2];
+            const uint32_t D0 = sa2[pprev2];
+            const uint32_t G0 = sa3[pprev2];
+
+            const int pnext = 3 - (x == input->width - 1);
+            const uint32_t C1 = sa0[pnext];
+            const uint32_t PC = sa1[pnext];
+            const uint32_t PF = sa2[pnext];
+            const uint32_t PI = sa3[pnext];
+            const uint32_t I5 = sa4[pnext];
+
+            const int pnext2 = pnext + 1 - (x >= input->width - 2);
+            const uint32_t C4 = sa1[pnext2];
+            const uint32_t F4 = sa2[pnext2];
+            const uint32_t I4 = sa3[pnext2];
+
+            if (n == 2) {
+                E[0]  = E[1]      =     // 0, 1
+                E[nl] = E[nl + 1] = PE; // 2, 3
+
+                FILT2(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, nl, nl+1);
+                FILT2(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl, 0, nl+1, 1);
+                FILT2(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl+1, nl, 1, 0);
+                FILT2(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 1, nl+1, 0, nl);
+            } else if (n == 3) {
+                E[0]   = E[1]     = E[2]     =     // 0, 1, 2
+                E[nl]  = E[nl+1]  = E[nl+2]  =     // 3, 4, 5
+                E[nl1] = E[nl1+1] = E[nl1+2] = PE; // 6, 7, 8
+
+                FILT3(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, 0, 1, 2, nl, nl+1, nl+2, nl1, nl1+1, nl1+2);
+                FILT3(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, nl1, nl, 0, nl1+1, nl+1, 1, nl1+2, nl+2, 2);
+                FILT3(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, nl1+2, nl1+1, nl1, nl+2, nl+1, nl, 2, 1, 0);
+                FILT3(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, 2, nl+2, nl1+2, 1, nl+1, nl1+1, 0, nl, nl1);
+            } else if (n == 4) {
+                E[0]   = E[1]     = E[2]     = E[3]     =     //  0,  1,  2,  3
+                E[nl]  = E[nl+1]  = E[nl+2]  = E[nl+3]  =     //  4,  5,  6,  7
+                E[nl1] = E[nl1+1] = E[nl1+2] = E[nl1+3] =     //  8,  9, 10, 11
+                E[nl2] = E[nl2+1] = E[nl2+2] = E[nl2+3] = PE; // 12, 13, 14, 15
+
+                FILT4(PE, PI, PH, PF, PG, PC, PD, PB, PA, G5, C4, G0, D0, C1, B1, F4, I4, H5, I5, A0, A1, nl2+3, nl2+2, nl1+3, 3, nl+3, nl1+2, nl2+1, nl2, nl1+1, nl+2, 2, 1, nl+1, nl1, nl, 0);
+                FILT4(PE, PC, PF, PB, PI, PA, PH, PD, PG, I4, A1, I5, H5, A0, D0, B1, C1, F4, C4, G5, G0, 3, nl+3, 2, 0, 1, nl+2, nl1+3, nl2+3, nl1+2, nl+1, nl, nl1, nl1+1, nl2+2, nl2+1, nl2);
+                FILT4(PE, PA, PB, PD, PC, PG, PF, PH, PI, C1, G0, C4, F4, G5, H5, D0, A0, B1, A1, I4, I5, 0, 1, nl, nl2, nl1, nl+1, 2, 3, nl+2, nl1+1, nl2+1, nl2+2, nl1+2, nl+3, nl1+3, nl2+3);
+                FILT4(PE, PG, PD, PH, PA, PI, PB, PF, PC, A0, I5, A1, B1, I4, F4, H5, G5, D0, G0, C1, C4, nl2, nl1, nl2+1, nl2+3, nl2+2, nl1+1, nl, 0, nl+1, nl1+2, nl1+3, nl+3, nl+2, 1, 2, 3);
+            }
+
+            sa0 += 1;
+            sa1 += 1;
+            sa2 += 1;
+            sa3 += 1;
+            sa4 += 1;
+
+            E += n;
+        }
+    }
+}
+
+#define XBR_FUNC(size) \
+static int xbr##size##x(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
+{ \
+    xbr_filter(arg, jobnr, nb_jobs, size); \
+    return 0; \
+}
+
+XBR_FUNC(2)
+XBR_FUNC(3)
+XBR_FUNC(4)
+
+
+static int config_output(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    XBRContext *xbr = ctx->priv;
+    AVFilterLink *inlink = ctx->inputs[0];
+
+    outlink->w = inlink->w * xbr->n;
+    outlink->h = inlink->h * xbr->n;
+    return 0;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    static const enum AVPixelFormat pix_fmts[] = {
+        AV_PIX_FMT_0RGB32, AV_PIX_FMT_NONE,
+    };
+
+    ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    XBRContext *xbr = ctx->priv;
+    ThreadData td;
+
+    AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
+    if (!out) {
+        av_frame_free(&in);
+        return AVERROR(ENOMEM);
+    }
+
+    av_frame_copy_props(out, in);
+
+    td.in = in;
+    td.out = out;
+    td.rgbtoyuv = xbr->rgbtoyuv;
+    ctx->internal->execute(ctx, xbr->func, &td, NULL, FFMIN(inlink->h, ctx->graph->nb_threads));
+
+    out->width  = outlink->w;
+    out->height = outlink->h;
+
+    av_frame_free(&in);
+    return ff_filter_frame(outlink, out);
+}
+
+static int init(AVFilterContext *ctx)
+{
+    XBRContext *xbr = ctx->priv;
+    static const xbrfunc_t xbrfuncs[] = {xbr2x, xbr3x, xbr4x};
+
+    uint32_t c;
+    int bg, rg, g;
+
+    for (bg = -255; bg < 256; bg++) {
+        for (rg = -255; rg < 256; rg++) {
+            const uint32_t u = (uint32_t)((-169*rg + 500*bg)/1000) + 128;
+            const uint32_t v = (uint32_t)(( 500*rg -  81*bg)/1000) + 128;
+            int startg = FFMAX3(-bg, -rg, 0);
+            int endg = FFMIN3(255-bg, 255-rg, 255);
+            uint32_t y = (uint32_t)(( 299*rg + 1000*startg + 114*bg)/1000);
+            c = bg + (rg<<16) + 0x010101 * startg;
+            for (g = startg; g <= endg; g++) {
+                xbr->rgbtoyuv[c] = ((y++) << 16) + (u << 8) + v;
+                c+= 0x010101;
+            }
+        }
+    }
+
+    xbr->func = xbrfuncs[xbr->n - 2];
+    return 0;
+}
+
+static const AVFilterPad xbr_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .filter_frame = filter_frame,
+    },
+    { NULL }
+};
+
+static const AVFilterPad xbr_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_VIDEO,
+        .config_props = config_output,
+    },
+    { NULL }
+};
+
+AVFilter ff_vf_xbr = {
+    .name          = "xbr",
+    .description   = NULL_IF_CONFIG_SMALL("Scale the input using xBR algorithm."),
+    .inputs        = xbr_inputs,
+    .outputs       = xbr_outputs,
+    .query_formats = query_formats,
+    .priv_size     = sizeof(XBRContext),
+    .priv_class    = &xbr_class,
+    .init          = init,
+    .flags         = AVFILTER_FLAG_SLICE_THREADS,
+};
diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c
index 70670c3..da6ee70 100644
--- a/libavfilter/vf_yadif.c
+++ b/libavfilter/vf_yadif.c
@@ -342,6 +342,9 @@
         return -1;
     }
 
+    if (!yadif->prev)
+        return 0;
+
     if ((yadif->deint && !yadif->cur->interlaced_frame) || ctx->is_disabled) {
         yadif->out  = av_frame_clone(yadif->cur);
         if (!yadif->out)
@@ -353,9 +356,6 @@
         return ff_filter_frame(ctx->outputs[0], yadif->out);
     }
 
-    if (!yadif->prev)
-        return 0;
-
     yadif->out = ff_get_video_buffer(ctx->outputs[0], link->w, link->h);
     if (!yadif->out)
         return AVERROR(ENOMEM);
diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile
index 32145db..44765d2 100644
--- a/libavfilter/x86/Makefile
+++ b/libavfilter/x86/Makefile
@@ -1,15 +1,19 @@
 OBJS-$(CONFIG_GRADFUN_FILTER)                += x86/vf_gradfun_init.o
 OBJS-$(CONFIG_HQDN3D_FILTER)                 += x86/vf_hqdn3d_init.o
 OBJS-$(CONFIG_IDET_FILTER)                   += x86/vf_idet_init.o
+OBJS-$(CONFIG_INTERLACE_FILTER)              += x86/vf_interlace_init.o
 OBJS-$(CONFIG_NOISE_FILTER)                  += x86/vf_noise.o
 OBJS-$(CONFIG_PULLUP_FILTER)                 += x86/vf_pullup_init.o
 OBJS-$(CONFIG_SPP_FILTER)                    += x86/vf_spp.o
+OBJS-$(CONFIG_TINTERLACE_FILTER)             += x86/vf_tinterlace_init.o
 OBJS-$(CONFIG_VOLUME_FILTER)                 += x86/af_volume_init.o
 OBJS-$(CONFIG_YADIF_FILTER)                  += x86/vf_yadif_init.o
 
 YASM-OBJS-$(CONFIG_GRADFUN_FILTER)           += x86/vf_gradfun.o
 YASM-OBJS-$(CONFIG_HQDN3D_FILTER)            += x86/vf_hqdn3d.o
 YASM-OBJS-$(CONFIG_IDET_FILTER)              += x86/vf_idet.o
+YASM-OBJS-$(CONFIG_INTERLACE_FILTER)         += x86/vf_interlace.o
 YASM-OBJS-$(CONFIG_PULLUP_FILTER)            += x86/vf_pullup.o
+YASM-OBJS-$(CONFIG_TINTERLACE_FILTER)        += x86/vf_interlace.o
 YASM-OBJS-$(CONFIG_VOLUME_FILTER)            += x86/af_volume.o
 YASM-OBJS-$(CONFIG_YADIF_FILTER)             += x86/vf_yadif.o x86/yadif-16.o x86/yadif-10.o
diff --git a/libavfilter/x86/vf_interlace.asm b/libavfilter/x86/vf_interlace.asm
new file mode 100644
index 0000000..ce3dd81
--- /dev/null
+++ b/libavfilter/x86/vf_interlace.asm
@@ -0,0 +1,65 @@
+;*****************************************************************************
+;* x86-optimized functions for interlace filter
+;*
+;* Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv>
+;* Copyright (c) 2014 Michael Niedermayer <michaelni@gmx.at>
+;*
+;* This file is part of FFmpeg.
+;*
+;* FFmpeg is free software; you can redistribute it and/or modify
+;* it under the terms of the GNU General Public License as published by
+;* the Free Software Foundation; either version 2 of the License, or
+;* (at your option) any later version.
+;*
+;* FFmpeg is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;* GNU General Public License for more details.
+;*
+;* You should have received a copy of the GNU General Public License along
+;* with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+;* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;******************************************************************************
+
+%include "libavutil/x86/x86util.asm"
+
+SECTION_RODATA
+
+SECTION .text
+
+%macro LOWPASS_LINE 0
+cglobal lowpass_line, 5, 5, 7
+    add r0, r1
+    add r2, r1
+    add r3, r1
+    add r4, r1
+    neg r1
+
+    pcmpeqb m6, m6
+
+.loop
+    mova m0, [r3+r1]
+    mova m1, [r3+r1+mmsize]
+    pavgb m0, [r4+r1]
+    pavgb m1, [r4+r1+mmsize]
+    pxor m0, m6
+    pxor m1, m6
+    pxor m2, m6, [r2+r1]
+    pxor m3, m6, [r2+r1+mmsize]
+    pavgb m0, m2
+    pavgb m1, m3
+    pxor m0, m6
+    pxor m1, m6
+    mova [r0+r1], m0
+    mova [r0+r1+mmsize], m1
+
+    add r1, 2*mmsize
+    jl .loop
+REP_RET
+%endmacro
+
+INIT_XMM sse2
+LOWPASS_LINE
+
+INIT_XMM avx
+LOWPASS_LINE
diff --git a/libavfilter/x86/vf_interlace_init.c b/libavfilter/x86/vf_interlace_init.c
new file mode 100644
index 0000000..68ee47d
--- /dev/null
+++ b/libavfilter/x86/vf_interlace_init.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv>
+ *
+ * This file is part of FFmpeg.
+ *
+  * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/internal.h"
+#include "libavutil/mem.h"
+#include "libavutil/x86/asm.h"
+#include "libavutil/x86/cpu.h"
+
+#include "libavfilter/interlace.h"
+
+void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp,
+                          const uint8_t *srcp_above,
+                          const uint8_t *srcp_below);
+void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp,
+                          const uint8_t *srcp_above,
+                          const uint8_t *srcp_below);
+
+av_cold void ff_interlace_init_x86(InterlaceContext *s)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (EXTERNAL_SSE2(cpu_flags))
+        s->lowpass_line = ff_lowpass_line_sse2;
+    if (EXTERNAL_AVX(cpu_flags))
+        s->lowpass_line = ff_lowpass_line_avx;
+}
diff --git a/libavfilter/x86/vf_tinterlace_init.c b/libavfilter/x86/vf_tinterlace_init.c
new file mode 100644
index 0000000..ddb0cce
--- /dev/null
+++ b/libavfilter/x86/vf_tinterlace_init.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 Kieran Kunhya <kierank@obe.tv>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/internal.h"
+#include "libavutil/mem.h"
+#include "libavutil/x86/asm.h"
+#include "libavutil/x86/cpu.h"
+
+#include "libavfilter/tinterlace.h"
+
+void ff_lowpass_line_sse2(uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp,
+                          const uint8_t *srcp_above,
+                          const uint8_t *srcp_below);
+void ff_lowpass_line_avx (uint8_t *dstp, ptrdiff_t linesize,
+                          const uint8_t *srcp,
+                          const uint8_t *srcp_above,
+                          const uint8_t *srcp_below);
+
+av_cold void ff_tinterlace_init_x86(TInterlaceContext *s)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (EXTERNAL_SSE2(cpu_flags))
+        s->lowpass_line = ff_lowpass_line_sse2;
+    if (EXTERNAL_AVX(cpu_flags))
+        s->lowpass_line = ff_lowpass_line_avx;
+}
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 62dc41c..c1b5ace 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -76,6 +76,7 @@
 OBJS-$(CONFIG_ANM_DEMUXER)               += anm.o
 OBJS-$(CONFIG_APC_DEMUXER)               += apc.o
 OBJS-$(CONFIG_APE_DEMUXER)               += ape.o apetag.o img2.o
+OBJS-$(CONFIG_APNG_DEMUXER)              += apngdec.o
 OBJS-$(CONFIG_AQTITLE_DEMUXER)           += aqtitledec.o subtitles.o
 OBJS-$(CONFIG_ASF_DEMUXER)               += asfdec.o asf.o asfcrypt.o \
                                             avlanguage.o
@@ -114,6 +115,7 @@
 OBJS-$(CONFIG_CRC_MUXER)                 += crcenc.o
 OBJS-$(CONFIG_DATA_DEMUXER)              += rawdec.o
 OBJS-$(CONFIG_DATA_MUXER)                += rawdec.o
+OBJS-$(CONFIG_DASH_MUXER)                += dashenc.o isom.o
 OBJS-$(CONFIG_DAUD_DEMUXER)              += dauddec.o
 OBJS-$(CONFIG_DAUD_MUXER)                += daudenc.o
 OBJS-$(CONFIG_DFA_DEMUXER)               += dfa.o
@@ -450,6 +452,7 @@
                                             oggparsevorbis.o vorbiscomment.o \
                                             flac_picture.o replaygain.o
 OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER)  += webmdashenc.o matroska.o
+OBJS-$(CONFIG_WEBP_MUXER)                += webpenc.o
 OBJS-$(CONFIG_WEBVTT_DEMUXER)            += webvttdec.o subtitles.o
 OBJS-$(CONFIG_WEBVTT_MUXER)              += webvttenc.o
 OBJS-$(CONFIG_WSAUD_DEMUXER)             += westwood_aud.o
@@ -533,3 +536,4 @@
             pktdumper                                                   \
             probetest                                                   \
             seek_print                                                  \
+            sidxindex                                                   \
diff --git a/libavformat/allformats.c b/libavformat/allformats.c
index bf81737..81aab56 100644
--- a/libavformat/allformats.c
+++ b/libavformat/allformats.c
@@ -74,6 +74,7 @@
     REGISTER_DEMUXER (ANM,              anm);
     REGISTER_DEMUXER (APC,              apc);
     REGISTER_DEMUXER (APE,              ape);
+    REGISTER_DEMUXER (APNG,             apng);
     REGISTER_DEMUXER (AQTITLE,          aqtitle);
     REGISTER_MUXDEMUX(ASF,              asf);
     REGISTER_MUXDEMUX(ASS,              ass);
@@ -101,6 +102,7 @@
     REGISTER_DEMUXER (CINE,             cine);
     REGISTER_DEMUXER (CONCAT,           concat);
     REGISTER_MUXER   (CRC,              crc);
+    REGISTER_MUXER   (DASH,             dash);
     REGISTER_MUXDEMUX(DATA,             data);
     REGISTER_MUXDEMUX(DAUD,             daud);
     REGISTER_DEMUXER (DFA,              dfa);
@@ -310,6 +312,7 @@
     REGISTER_DEMUXER (WC3,              wc3);
     REGISTER_MUXER   (WEBM,             webm);
     REGISTER_MUXDEMUX(WEBM_DASH_MANIFEST, webm_dash_manifest);
+    REGISTER_MUXER   (WEBP,             webp);
     REGISTER_MUXDEMUX(WEBVTT,           webvtt);
     REGISTER_DEMUXER (WSAUD,            wsaud);
     REGISTER_DEMUXER (WSVQA,            wsvqa);
@@ -370,6 +373,7 @@
     REGISTER_PROTOCOL(TCP,              tcp);
     REGISTER_PROTOCOL(TLS,              tls);
     REGISTER_PROTOCOL(UDP,              udp);
+    REGISTER_PROTOCOL(UDPLITE,          udplite);
     REGISTER_PROTOCOL(UNIX,             unix);
 
     /* external libraries */
diff --git a/libavformat/apng.h b/libavformat/apng.h
new file mode 100644
index 0000000..2abf011
--- /dev/null
+++ b/libavformat/apng.h
@@ -0,0 +1,41 @@
+/*
+ * APNG common header
+ * Copyright (c) 2014 Benoit Fouet
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * APNG common header
+ */
+
+#ifndef AVFORMAT_APNG_H
+#define AVFORMAT_APNG_H
+
+enum {
+   APNG_DISPOSE_OP_NONE       = 0,
+   APNG_DISPOSE_OP_BACKGROUND = 1,
+   APNG_DISPOSE_OP_PREVIOUS   = 2,
+};
+
+enum {
+    APNG_BLEND_OP_SOURCE = 0,
+    APNG_BLEND_OP_OVER   = 1,
+};
+
+#endif /* AVFORMAT_APNG_H */
diff --git a/libavformat/apngdec.c b/libavformat/apngdec.c
new file mode 100644
index 0000000..276d765
--- /dev/null
+++ b/libavformat/apngdec.c
@@ -0,0 +1,446 @@
+/*
+ * APNG demuxer
+ * Copyright (c) 2014 Benoit Fouet
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * APNG demuxer.
+ * @see https://wiki.mozilla.org/APNG_Specification
+ * @see http://www.w3.org/TR/PNG
+ */
+
+#include "apng.h"
+#include "avformat.h"
+#include "avio_internal.h"
+#include "internal.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "libavcodec/png.h"
+#include "libavcodec/bytestream.h"
+
+#define DEFAULT_APNG_FPS 15
+
+typedef struct APNGDemuxContext {
+    const AVClass *class;
+
+    int max_fps;
+    int default_fps;
+
+    int64_t pkt_pts;
+    int pkt_duration;
+
+    int is_key_frame;
+
+    /*
+     * loop options
+     */
+    int ignore_loop;
+    uint32_t num_frames;
+    uint32_t num_play;
+    uint32_t cur_loop;
+} APNGDemuxContext;
+
+/*
+ * To be a valid APNG file, we mandate, in this order:
+ *     PNGSIG
+ *     IHDR
+ *     ...
+ *     acTL
+ *     ...
+ *     IDAT
+ */
+static int apng_probe(AVProbeData *p)
+{
+    GetByteContext gb;
+    int state = 0;
+    uint32_t len, tag;
+
+    bytestream2_init(&gb, p->buf, p->buf_size);
+
+    if (bytestream2_get_be64(&gb) != PNGSIG)
+        return 0;
+
+    for (;;) {
+        len = bytestream2_get_be32(&gb);
+        if (len > 0x7fffffff)
+            return 0;
+
+        tag = bytestream2_get_le32(&gb);
+        /* we don't check IDAT size, as this is the last tag
+         * we check, and it may be larger than the probe buffer */
+        if (tag != MKTAG('I', 'D', 'A', 'T') &&
+            len > bytestream2_get_bytes_left(&gb))
+            return 0;
+
+        switch (tag) {
+        case MKTAG('I', 'H', 'D', 'R'):
+            if (len != 13)
+                return 0;
+            if (av_image_check_size(bytestream2_get_be32(&gb), bytestream2_get_be32(&gb), 0, NULL))
+                return 0;
+            bytestream2_skip(&gb, 9);
+            state++;
+            break;
+        case MKTAG('a', 'c', 'T', 'L'):
+            if (state != 1 ||
+                len != 8 ||
+                bytestream2_get_be32(&gb) == 0) /* 0 is not a valid value for number of frames */
+                return 0;
+            bytestream2_skip(&gb, 8);
+            state++;
+            break;
+        case MKTAG('I', 'D', 'A', 'T'):
+            if (state != 2)
+                return 0;
+            goto end;
+        default:
+            /* skip other tags */
+            bytestream2_skip(&gb, len + 4);
+            break;
+        }
+    }
+
+end:
+    return AVPROBE_SCORE_MAX;
+}
+
+static int append_extradata(AVCodecContext *s, AVIOContext *pb, int len)
+{
+    int previous_size = s->extradata_size;
+    int new_size, ret;
+    uint8_t *new_extradata;
+
+    if (previous_size > INT_MAX - len)
+        return AVERROR_INVALIDDATA;
+
+    new_size = previous_size + len;
+    new_extradata = av_realloc(s->extradata, new_size + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!new_extradata)
+        return AVERROR(ENOMEM);
+    s->extradata = new_extradata;
+    s->extradata_size = new_size;
+
+    if ((ret = avio_read(pb, s->extradata + previous_size, len)) < 0)
+        return ret;
+
+    return previous_size;
+}
+
+static int apng_read_header(AVFormatContext *s)
+{
+    APNGDemuxContext *ctx = s->priv_data;
+    AVIOContext *pb = s->pb;
+    uint32_t len, tag;
+    AVStream *st;
+    int ret = AVERROR_INVALIDDATA, acTL_found = 0;
+
+    /* verify PNGSIG */
+    if (avio_rb64(pb) != PNGSIG)
+        return ret;
+
+    /* parse IHDR (must be first chunk) */
+    len = avio_rb32(pb);
+    tag = avio_rl32(pb);
+    if (len != 13 || tag != MKTAG('I', 'H', 'D', 'R'))
+        return ret;
+
+    st = avformat_new_stream(s, NULL);
+    if (!st)
+        return AVERROR(ENOMEM);
+
+    /* set the timebase to something large enough (1/100,000 of second)
+     * to hopefully cope with all sane frame durations */
+    avpriv_set_pts_info(st, 64, 1, 100000);
+    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+    st->codec->codec_id   = AV_CODEC_ID_APNG;
+    st->codec->width      = avio_rb32(pb);
+    st->codec->height     = avio_rb32(pb);
+    if ((ret = av_image_check_size(st->codec->width, st->codec->height, 0, s)) < 0)
+        return ret;
+
+    /* extradata will contain every chunk up to the first fcTL (excluded) */
+    st->codec->extradata = av_malloc(len + 12 + FF_INPUT_BUFFER_PADDING_SIZE);
+    if (!st->codec->extradata)
+        return AVERROR(ENOMEM);
+    st->codec->extradata_size = len + 12;
+    AV_WB32(st->codec->extradata,    len);
+    AV_WL32(st->codec->extradata+4,  tag);
+    AV_WB32(st->codec->extradata+8,  st->codec->width);
+    AV_WB32(st->codec->extradata+12, st->codec->height);
+    if ((ret = avio_read(pb, st->codec->extradata+16, 9)) < 0)
+        goto fail;
+
+    while (!avio_feof(pb)) {
+        if (acTL_found && ctx->num_play != 1) {
+            int64_t size   = avio_size(pb);
+            int64_t offset = avio_tell(pb);
+            if (size < 0) {
+                ret = size;
+                goto fail;
+            } else if (offset < 0) {
+                ret = offset;
+                goto fail;
+            } else if ((ret = ffio_ensure_seekback(pb, size - offset)) < 0) {
+                av_log(s, AV_LOG_WARNING, "Could not ensure seekback, will not loop\n");
+                ctx->num_play = 1;
+            }
+        }
+        if ((ctx->num_play == 1 || !acTL_found) &&
+            ((ret = ffio_ensure_seekback(pb, 4 /* len */ + 4 /* tag */)) < 0))
+            goto fail;
+
+        len = avio_rb32(pb);
+        if (len > 0x7fffffff) {
+            ret = AVERROR_INVALIDDATA;
+            goto fail;
+        }
+
+        tag = avio_rl32(pb);
+        switch (tag) {
+        case MKTAG('a', 'c', 'T', 'L'):
+            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
+                (ret = append_extradata(st->codec, pb, len + 12)) < 0)
+                goto fail;
+            acTL_found = 1;
+            ctx->num_frames = AV_RB32(st->codec->extradata + ret + 8);
+            ctx->num_play   = AV_RB32(st->codec->extradata + ret + 12);
+            av_log(s, AV_LOG_DEBUG, "num_frames: %"PRIu32", num_play: %"PRIu32"\n",
+                                    ctx->num_frames, ctx->num_play);
+            break;
+        case MKTAG('f', 'c', 'T', 'L'):
+            if (!acTL_found) {
+               ret = AVERROR_INVALIDDATA;
+               goto fail;
+            }
+            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)
+                goto fail;
+            return 0;
+        default:
+            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
+                (ret = append_extradata(st->codec, pb, len + 12)) < 0)
+                goto fail;
+        }
+    }
+
+fail:
+    if (st->codec->extradata_size) {
+        av_freep(&st->codec->extradata);
+        st->codec->extradata_size = 0;
+    }
+    return ret;
+}
+
+static int decode_fctl_chunk(AVFormatContext *s, APNGDemuxContext *ctx, AVPacket *pkt)
+{
+    uint32_t sequence_number, width, height, x_offset, y_offset;
+    uint16_t delay_num, delay_den;
+    uint8_t dispose_op, blend_op;
+
+    sequence_number = avio_rb32(s->pb);
+    width           = avio_rb32(s->pb);
+    height          = avio_rb32(s->pb);
+    x_offset        = avio_rb32(s->pb);
+    y_offset        = avio_rb32(s->pb);
+    delay_num       = avio_rb16(s->pb);
+    delay_den       = avio_rb16(s->pb);
+    dispose_op      = avio_r8(s->pb);
+    blend_op        = avio_r8(s->pb);
+    avio_skip(s->pb, 4); /* crc */
+
+    /* default is hundredths of seconds */
+    if (!delay_den)
+        delay_den = 100;
+    if (!delay_num || delay_den / delay_num > ctx->max_fps) {
+        delay_num = 1;
+        delay_den = ctx->default_fps;
+    }
+    ctx->pkt_duration = av_rescale_q(delay_num,
+                                     (AVRational){ 1, delay_den },
+                                     s->streams[0]->time_base);
+
+    av_log(s, AV_LOG_DEBUG, "%s: "
+            "sequence_number: %"PRId32", "
+            "width: %"PRIu32", "
+            "height: %"PRIu32", "
+            "x_offset: %"PRIu32", "
+            "y_offset: %"PRIu32", "
+            "delay_num: %"PRIu16", "
+            "delay_den: %"PRIu16", "
+            "dispose_op: %d, "
+            "blend_op: %d\n",
+            __FUNCTION__,
+            sequence_number,
+            width,
+            height,
+            x_offset,
+            y_offset,
+            delay_num,
+            delay_den,
+            dispose_op,
+            blend_op);
+
+    if (width != s->streams[0]->codec->width ||
+        height != s->streams[0]->codec->height ||
+        x_offset != 0 ||
+        y_offset != 0) {
+        if (sequence_number == 0 ||
+            x_offset >= s->streams[0]->codec->width ||
+            width > s->streams[0]->codec->width - x_offset ||
+            y_offset >= s->streams[0]->codec->height ||
+            height > s->streams[0]->codec->height - y_offset)
+            return AVERROR_INVALIDDATA;
+        ctx->is_key_frame = 0;
+    } else {
+        if (sequence_number == 0 && dispose_op == APNG_DISPOSE_OP_PREVIOUS)
+            dispose_op = APNG_DISPOSE_OP_BACKGROUND;
+        ctx->is_key_frame = dispose_op == APNG_DISPOSE_OP_BACKGROUND ||
+                            blend_op   == APNG_BLEND_OP_SOURCE;
+    }
+
+    return 0;
+}
+
+static int apng_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    APNGDemuxContext *ctx = s->priv_data;
+    int ret;
+    int64_t size;
+    AVIOContext *pb = s->pb;
+    uint32_t len, tag;
+
+    /*
+     * fcTL chunk length, in bytes:
+     *  4 (length)
+     *  4 (tag)
+     * 26 (actual chunk)
+     *  4 (crc) bytes
+     * and needed next:
+     *  4 (length)
+     *  4 (tag (must be fdAT or IDAT))
+     */
+    /* if num_play is not 1, then the seekback is already guaranteed */
+    if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 46)) < 0)
+        return ret;
+
+    len = avio_rb32(pb);
+    tag = avio_rl32(pb);
+    switch (tag) {
+    case MKTAG('f', 'c', 'T', 'L'):
+        if (len != 26)
+            return AVERROR_INVALIDDATA;
+
+        if ((ret = decode_fctl_chunk(s, ctx, pkt)) < 0)
+            return ret;
+
+        /* fcTL must precede fdAT or IDAT */
+        len = avio_rb32(pb);
+        tag = avio_rl32(pb);
+        if (len > 0x7fffffff ||
+            tag != MKTAG('f', 'd', 'A', 'T') &&
+            tag != MKTAG('I', 'D', 'A', 'T'))
+            return AVERROR_INVALIDDATA;
+
+        size = 38 /* fcTL */ + 8 /* len, tag */ + len + 4 /* crc */;
+        if (size > INT_MAX)
+            return AVERROR(EINVAL);
+
+        if ((ret = avio_seek(pb, -46, SEEK_CUR)) < 0 ||
+            (ret = av_append_packet(pb, pkt, size)) < 0)
+            return ret;
+
+        if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0)
+            return ret;
+
+        len = avio_rb32(pb);
+        tag = avio_rl32(pb);
+        while (tag &&
+               tag != MKTAG('f', 'c', 'T', 'L') &&
+               tag != MKTAG('I', 'E', 'N', 'D')) {
+            if (len > 0x7fffffff)
+                return AVERROR_INVALIDDATA;
+            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
+                (ret = av_append_packet(pb, pkt, len + 12)) < 0)
+                return ret;
+            if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0)
+                return ret;
+            len = avio_rb32(pb);
+            tag = avio_rl32(pb);
+        }
+        if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)
+            return ret;
+
+        if (ctx->is_key_frame)
+            pkt->flags |= AV_PKT_FLAG_KEY;
+        pkt->pts = ctx->pkt_pts;
+        pkt->duration = ctx->pkt_duration;
+        ctx->pkt_pts += ctx->pkt_duration;
+        return ret;
+    case MKTAG('I', 'E', 'N', 'D'):
+        ctx->cur_loop++;
+        if (ctx->ignore_loop || ctx->num_play >= 1 && ctx->cur_loop == ctx->num_play) {
+            avio_seek(pb, -8, SEEK_CUR);
+            return AVERROR_EOF;
+        }
+        if ((ret = avio_seek(pb, s->streams[0]->codec->extradata_size + 8, SEEK_SET)) < 0)
+            return ret;
+        return 0;
+    default:
+        {
+        char tag_buf[5];
+
+        av_get_codec_tag_string(tag_buf, sizeof(tag_buf), tag);
+        avpriv_request_sample(s, "In-stream tag=%s (0x%08X) len=%"PRIu32, tag_buf, tag, len);
+        avio_skip(pb, len + 4);
+        }
+    }
+
+    /* Handle the unsupported yet cases */
+    return AVERROR_PATCHWELCOME;
+}
+
+static const AVOption options[] = {
+    { "ignore_loop", "ignore loop setting"                         , offsetof(APNGDemuxContext, ignore_loop),
+      AV_OPT_TYPE_INT, { .i64 = 1 }               , 0, 1      , AV_OPT_FLAG_DECODING_PARAM },
+    { "max_fps"    , "maximum framerate (0 is no limit)"           , offsetof(APNGDemuxContext, max_fps),
+      AV_OPT_TYPE_INT, { .i64 = DEFAULT_APNG_FPS }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { "default_fps", "default framerate (0 is as fast as possible)", offsetof(APNGDemuxContext, default_fps),
+      AV_OPT_TYPE_INT, { .i64 = DEFAULT_APNG_FPS }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { NULL },
+};
+
+static const AVClass demuxer_class = {
+    .class_name = "APNG demuxer",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+    .category   = AV_CLASS_CATEGORY_DEMUXER,
+};
+
+AVInputFormat ff_apng_demuxer = {
+    .name           = "apng",
+    .long_name      = NULL_IF_CONFIG_SMALL("Animated Portable Network Graphics"),
+    .priv_data_size = sizeof(APNGDemuxContext),
+    .read_probe     = apng_probe,
+    .read_header    = apng_read_header,
+    .read_packet    = apng_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+    .priv_class     = &demuxer_class,
+};
diff --git a/libavformat/assenc.c b/libavformat/assenc.c
index 8225967..bde1096 100644
--- a/libavformat/assenc.c
+++ b/libavformat/assenc.c
@@ -23,6 +23,8 @@
 #include "avformat.h"
 #include "internal.h"
 
+#include "libavutil/opt.h"
+
 typedef struct DialogueLine {
     int readorder;
     char *line;
@@ -30,12 +32,14 @@
 } DialogueLine;
 
 typedef struct ASSContext{
+    const AVClass *class;
     int write_ts; // 0: ssa (timing in payload), 1: ass (matroska like)
     int expected_readorder;
     DialogueLine *dialogue_cache;
     DialogueLine *last_added_dialogue;
     int cache_size;
     int ssa_mode;
+    int ignore_readorder;
 }ASSContext;
 
 static int write_header(AVFormatContext *s)
@@ -178,7 +182,7 @@
             return AVERROR(ENOMEM);
         }
         insert_dialogue(ass, dialogue);
-        purge_dialogues(s, 0);
+        purge_dialogues(s, ass->ignore_readorder);
     } else {
         avio_write(s->pb, pkt->data, pkt->size);
     }
@@ -192,6 +196,20 @@
     return 0;
 }
 
+#define OFFSET(x) offsetof(ASSContext, x)
+#define E AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "ignore_readorder", "write events immediately, even if they're out-of-order", OFFSET(ignore_readorder), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E },
+    { NULL },
+};
+
+static const AVClass ass_class = {
+    .class_name = "ass muxer",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
 AVOutputFormat ff_ass_muxer = {
     .name           = "ass",
     .long_name      = NULL_IF_CONFIG_SMALL("SSA (SubStation Alpha) subtitle"),
@@ -203,4 +221,5 @@
     .write_packet   = write_packet,
     .write_trailer  = write_trailer,
     .flags          = AVFMT_GLOBALHEADER | AVFMT_NOTIMESTAMPS | AVFMT_TS_NONSTRICT,
+    .priv_class     = &ass_class,
 };
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index f21a1d6..2e54ed1 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -916,7 +916,7 @@
     /**
      * Stream information used internally by av_find_stream_info()
      */
-#define MAX_STD_TIMEBASES (60*12+6)
+#define MAX_STD_TIMEBASES (30*12+7+6)
     struct {
         int64_t last_dts;
         int64_t duration_gcd;
@@ -1097,11 +1097,26 @@
      */
     int inject_global_side_data;
 
+    /**
+     * String containing paris of key and values describing recommended encoder configuration.
+     * Paris are separated by ','.
+     * Keys are separated from values by '='.
+     */
+    char *recommended_encoder_configuration;
+
+    /**
+     * display aspect ratio (0 if unknown)
+     * - encoding: unused
+     * - decoding: Set by libavformat to calculate sample_aspect_ratio internally
+     */
+    AVRational display_aspect_ratio;
 } AVStream;
 
 AVRational av_stream_get_r_frame_rate(const AVStream *s);
 void       av_stream_set_r_frame_rate(AVStream *s, AVRational r);
 struct AVCodecParserContext *av_stream_get_parser(const AVStream *s);
+char* av_stream_get_recommended_encoder_configuration(const AVStream *s);
+void  av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration);
 
 /**
  * Returns the pts of the last muxed packet + its duration
@@ -1475,6 +1490,18 @@
      */
     int max_ts_probe;
 
+    /**
+     * Avoid negative timestamps during muxing.
+     * Any value of the AVFMT_AVOID_NEG_TS_* constants.
+     * Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts is in use)
+     * - muxing: Set by user
+     * - demuxing: unused
+     */
+    int avoid_negative_ts;
+#define AVFMT_AVOID_NEG_TS_AUTO             -1 ///< Enabled when required by target format
+#define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative
+#define AVFMT_AVOID_NEG_TS_MAKE_ZERO         2 ///< Shift timestamps so that they start at 0
+
 
     /**
      * Transport stream id.
@@ -1515,17 +1542,6 @@
     int use_wallclock_as_timestamps;
 
     /**
-     * Avoid negative timestamps during muxing.
-     *  0 -> allow negative timestamps
-     *  1 -> avoid negative timestamps
-     * -1 -> choose automatically (default)
-     * Note, this only works when interleave_packet_per_dts is in use.
-     * - encoding: Set by user via AVOptions (NO direct access)
-     * - decoding: unused
-     */
-    int avoid_negative_ts;
-
-    /**
      * avio flags, used to force AVIO_FLAG_DIRECT.
      * - encoding: unused
      * - decoding: Set by user via AVOptions (NO direct access)
@@ -1585,7 +1601,7 @@
     int format_probesize;
 
     /**
-     * ',' seperated list of allowed decoders.
+     * ',' separated list of allowed decoders.
      * If NULL then all are allowed
      * - encoding: unused
      * - decoding: set by user through AVOptions (NO direct access)
@@ -1593,7 +1609,7 @@
     char *codec_whitelist;
 
     /**
-     * ',' seperated list of allowed demuxers.
+     * ',' separated list of allowed demuxers.
      * If NULL then all are allowed
      * - encoding: unused
      * - decoding: set by user through AVOptions (NO direct access)
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 0cdcc08..78a6dea 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -1150,7 +1150,7 @@
             goto start_sync;
         }
 
-        n = avi->dv_demux ? 0 : get_stream_idx(d);
+        n = get_stream_idx(d);
 
         if (!((i - avi->last_pkt_pos) & 1) &&
             get_stream_idx(d + 1) < s->nb_streams)
@@ -1162,6 +1162,9 @@
             goto start_sync;
         }
 
+        if (avi->dv_demux && n != 0)
+            continue;
+
         // parse ##dc/##wb
         if (n < s->nb_streams) {
             AVStream *st;
diff --git a/libavformat/avienc.c b/libavformat/avienc.c
index e05e022..944c154 100644
--- a/libavformat/avienc.c
+++ b/libavformat/avienc.c
@@ -67,9 +67,13 @@
     int entry;
     int max_size;
 
+    int64_t last_dts;
+
     AVIIndex indexes;
 } AVIStream;
 
+static int avi_write_packet(AVFormatContext *s, AVPacket *pkt);
+
 static inline AVIIentry *avi_get_ientry(const AVIIndex *idx, int ent_id)
 {
     int cl = ent_id / AVI_INDEX_CLUSTER_SIZE;
@@ -565,6 +569,32 @@
     return 0;
 }
 
+static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts)
+{
+    AVIStream *avist    = s->streams[stream_index]->priv_data;
+    AVCodecContext *enc = s->streams[stream_index]->codec;
+
+    av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(dts), avist->packet_count, stream_index);
+    while (enc->block_align == 0 && dts != AV_NOPTS_VALUE &&
+           dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
+        AVPacket empty_packet;
+
+        if (dts - avist->packet_count > 60000) {
+            av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", dts - avist->packet_count);
+            return AVERROR(EINVAL);
+        }
+
+        av_init_packet(&empty_packet);
+        empty_packet.size         = 0;
+        empty_packet.data         = NULL;
+        empty_packet.stream_index = stream_index;
+        avi_write_packet(s, &empty_packet);
+        av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(dts), avist->packet_count);
+    }
+
+    return 0;
+}
+
 static int avi_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     unsigned char tag[5];
@@ -575,29 +605,20 @@
     AVIOContext *pb     = s->pb;
     AVIStream *avist    = s->streams[stream_index]->priv_data;
     AVCodecContext *enc = s->streams[stream_index]->codec;
+    int ret;
 
     if (enc->codec_id == AV_CODEC_ID_H264 && enc->codec_tag == MKTAG('H','2','6','4') && pkt->size) {
-        int ret = ff_check_h264_startcode(s, s->streams[stream_index], pkt);
+        ret = ff_check_h264_startcode(s, s->streams[stream_index], pkt);
         if (ret < 0)
             return ret;
     }
-    av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index);
-    while (enc->block_align == 0 && pkt->dts != AV_NOPTS_VALUE &&
-           pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) {
-        AVPacket empty_packet;
 
-        if (pkt->dts - avist->packet_count > 60000) {
-            av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", pkt->dts - avist->packet_count);
-            return AVERROR(EINVAL);
-        }
+    if ((ret = write_skip_frames(s, stream_index, pkt->dts)) < 0)
+        return ret;
 
-        av_init_packet(&empty_packet);
-        empty_packet.size         = 0;
-        empty_packet.data         = NULL;
-        empty_packet.stream_index = stream_index;
-        avi_write_packet(s, &empty_packet);
-        av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(pkt->dts), avist->packet_count);
-    }
+    if (pkt->dts != AV_NOPTS_VALUE)
+        avist->last_dts = pkt->dts + pkt->duration;
+
     avist->packet_count++;
 
     // Make sure to put an OpenDML chunk when the file size exceeds the limits
@@ -661,6 +682,11 @@
     int i, j, n, nb_frames;
     int64_t file_size;
 
+    for (i = 0; i < s->nb_streams; i++) {
+        AVIStream *avist = s->streams[i]->priv_data;
+        write_skip_frames(s, i, avist->last_dts);
+    }
+
     if (pb->seekable) {
         if (avi->riff_id == 1) {
             ff_end_tag(pb, avi->movi_list);
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 86f754e..b9b4017 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -186,6 +186,9 @@
  *
  * @param buffer Memory block for input/output operations via AVIOContext.
  *        The buffer must be allocated with av_malloc() and friends.
+ *        It may be freed and replaced with a new buffer by libavformat.
+ *        AVIOContext.buffer holds the buffer currently in use,
+ *        which must be later freed with av_free().
  * @param buffer_size The buffer size is very important for performance.
  *        For protocols with fixed blocksize it should be set to this blocksize.
  *        For others a typical size is a cache page, e.g. 4kb.
diff --git a/libavformat/cinedec.c b/libavformat/cinedec.c
index 5776708..632f46c 100644
--- a/libavformat/cinedec.c
+++ b/libavformat/cinedec.c
@@ -27,6 +27,7 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavcodec/bmp.h"
+#include "libavutil/intfloat.h"
 #include "avformat.h"
 #include "internal.h"
 
@@ -78,6 +79,16 @@
     return 0;
 }
 
+static int set_metadata_float(AVDictionary **dict, const char *key, float value, int allow_zero)
+{
+    if (value != 0 || allow_zero) {
+        char tmp[64];
+        snprintf(tmp, sizeof(tmp), "%f", value);
+        return av_dict_set(dict, key, tmp, 0);
+    }
+    return 0;
+}
+
 static int cine_read_header(AVFormatContext *avctx)
 {
     AVIOContext *pb = avctx->pb;
@@ -177,7 +188,10 @@
     set_metadata_int(&st->metadata, "contrast", avio_rl32(pb), 1);
     set_metadata_int(&st->metadata, "gamma", avio_rl32(pb), 1);
 
-    avio_skip(pb, 72); // Reserved1 .. WBView
+    avio_skip(pb, 12 + 16); // Reserved1 .. AutoExpRect
+    set_metadata_float(&st->metadata, "wbgain[0].r", av_int2float(avio_rl32(pb)), 1);
+    set_metadata_float(&st->metadata, "wbgain[0].b", av_int2float(avio_rl32(pb)), 1);
+    avio_skip(pb, 36); // WBGain[1].. WBView
 
     st->codec->bits_per_coded_sample = avio_rl32(pb);
 
diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c
index 2089883..a2584d7 100644
--- a/libavformat/concatdec.c
+++ b/libavformat/concatdec.c
@@ -23,6 +23,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
+#include "libavutil/timestamp.h"
 #include "avformat.h"
 #include "internal.h"
 #include "url.h"
@@ -479,6 +480,7 @@
     int ret;
     int64_t delta;
     ConcatStream *cs;
+    AVStream *st;
 
     while (1) {
         ret = av_read_frame(cat->avf, pkt);
@@ -504,6 +506,12 @@
     if ((ret = filter_packet(avf, cs, pkt)))
         return ret;
 
+    st = cat->avf->streams[pkt->stream_index];
+    av_log(avf, AV_LOG_DEBUG, "file:%d stream:%d pts:%s pts_time:%s dts:%s dts_time:%s",
+           (unsigned)(cat->cur_file - cat->files), pkt->stream_index,
+           av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
+           av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
+
     delta = av_rescale_q(cat->cur_file->start_time - cat->avf->start_time,
                          AV_TIME_BASE_Q,
                          cat->avf->streams[pkt->stream_index]->time_base);
@@ -511,6 +519,9 @@
         pkt->pts += delta;
     if (pkt->dts != AV_NOPTS_VALUE)
         pkt->dts += delta;
+    av_log(avf, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n",
+           av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base),
+           av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
     return ret;
 }
 
diff --git a/libavformat/crypto.c b/libavformat/crypto.c
index a9b6e47..c1754b0 100644
--- a/libavformat/crypto.c
+++ b/libavformat/crypto.c
@@ -41,14 +41,32 @@
     int keylen;
     uint8_t *iv;
     int ivlen;
-    struct AVAES *aes;
+    uint8_t *decrypt_key;
+    int decrypt_keylen;
+    uint8_t *decrypt_iv;
+    int decrypt_ivlen;
+    uint8_t *encrypt_key;
+    int encrypt_keylen;
+    uint8_t *encrypt_iv;
+    int encrypt_ivlen;
+    struct AVAES *aes_decrypt;
+    struct AVAES *aes_encrypt;
+
+    uint8_t pad[BLOCKSIZE];
+    int pad_len;
+
 } CryptoContext;
 
 #define OFFSET(x) offsetof(CryptoContext, x)
 #define D AV_OPT_FLAG_DECODING_PARAM
+#define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
-    {"key", "AES decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, .flags = D },
-    {"iv",  "AES decryption initialization vector", OFFSET(iv), AV_OPT_TYPE_BINARY, .flags = D },
+    {"key", "AES encryption/decryption key",                   OFFSET(key),         AV_OPT_TYPE_BINARY, .flags = D|E },
+    {"iv",  "AES encryption/decryption initialization vector", OFFSET(iv),          AV_OPT_TYPE_BINARY, .flags = D|E },
+    {"decryption_key", "AES decryption key",                   OFFSET(decrypt_key), AV_OPT_TYPE_BINARY, .flags = D },
+    {"decryption_iv",  "AES decryption initialization vector", OFFSET(decrypt_iv),  AV_OPT_TYPE_BINARY, .flags = D },
+    {"encryption_key", "AES encryption key",                   OFFSET(encrypt_key), AV_OPT_TYPE_BINARY, .flags = E },
+    {"encryption_iv",  "AES encryption initialization vector", OFFSET(encrypt_iv),  AV_OPT_TYPE_BINARY, .flags = E },
     { NULL }
 };
 
@@ -59,6 +77,33 @@
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
+static int set_aes_arg(CryptoContext *c, uint8_t **buf, int *buf_len,
+                       uint8_t *default_buf, int default_buf_len,
+                       const char *desc)
+{
+    if (!*buf_len) {
+        if (!default_buf_len) {
+            av_log(c, AV_LOG_ERROR, "%s not set\n", desc);
+            return AVERROR(EINVAL);
+        } else if (default_buf_len != BLOCKSIZE) {
+            av_log(c, AV_LOG_ERROR,
+                   "invalid %s size (%d bytes, block size is %d)\n",
+                   desc, default_buf_len, BLOCKSIZE);
+            return AVERROR(EINVAL);
+        }
+        *buf = av_memdup(default_buf, default_buf_len);
+        if (!*buf)
+            return AVERROR(ENOMEM);
+        *buf_len = default_buf_len;
+    } else if (*buf_len != BLOCKSIZE) {
+        av_log(c, AV_LOG_ERROR,
+               "invalid %s size (%d bytes, block size is %d)\n",
+               desc, *buf_len, BLOCKSIZE);
+        return AVERROR(EINVAL);
+    }
+    return 0;
+}
+
 static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary **options)
 {
     const char *nested_url;
@@ -72,28 +117,54 @@
         goto err;
     }
 
-    if (c->keylen < BLOCKSIZE || c->ivlen < BLOCKSIZE) {
-        av_log(h, AV_LOG_ERROR, "Key or IV not set\n");
-        ret = AVERROR(EINVAL);
-        goto err;
+    if (flags & AVIO_FLAG_READ) {
+        if ((ret = set_aes_arg(c, &c->decrypt_key, &c->decrypt_keylen,
+                               c->key, c->keylen, "decryption key")) < 0)
+            goto err;
+        if ((ret = set_aes_arg(c, &c->decrypt_iv, &c->decrypt_ivlen,
+                               c->key, c->keylen, "decryption IV")) < 0)
+            goto err;
     }
+
     if (flags & AVIO_FLAG_WRITE) {
-        av_log(h, AV_LOG_ERROR, "Only decryption is supported currently\n");
-        ret = AVERROR(ENOSYS);
-        goto err;
+        if ((ret = set_aes_arg(c, &c->encrypt_key, &c->encrypt_keylen,
+                               c->key, c->keylen, "encryption key")) < 0)
+        if (ret < 0)
+            goto err;
+        if ((ret = set_aes_arg(c, &c->encrypt_iv, &c->encrypt_ivlen,
+                               c->key, c->keylen, "encryption IV")) < 0)
+            goto err;
     }
-    if ((ret = ffurl_open(&c->hd, nested_url, AVIO_FLAG_READ,
+
+    if ((ret = ffurl_open(&c->hd, nested_url, flags,
                           &h->interrupt_callback, options)) < 0) {
-        av_log(h, AV_LOG_ERROR, "Unable to open input\n");
-        goto err;
-    }
-    c->aes = av_aes_alloc();
-    if (!c->aes) {
-        ret = AVERROR(ENOMEM);
+        av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url);
         goto err;
     }
 
-    av_aes_init(c->aes, c->key, 128, 1);
+    if (flags & AVIO_FLAG_READ) {
+        c->aes_decrypt = av_aes_alloc();
+        if (!c->aes_decrypt) {
+            ret = AVERROR(ENOMEM);
+            goto err;
+        }
+        ret = av_aes_init(c->aes_decrypt, c->decrypt_key, BLOCKSIZE*8, 1);
+        if (ret < 0)
+            goto err;
+    }
+
+    if (flags & AVIO_FLAG_WRITE) {
+        c->aes_encrypt = av_aes_alloc();
+        if (!c->aes_encrypt) {
+            ret = AVERROR(ENOMEM);
+            goto err;
+        }
+        ret = av_aes_init(c->aes_encrypt, c->encrypt_key, BLOCKSIZE*8, 0);
+        if (ret < 0)
+            goto err;
+    }
+
+    c->pad_len = 0;
 
     h->is_streamed = 1;
 
@@ -131,8 +202,8 @@
         return AVERROR_EOF;
     if (!c->eof)
         blocks--;
-    av_aes_crypt(c->aes, c->outbuffer, c->inbuffer + c->indata_used, blocks,
-                 c->iv, 1);
+    av_aes_crypt(c->aes_decrypt, c->outbuffer, c->inbuffer + c->indata_used,
+                 blocks, c->decrypt_iv, 1);
     c->outdata      = BLOCKSIZE * blocks;
     c->outptr       = c->outbuffer;
     c->indata_used += BLOCKSIZE * blocks;
@@ -150,12 +221,65 @@
     goto retry;
 }
 
+static int crypto_write(URLContext *h, const unsigned char *buf, int size)
+{
+    CryptoContext *c = h->priv_data;
+    int total_size, blocks, pad_len, out_size;
+    uint8_t *out_buf;
+    int ret = 0;
+
+    total_size = size + c->pad_len;
+    pad_len = total_size % BLOCKSIZE;
+    out_size = total_size - pad_len;
+    blocks = out_size / BLOCKSIZE;
+
+    if (out_size) {
+        out_buf = av_malloc(out_size);
+        if (!out_buf)
+            return AVERROR(ENOMEM);
+
+        if (c->pad_len) {
+            memcpy(&c->pad[c->pad_len], buf, BLOCKSIZE - c->pad_len);
+            av_aes_crypt(c->aes_encrypt, out_buf, c->pad, 1, c->encrypt_iv, 0);
+            blocks--;
+        }
+
+        av_aes_crypt(c->aes_encrypt, &out_buf[c->pad_len ? BLOCKSIZE : 0],
+                             &buf[c->pad_len ? BLOCKSIZE - c->pad_len: 0],
+                             blocks, c->encrypt_iv, 0);
+
+        ret = ffurl_write(c->hd, out_buf, out_size);
+        av_free(out_buf);
+        if (ret < 0)
+            return ret;
+
+        memcpy(c->pad, &buf[size - pad_len], pad_len);
+    } else
+        memcpy(&c->pad[c->pad_len], buf, size);
+
+    c->pad_len = pad_len;
+
+    return size;
+}
+
 static int crypto_close(URLContext *h)
 {
     CryptoContext *c = h->priv_data;
+    uint8_t out_buf[BLOCKSIZE];
+    int ret, pad;
+
+    if (c->aes_encrypt) {
+        pad = BLOCKSIZE - c->pad_len;
+        memset(&c->pad[c->pad_len], pad, pad);
+        av_aes_crypt(c->aes_encrypt, out_buf, c->pad, 1, c->encrypt_iv, 0);
+        if ((ret =  ffurl_write(c->hd, out_buf, BLOCKSIZE)) < 0)
+            return ret;
+    }
+
     if (c->hd)
         ffurl_close(c->hd);
-    av_freep(&c->aes);
+    av_freep(&c->aes_decrypt);
+    av_freep(&c->aes_encrypt);
     return 0;
 }
 
@@ -163,6 +287,7 @@
     .name            = "crypto",
     .url_open2       = crypto_open2,
     .url_read        = crypto_read,
+    .url_write       = crypto_write,
     .url_close       = crypto_close,
     .priv_data_size  = sizeof(CryptoContext),
     .priv_data_class = &crypto_class,
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
new file mode 100644
index 0000000..149e7d9
--- /dev/null
+++ b/libavformat/dashenc.c
@@ -0,0 +1,933 @@
+/*
+ * MPEG-DASH ISO BMFF segmenter
+ * Copyright (c) 2014 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "libavutil/avstring.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/opt.h"
+#include "libavutil/time_internal.h"
+
+#include "avc.h"
+#include "avformat.h"
+#include "avio_internal.h"
+#include "internal.h"
+#include "isom.h"
+#include "os_support.h"
+#include "url.h"
+
+// See ISO/IEC 23009-1:2014 5.3.9.4.4
+typedef enum {
+    DASH_TMPL_ID_UNDEFINED = -1,
+    DASH_TMPL_ID_ESCAPE,
+    DASH_TMPL_ID_REP_ID,
+    DASH_TMPL_ID_NUMBER,
+    DASH_TMPL_ID_BANDWIDTH,
+    DASH_TMPL_ID_TIME,
+} DASHTmplId;
+
+typedef struct Segment {
+    char file[1024];
+    int64_t start_pos;
+    int range_length, index_length;
+    int64_t time;
+    int duration;
+    int n;
+} Segment;
+
+typedef struct OutputStream {
+    AVFormatContext *ctx;
+    int ctx_inited;
+    uint8_t iobuf[32768];
+    URLContext *out;
+    int packets_written;
+    char initfile[1024];
+    int64_t init_start_pos;
+    int init_range_length;
+    int nb_segments, segments_size, segment_index;
+    Segment **segments;
+    int64_t first_dts, start_dts, end_dts;
+    int bit_rate;
+    char bandwidth_str[64];
+
+    char codec_str[100];
+} OutputStream;
+
+typedef struct DASHContext {
+    const AVClass *class;  /* Class for private options. */
+    int window_size;
+    int extra_window_size;
+    int min_seg_duration;
+    int remove_at_exit;
+    int use_template;
+    int use_timeline;
+    int single_file;
+    OutputStream *streams;
+    int has_video, has_audio;
+    int last_duration;
+    int total_duration;
+    char availability_start_time[100];
+    char dirname[1024];
+    const char *single_file_name;
+    const char *init_seg_name;
+    const char *media_seg_name;
+} DASHContext;
+
+static int dash_write(void *opaque, uint8_t *buf, int buf_size)
+{
+    OutputStream *os = opaque;
+    if (os->out)
+        ffurl_write(os->out, buf, buf_size);
+    return buf_size;
+}
+
+// RFC 6381
+static void set_codec_str(AVFormatContext *s, AVCodecContext *codec,
+                          char *str, int size)
+{
+    const AVCodecTag *tags[2] = { NULL, NULL };
+    uint32_t tag;
+    if (codec->codec_type == AVMEDIA_TYPE_VIDEO)
+        tags[0] = ff_codec_movvideo_tags;
+    else if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
+        tags[0] = ff_codec_movaudio_tags;
+    else
+        return;
+
+    tag = av_codec_get_tag(tags, codec->codec_id);
+    if (!tag)
+        return;
+    if (size < 5)
+        return;
+
+    AV_WL32(str, tag);
+    str[4] = '\0';
+    if (!strcmp(str, "mp4a") || !strcmp(str, "mp4v")) {
+        uint32_t oti;
+        tags[0] = ff_mp4_obj_type;
+        oti = av_codec_get_tag(tags, codec->codec_id);
+        if (oti)
+            av_strlcatf(str, size, ".%02x", oti);
+        else
+            return;
+
+        if (tag == MKTAG('m', 'p', '4', 'a')) {
+            if (codec->extradata_size >= 2) {
+                int aot = codec->extradata[0] >> 3;
+                if (aot == 31)
+                    aot = ((AV_RB16(codec->extradata) >> 5) & 0x3f) + 32;
+                av_strlcatf(str, size, ".%d", aot);
+            }
+        } else if (tag == MKTAG('m', 'p', '4', 'v')) {
+            // Unimplemented, should output ProfileLevelIndication as a decimal number
+            av_log(s, AV_LOG_WARNING, "Incomplete RFC 6381 codec string for mp4v\n");
+        }
+    } else if (!strcmp(str, "avc1")) {
+        uint8_t *tmpbuf = NULL;
+        uint8_t *extradata = codec->extradata;
+        int extradata_size = codec->extradata_size;
+        if (!extradata_size)
+            return;
+        if (extradata[0] != 1) {
+            AVIOContext *pb;
+            if (avio_open_dyn_buf(&pb) < 0)
+                return;
+            if (ff_isom_write_avcc(pb, extradata, extradata_size) < 0) {
+                avio_close_dyn_buf(pb, &tmpbuf);
+                av_free(tmpbuf);
+                return;
+            }
+            extradata_size = avio_close_dyn_buf(pb, &extradata);
+            tmpbuf = extradata;
+        }
+
+        if (extradata_size >= 4)
+            av_strlcatf(str, size, ".%02x%02x%02x",
+                        extradata[1], extradata[2], extradata[3]);
+        av_free(tmpbuf);
+    }
+}
+
+static void dash_free(AVFormatContext *s)
+{
+    DASHContext *c = s->priv_data;
+    int i, j;
+    if (!c->streams)
+        return;
+    for (i = 0; i < s->nb_streams; i++) {
+        OutputStream *os = &c->streams[i];
+        if (os->ctx && os->ctx_inited)
+            av_write_trailer(os->ctx);
+        if (os->ctx && os->ctx->pb)
+            av_free(os->ctx->pb);
+        ffurl_close(os->out);
+        os->out =  NULL;
+        if (os->ctx)
+            avformat_free_context(os->ctx);
+        for (j = 0; j < os->nb_segments; j++)
+            av_free(os->segments[j]);
+        av_free(os->segments);
+    }
+    av_freep(&c->streams);
+}
+
+static void output_segment_list(OutputStream *os, AVIOContext *out, DASHContext *c)
+{
+    int i, start_index = 0, start_number = 1;
+    if (c->window_size) {
+        start_index  = FFMAX(os->nb_segments   - c->window_size, 0);
+        start_number = FFMAX(os->segment_index - c->window_size, 1);
+    }
+
+    if (c->use_template) {
+        int timescale = c->use_timeline ? os->ctx->streams[0]->time_base.den : AV_TIME_BASE;
+        avio_printf(out, "\t\t\t\t<SegmentTemplate timescale=\"%d\" ", timescale);
+        if (!c->use_timeline)
+            avio_printf(out, "duration=\"%d\" ", c->last_duration);
+        avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\">\n", c->init_seg_name, c->media_seg_name, c->use_timeline ? start_number : 1);
+        if (c->use_timeline) {
+            avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
+            for (i = start_index; i < os->nb_segments; ) {
+                Segment *seg = os->segments[i];
+                int repeat = 0;
+                avio_printf(out, "\t\t\t\t\t\t<S ");
+                if (i == start_index)
+                    avio_printf(out, "t=\"%"PRId64"\" ", seg->time);
+                avio_printf(out, "d=\"%d\" ", seg->duration);
+                while (i + repeat + 1 < os->nb_segments && os->segments[i + repeat + 1]->duration == seg->duration)
+                    repeat++;
+                if (repeat > 0)
+                    avio_printf(out, "r=\"%d\" ", repeat);
+                avio_printf(out, "/>\n");
+                i += 1 + repeat;
+            }
+            avio_printf(out, "\t\t\t\t\t</SegmentTimeline>\n");
+        }
+        avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
+    } else if (c->single_file) {
+        avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
+        avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%d\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
+        avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1);
+        for (i = start_index; i < os->nb_segments; i++) {
+            Segment *seg = os->segments[i];
+            avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
+            if (seg->index_length)
+                avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
+            avio_printf(out, "/>\n");
+        }
+        avio_printf(out, "\t\t\t\t</SegmentList>\n");
+    } else {
+        avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%d\" startNumber=\"%d\">\n", AV_TIME_BASE, c->last_duration, start_number);
+        avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
+        for (i = start_index; i < os->nb_segments; i++) {
+            Segment *seg = os->segments[i];
+            avio_printf(out, "\t\t\t\t\t<SegmentURL media=\"%s\" />\n", seg->file);
+        }
+        avio_printf(out, "\t\t\t\t</SegmentList>\n");
+    }
+}
+
+static DASHTmplId dash_read_tmpl_id(const char *identifier, char *format_tag,
+                                    size_t format_tag_size, const char **ptr) {
+    const char *next_ptr;
+    DASHTmplId id_type = DASH_TMPL_ID_UNDEFINED;
+
+    if (av_strstart(identifier, "$$", &next_ptr)) {
+        id_type = DASH_TMPL_ID_ESCAPE;
+        *ptr = next_ptr;
+    } else if (av_strstart(identifier, "$RepresentationID$", &next_ptr)) {
+        id_type = DASH_TMPL_ID_REP_ID;
+        // default to basic format, as $RepresentationID$ identifiers
+        // are not allowed to have custom format-tags.
+        av_strlcpy(format_tag, "%d", format_tag_size);
+        *ptr = next_ptr;
+    } else { // the following identifiers may have an explicit format_tag
+        if (av_strstart(identifier, "$Number", &next_ptr))
+            id_type = DASH_TMPL_ID_NUMBER;
+        else if (av_strstart(identifier, "$Bandwidth", &next_ptr))
+            id_type = DASH_TMPL_ID_BANDWIDTH;
+        else if (av_strstart(identifier, "$Time", &next_ptr))
+            id_type = DASH_TMPL_ID_TIME;
+        else
+            id_type = DASH_TMPL_ID_UNDEFINED;
+
+        // next parse the dash format-tag and generate a c-string format tag
+        // (next_ptr now points at the first '%' at the beginning of the format-tag)
+        if (id_type != DASH_TMPL_ID_UNDEFINED) {
+            const char *number_format = DASH_TMPL_ID_TIME ? "lld" : "d";
+            if (next_ptr[0] == '$') { // no dash format-tag
+                snprintf(format_tag, format_tag_size, "%%%s", number_format);
+                *ptr = &next_ptr[1];
+            } else {
+                const char *width_ptr;
+                // only tolerate single-digit width-field (i.e. up to 9-digit width)
+                if (av_strstart(next_ptr, "%0", &width_ptr) &&
+                    av_isdigit(width_ptr[0]) &&
+                    av_strstart(&width_ptr[1], "d$", &next_ptr)) {
+                    // yes, we're using a format tag to build format_tag.
+                    snprintf(format_tag, format_tag_size, "%s%c%s", "%0", width_ptr[0], number_format);
+                    *ptr = next_ptr;
+                } else {
+                    av_log(NULL, AV_LOG_WARNING, "Failed to parse format-tag beginning with %s. Expected either a "
+                                                 "closing '$' character or a format-string like '%%0[width]d', "
+                                                 "where width must be a single digit\n", next_ptr);
+                    id_type = DASH_TMPL_ID_UNDEFINED;
+                }
+            }
+        }
+    }
+    return id_type;
+}
+
+static void dash_fill_tmpl_params(char *dst, size_t buffer_size,
+                                  const char *template, int rep_id,
+                                  int number, int bit_rate,
+                                  int64_t time) {
+    int dst_pos = 0;
+    const char *t_cur = template;
+    while (dst_pos < buffer_size - 1 && *t_cur) {
+        char format_tag[7]; // May be "%d", "%0Xd", or "%0Xlld" (for $Time$), where X is in [0-9]
+        int n = 0;
+        DASHTmplId id_type;
+        const char *t_next = strchr(t_cur, '$'); // copy over everything up to the first '$' character
+        if (t_next) {
+            int num_copy_bytes = FFMIN(t_next - t_cur, buffer_size - dst_pos - 1);
+            av_strlcpy(&dst[dst_pos], t_cur, num_copy_bytes + 1);
+            // advance
+            dst_pos += num_copy_bytes;
+            t_cur = t_next;
+        } else { // no more DASH identifiers to substitute - just copy the rest over and break
+            av_strlcpy(&dst[dst_pos], t_cur, buffer_size - dst_pos);
+            break;
+        }
+
+        if (dst_pos >= buffer_size - 1 || !*t_cur)
+            break;
+
+        // t_cur is now pointing to a '$' character
+        id_type = dash_read_tmpl_id(t_cur, format_tag, sizeof(format_tag), &t_next);
+        switch (id_type) {
+        case DASH_TMPL_ID_ESCAPE:
+            av_strlcpy(&dst[dst_pos], "$", 2);
+            n = 1;
+            break;
+        case DASH_TMPL_ID_REP_ID:
+            n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, rep_id);
+            break;
+        case DASH_TMPL_ID_NUMBER:
+            n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, number);
+            break;
+        case DASH_TMPL_ID_BANDWIDTH:
+            n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, bit_rate);
+            break;
+        case DASH_TMPL_ID_TIME:
+            n = snprintf(&dst[dst_pos], buffer_size - dst_pos, format_tag, time);
+            break;
+        case DASH_TMPL_ID_UNDEFINED:
+            // copy over one byte and advance
+            av_strlcpy(&dst[dst_pos], t_cur, 2);
+            n = 1;
+            t_next = &t_cur[1];
+            break;
+        }
+        // t_next points just past the processed identifier
+        // n is the number of bytes that were attempted to be written to dst
+        // (may have failed to write all because buffer_size).
+
+        // advance
+        dst_pos += FFMIN(n, buffer_size - dst_pos - 1);
+        t_cur = t_next;
+    }
+}
+
+static char *xmlescape(const char *str) {
+    int outlen = strlen(str)*3/2 + 6;
+    char *out = av_realloc(NULL, outlen + 1);
+    int pos = 0;
+    if (!out)
+        return NULL;
+    for (; *str; str++) {
+        if (pos + 6 > outlen) {
+            char *tmp;
+            outlen = 2 * outlen + 6;
+            tmp = av_realloc(out, outlen + 1);
+            if (!tmp) {
+                av_free(out);
+                return NULL;
+            }
+            out = tmp;
+        }
+        if (*str == '&') {
+            memcpy(&out[pos], "&amp;", 5);
+            pos += 5;
+        } else if (*str == '<') {
+            memcpy(&out[pos], "&lt;", 4);
+            pos += 4;
+        } else if (*str == '>') {
+            memcpy(&out[pos], "&gt;", 4);
+            pos += 4;
+        } else if (*str == '\'') {
+            memcpy(&out[pos], "&apos;", 6);
+            pos += 6;
+        } else if (*str == '\"') {
+            memcpy(&out[pos], "&quot;", 6);
+            pos += 6;
+        } else {
+            out[pos++] = *str;
+        }
+    }
+    out[pos] = '\0';
+    return out;
+}
+
+static void write_time(AVIOContext *out, int64_t time)
+{
+    int seconds = time / AV_TIME_BASE;
+    int fractions = time % AV_TIME_BASE;
+    int minutes = seconds / 60;
+    int hours = minutes / 60;
+    seconds %= 60;
+    minutes %= 60;
+    avio_printf(out, "PT");
+    if (hours)
+        avio_printf(out, "%dH", hours);
+    if (hours || minutes)
+        avio_printf(out, "%dM", minutes);
+    avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
+}
+
+static int write_manifest(AVFormatContext *s, int final)
+{
+    DASHContext *c = s->priv_data;
+    AVIOContext *out;
+    char temp_filename[1024];
+    int ret, i;
+    AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
+
+    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
+    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+    if (ret < 0) {
+        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
+        return ret;
+    }
+    avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+    avio_printf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
+                "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
+                "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
+                "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
+                "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
+                "\ttype=\"%s\"\n", final ? "static" : "dynamic");
+    if (final) {
+        avio_printf(out, "\tmediaPresentationDuration=\"");
+        write_time(out, c->total_duration);
+        avio_printf(out, "\"\n");
+    } else {
+        int update_period = c->last_duration / AV_TIME_BASE;
+        if (c->use_template && !c->use_timeline)
+            update_period = 500;
+        avio_printf(out, "\tminimumUpdatePeriod=\"PT%dS\"\n", update_period);
+        avio_printf(out, "\tsuggestedPresentationDelay=\"PT%dS\"\n", c->last_duration / AV_TIME_BASE);
+        if (!c->availability_start_time[0] && s->nb_streams > 0 && c->streams[0].nb_segments > 0) {
+            time_t t = time(NULL);
+            struct tm *ptm, tmbuf;
+            ptm = gmtime_r(&t, &tmbuf);
+            if (ptm) {
+                if (!strftime(c->availability_start_time, sizeof(c->availability_start_time),
+                              "%Y-%m-%dT%H:%M:%S", ptm))
+                    c->availability_start_time[0] = '\0';
+            }
+        }
+        if (c->availability_start_time[0])
+            avio_printf(out, "\tavailabilityStartTime=\"%s\"\n", c->availability_start_time);
+        if (c->window_size && c->use_template) {
+            avio_printf(out, "\ttimeShiftBufferDepth=\"");
+            write_time(out, c->last_duration * c->window_size);
+            avio_printf(out, "\"\n");
+        }
+    }
+    avio_printf(out, "\tminBufferTime=\"");
+    write_time(out, c->last_duration);
+    avio_printf(out, "\">\n");
+    avio_printf(out, "\t<ProgramInformation>\n");
+    if (title) {
+        char *escaped = xmlescape(title->value);
+        avio_printf(out, "\t\t<Title>%s</Title>\n", escaped);
+        av_free(escaped);
+    }
+    avio_printf(out, "\t</ProgramInformation>\n");
+    if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
+        OutputStream *os = &c->streams[0];
+        int start_index = FFMAX(os->nb_segments - c->window_size, 0);
+        int64_t start_time = av_rescale_q(os->segments[start_index]->time, s->streams[0]->time_base, AV_TIME_BASE_Q);
+        avio_printf(out, "\t<Period start=\"");
+        write_time(out, start_time);
+        avio_printf(out, "\">\n");
+    } else {
+        avio_printf(out, "\t<Period start=\"PT0.0S\">\n");
+    }
+
+    if (c->has_video) {
+        avio_printf(out, "\t\t<AdaptationSet id=\"video\" segmentAlignment=\"true\" bitstreamSwitching=\"true\">\n");
+        for (i = 0; i < s->nb_streams; i++) {
+            AVStream *st = s->streams[i];
+            OutputStream *os = &c->streams[i];
+            if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_VIDEO)
+                continue;
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codec->width, st->codec->height);
+            output_segment_list(&c->streams[i], out, c);
+            avio_printf(out, "\t\t\t</Representation>\n");
+        }
+        avio_printf(out, "\t\t</AdaptationSet>\n");
+    }
+    if (c->has_audio) {
+        avio_printf(out, "\t\t<AdaptationSet id=\"audio\" segmentAlignment=\"true\" bitstreamSwitching=\"true\">\n");
+        for (i = 0; i < s->nb_streams; i++) {
+            AVStream *st = s->streams[i];
+            OutputStream *os = &c->streams[i];
+            if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+                continue;
+            avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/mp4\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codec->sample_rate);
+            avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n", st->codec->channels);
+            output_segment_list(&c->streams[i], out, c);
+            avio_printf(out, "\t\t\t</Representation>\n");
+        }
+        avio_printf(out, "\t\t</AdaptationSet>\n");
+    }
+    avio_printf(out, "\t</Period>\n");
+    avio_printf(out, "</MPD>\n");
+    avio_flush(out);
+    avio_close(out);
+    return ff_rename(temp_filename, s->filename, s);
+}
+
+static int dash_write_header(AVFormatContext *s)
+{
+    DASHContext *c = s->priv_data;
+    int ret = 0, i;
+    AVOutputFormat *oformat;
+    char *ptr;
+    char basename[1024];
+
+    if (c->single_file_name)
+        c->single_file = 1;
+    if (c->single_file)
+        c->use_template = 0;
+
+    av_strlcpy(c->dirname, s->filename, sizeof(c->dirname));
+    ptr = strrchr(c->dirname, '/');
+    if (ptr) {
+        av_strlcpy(basename, &ptr[1], sizeof(basename));
+        ptr[1] = '\0';
+    } else {
+        c->dirname[0] = '\0';
+        av_strlcpy(basename, s->filename, sizeof(basename));
+    }
+
+    ptr = strrchr(basename, '.');
+    if (ptr)
+        *ptr = '\0';
+
+    oformat = av_guess_format("mp4", NULL, NULL);
+    if (!oformat) {
+        ret = AVERROR_MUXER_NOT_FOUND;
+        goto fail;
+    }
+
+    c->streams = av_mallocz(sizeof(*c->streams) * s->nb_streams);
+    if (!c->streams) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    for (i = 0; i < s->nb_streams; i++) {
+        OutputStream *os = &c->streams[i];
+        AVFormatContext *ctx;
+        AVStream *st;
+        AVDictionary *opts = NULL;
+        char filename[1024];
+
+        os->bit_rate = s->streams[i]->codec->bit_rate ?
+                       s->streams[i]->codec->bit_rate :
+                       s->streams[i]->codec->rc_max_rate;
+        if (os->bit_rate) {
+            snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),
+                     " bandwidth=\"%d\"", os->bit_rate);
+        } else {
+            int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ?
+                        AV_LOG_ERROR : AV_LOG_WARNING;
+            av_log(s, level, "No bit rate set for stream %d\n", i);
+            if (s->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+        }
+
+        ctx = avformat_alloc_context();
+        if (!ctx) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        os->ctx = ctx;
+        ctx->oformat = oformat;
+        ctx->interrupt_callback = s->interrupt_callback;
+
+        if (!(st = avformat_new_stream(ctx, NULL))) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+        avcodec_copy_context(st->codec, s->streams[i]->codec);
+        st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
+        st->time_base = s->streams[i]->time_base;
+        ctx->avoid_negative_ts = s->avoid_negative_ts;
+
+        ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, dash_write, NULL);
+        if (!ctx->pb) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        if (c->single_file) {
+            if (c->single_file_name)
+                dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->single_file_name, i, 0, os->bit_rate, 0);
+            else
+                snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.m4s", basename, i);
+        } else {
+            dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), c->init_seg_name, i, 0, os->bit_rate, 0);
+        }
+        snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
+        ret = ffurl_open(&os->out, filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+        if (ret < 0)
+            goto fail;
+        os->init_start_pos = 0;
+
+        av_dict_set(&opts, "movflags", "frag_custom+dash", 0);
+        if ((ret = avformat_write_header(ctx, &opts)) < 0) {
+             goto fail;
+        }
+        os->ctx_inited = 1;
+        avio_flush(ctx->pb);
+        av_dict_free(&opts);
+
+        if (c->single_file) {
+            os->init_range_length = avio_tell(ctx->pb);
+        } else {
+            ffurl_close(os->out);
+            os->out = NULL;
+        }
+
+        s->streams[i]->time_base = st->time_base;
+        // If the muxer wants to shift timestamps, request to have them shifted
+        // already before being handed to this muxer, so we don't have mismatches
+        // between the MPD and the actual segments.
+        s->avoid_negative_ts = ctx->avoid_negative_ts;
+        if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
+            c->has_video = 1;
+        else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
+            c->has_audio = 1;
+
+        set_codec_str(s, os->ctx->streams[0]->codec, os->codec_str, sizeof(os->codec_str));
+        os->first_dts = AV_NOPTS_VALUE;
+        os->segment_index = 1;
+    }
+
+    if (!c->has_video && c->min_seg_duration <= 0) {
+        av_log(s, AV_LOG_WARNING, "no video stream and no min seg duration set\n");
+        ret = AVERROR(EINVAL);
+    }
+    ret = write_manifest(s, 0);
+
+fail:
+    if (ret)
+        dash_free(s);
+    return ret;
+}
+
+static int add_segment(OutputStream *os, const char *file,
+                       int64_t time, int duration,
+                       int64_t start_pos, int64_t range_length,
+                       int64_t index_length)
+{
+    int err;
+    Segment *seg;
+    if (os->nb_segments >= os->segments_size) {
+        os->segments_size = (os->segments_size + 1) * 2;
+        if ((err = av_reallocp(&os->segments, sizeof(*os->segments) *
+                               os->segments_size)) < 0) {
+            os->segments_size = 0;
+            os->nb_segments = 0;
+            return err;
+        }
+    }
+    seg = av_mallocz(sizeof(*seg));
+    if (!seg)
+        return AVERROR(ENOMEM);
+    av_strlcpy(seg->file, file, sizeof(seg->file));
+    seg->time = time;
+    seg->duration = duration;
+    seg->start_pos = start_pos;
+    seg->range_length = range_length;
+    seg->index_length = index_length;
+    os->segments[os->nb_segments++] = seg;
+    os->segment_index++;
+    return 0;
+}
+
+static void write_styp(AVIOContext *pb)
+{
+    avio_wb32(pb, 24);
+    ffio_wfourcc(pb, "styp");
+    ffio_wfourcc(pb, "msdh");
+    avio_wb32(pb, 0); /* minor */
+    ffio_wfourcc(pb, "msdh");
+    ffio_wfourcc(pb, "msix");
+}
+
+static void find_index_range(AVFormatContext *s, const char *dirname,
+                             const char *filename, int64_t pos,
+                             int *index_length)
+{
+    char full_path[1024];
+    uint8_t buf[8];
+    URLContext *fd;
+    int ret;
+
+    snprintf(full_path, sizeof(full_path), "%s%s", dirname, filename);
+    ret = ffurl_open(&fd, full_path, AVIO_FLAG_READ, &s->interrupt_callback, NULL);
+    if (ret < 0)
+        return;
+    if (ffurl_seek(fd, pos, SEEK_SET) != pos) {
+        ffurl_close(fd);
+        return;
+    }
+    ret = ffurl_read(fd, buf, 8);
+    ffurl_close(fd);
+    if (ret < 8)
+        return;
+    if (AV_RL32(&buf[4]) != MKTAG('s', 'i', 'd', 'x'))
+        return;
+    *index_length = AV_RB32(&buf[0]);
+}
+
+static int dash_flush(AVFormatContext *s, int final, int stream)
+{
+    DASHContext *c = s->priv_data;
+    int i, ret = 0;
+    int cur_flush_segment_index = 0;
+    if (stream >= 0)
+        cur_flush_segment_index = c->streams[stream].segment_index;
+
+    for (i = 0; i < s->nb_streams; i++) {
+        OutputStream *os = &c->streams[i];
+        char filename[1024] = "", full_path[1024], temp_path[1024];
+        int64_t start_pos = avio_tell(os->ctx->pb);
+        int range_length, index_length = 0;
+
+        if (!os->packets_written)
+            continue;
+
+        // Flush the single stream that got a keyframe right now.
+        // Flush all audio streams as well, in sync with video keyframes,
+        // but not the other video streams.
+        if (stream >= 0 && i != stream) {
+            if (s->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO)
+                continue;
+            // Make sure we don't flush audio streams multiple times, when
+            // all video streams are flushed one at a time.
+            if (c->has_video && os->segment_index > cur_flush_segment_index)
+                continue;
+        }
+
+        if (!c->single_file) {
+            dash_fill_tmpl_params(filename, sizeof(filename), c->media_seg_name, i, os->segment_index, os->bit_rate, os->start_dts);
+            snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
+            snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
+            ret = ffurl_open(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+            if (ret < 0)
+                break;
+            write_styp(os->ctx->pb);
+        }
+        av_write_frame(os->ctx, NULL);
+        avio_flush(os->ctx->pb);
+        os->packets_written = 0;
+
+        range_length = avio_tell(os->ctx->pb) - start_pos;
+        if (c->single_file) {
+            find_index_range(s, c->dirname, os->initfile, start_pos, &index_length);
+        } else {
+            ffurl_close(os->out);
+            os->out = NULL;
+            ret = ff_rename(temp_path, full_path, s);
+            if (ret < 0)
+                break;
+        }
+        add_segment(os, filename, os->start_dts, os->end_dts - os->start_dts, start_pos, range_length, index_length);
+    }
+
+    if (c->window_size || (final && c->remove_at_exit)) {
+        for (i = 0; i < s->nb_streams; i++) {
+            OutputStream *os = &c->streams[i];
+            int j;
+            int remove = os->nb_segments - c->window_size - c->extra_window_size;
+            if (final && c->remove_at_exit)
+                remove = os->nb_segments;
+            if (remove > 0) {
+                for (j = 0; j < remove; j++) {
+                    char filename[1024];
+                    snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->segments[j]->file);
+                    unlink(filename);
+                    av_free(os->segments[j]);
+                }
+                os->nb_segments -= remove;
+                memmove(os->segments, os->segments + remove, os->nb_segments * sizeof(*os->segments));
+            }
+        }
+    }
+
+    if (ret >= 0)
+        ret = write_manifest(s, final);
+    return ret;
+}
+
+static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    DASHContext *c = s->priv_data;
+    AVStream *st = s->streams[pkt->stream_index];
+    OutputStream *os = &c->streams[pkt->stream_index];
+    int64_t seg_end_duration = (os->segment_index) * (int64_t) c->min_seg_duration;
+    int ret;
+
+    // If forcing the stream to start at 0, the mp4 muxer will set the start
+    // timestamps to 0. Do the same here, to avoid mismatches in duration/timestamps.
+    if (os->first_dts == AV_NOPTS_VALUE &&
+        s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
+        pkt->pts -= pkt->dts;
+        pkt->dts  = 0;
+    }
+
+    if (os->first_dts == AV_NOPTS_VALUE)
+        os->first_dts = pkt->dts;
+
+    if ((!c->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
+        pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
+        av_compare_ts(pkt->dts - os->first_dts, st->time_base,
+                      seg_end_duration, AV_TIME_BASE_Q) >= 0) {
+        int64_t prev_duration = c->last_duration;
+
+        c->last_duration = av_rescale_q(pkt->dts - os->start_dts,
+                                        st->time_base,
+                                        AV_TIME_BASE_Q);
+        c->total_duration = av_rescale_q(pkt->dts - os->first_dts,
+                                         st->time_base,
+                                         AV_TIME_BASE_Q);
+
+        if ((!c->use_timeline || !c->use_template) && prev_duration) {
+            if (c->last_duration < prev_duration*9/10 ||
+                c->last_duration > prev_duration*11/10) {
+                av_log(s, AV_LOG_WARNING,
+                       "Segment durations differ too much, enable use_timeline "
+                       "and use_template, or keep a stricter keyframe interval\n");
+            }
+        }
+
+        if ((ret = dash_flush(s, 0, pkt->stream_index)) < 0)
+            return ret;
+    }
+
+    if (!os->packets_written)
+        os->start_dts = pkt->dts;
+    os->end_dts = pkt->dts + pkt->duration;
+    os->packets_written++;
+    return ff_write_chained(os->ctx, 0, pkt, s, 0);
+}
+
+static int dash_write_trailer(AVFormatContext *s)
+{
+    DASHContext *c = s->priv_data;
+
+    if (s->nb_streams > 0) {
+        OutputStream *os = &c->streams[0];
+        // If no segments have been written so far, try to do a crude
+        // guess of the segment duration
+        if (!c->last_duration)
+            c->last_duration = av_rescale_q(os->end_dts - os->start_dts,
+                                            s->streams[0]->time_base,
+                                            AV_TIME_BASE_Q);
+        c->total_duration = av_rescale_q(os->end_dts - os->first_dts,
+                                         s->streams[0]->time_base,
+                                         AV_TIME_BASE_Q);
+    }
+    dash_flush(s, 1, -1);
+
+    if (c->remove_at_exit) {
+        char filename[1024];
+        int i;
+        for (i = 0; i < s->nb_streams; i++) {
+            OutputStream *os = &c->streams[i];
+            snprintf(filename, sizeof(filename), "%s%s", c->dirname, os->initfile);
+            unlink(filename);
+        }
+        unlink(s->filename);
+    }
+
+    dash_free(s);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(DASHContext, x)
+#define E AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
+    { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
+    { "min_seg_duration", "minimum segment duration (in microseconds)", OFFSET(min_seg_duration), AV_OPT_TYPE_INT64, { .i64 = 5000000 }, 0, INT_MAX, E },
+    { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E },
+    { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E },
+    { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, E },
+    { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E },
+    { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
+    { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.m4s"},  0, 0, E },
+    { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.m4s"},  0, 0, E },
+    { NULL },
+};
+
+static const AVClass dash_class = {
+    .class_name = "dash muxer",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+AVOutputFormat ff_dash_muxer = {
+    .name           = "dash",
+    .long_name      = NULL_IF_CONFIG_SMALL("DASH Muxer"),
+    .priv_data_size = sizeof(DASHContext),
+    .audio_codec    = AV_CODEC_ID_AAC,
+    .video_codec    = AV_CODEC_ID_H264,
+    .flags          = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
+    .write_header   = dash_write_header,
+    .write_packet   = dash_write_packet,
+    .write_trailer  = dash_write_trailer,
+    .codec_tag      = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
+    .priv_class     = &dash_class,
+};
diff --git a/libavformat/dtsdec.c b/libavformat/dtsdec.c
index f6a939a..d054f43 100644
--- a/libavformat/dtsdec.c
+++ b/libavformat/dtsdec.c
@@ -34,7 +34,7 @@
 {
     const uint8_t *buf, *bufp;
     uint32_t state = -1;
-    int markers[4] = {0};
+    int markers[4*16] = {0};
     int sum, max, i;
     int64_t diff = 0;
     uint8_t hdr[12 + FF_INPUT_BUFFER_PADDING_SIZE] = { 0 };
@@ -43,6 +43,7 @@
 
     for(; buf < (p->buf+p->buf_size)-2; buf+=2) {
         int marker, sample_blocks, sample_rate, sr_code, framesize;
+        int lfe;
         GetBitContext gb;
 
         bufp = buf;
@@ -89,13 +90,27 @@
         if (sample_rate == 0)
             continue;
 
+        get_bits(&gb, 5);
+        if (get_bits(&gb, 1))
+            continue;
+
+        skip_bits_long(&gb, 9);
+        lfe = get_bits(&gb, 2);
+        if (lfe > 2)
+            continue;
+
+        marker += 4* sr_code;
+
         markers[marker] ++;
     }
-    sum = markers[0] + markers[1] + markers[2] + markers[3];
-    max = 0;
-    for (i=1; i<4; i++)
+
+    sum = max = 0;
+    for (i=0; i<FF_ARRAY_ELEMS(markers); i++) {
+        sum += markers[i];
         if (markers[max] < markers[i])
             max = i;
+    }
+
     if (markers[max] > 3 && p->buf_size / markers[max] < 32*1024 &&
         markers[max] * 4 > sum * 3 &&
         diff / p->buf_size > 200)
diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c
index 448762b..987f419 100644
--- a/libavformat/ffmdec.c
+++ b/libavformat/ffmdec.c
@@ -23,6 +23,9 @@
 
 #include "libavutil/intreadwrite.h"
 #include "libavutil/intfloat.h"
+#include "libavutil/opt.h"
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -230,6 +233,27 @@
     return 0;
 }
 
+static int ffm_append_recommended_configuration(AVStream *st, char **conf)
+{
+    int ret;
+    size_t newsize;
+    av_assert0(conf && st);
+    if (!*conf)
+        return 0;
+    if (!st->recommended_encoder_configuration) {
+        st->recommended_encoder_configuration = *conf;
+        *conf = 0;
+        return 0;
+    }
+    newsize = strlen(*conf) + strlen(st->recommended_encoder_configuration) + 2;
+    if ((ret = av_reallocp(&st->recommended_encoder_configuration, newsize)) < 0)
+        return ret;
+    av_strlcat(st->recommended_encoder_configuration, ",", newsize);
+    av_strlcat(st->recommended_encoder_configuration, *conf, newsize);
+    av_freep(conf);
+    return 0;
+}
+
 static int ffm2_read_header(AVFormatContext *s)
 {
     FFMContext *ffm = s->priv_data;
@@ -237,6 +261,9 @@
     AVIOContext *pb = s->pb;
     AVCodecContext *codec;
     int ret;
+    int f_main = 0, f_cprv, f_stvi, f_stau;
+    AVCodec *enc;
+    char *buffer;
 
     ffm->packet_size = avio_rb32(pb);
     if (ffm->packet_size != FFM_PACKET_SIZE) {
@@ -267,10 +294,15 @@
 
         switch(id) {
         case MKBETAG('M', 'A', 'I', 'N'):
+            if (f_main++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
             avio_rb32(pb); /* nb_streams */
             avio_rb32(pb); /* total bitrate */
             break;
         case MKBETAG('C', 'O', 'M', 'M'):
+            f_cprv = f_stvi = f_stau = 0;
             st = avformat_new_stream(s, NULL);
             if (!st) {
                 ret = AVERROR(ENOMEM);
@@ -291,63 +323,111 @@
                 if (ff_get_extradata(codec, pb, avio_rb32(pb)) < 0)
                     return AVERROR(ENOMEM);
             }
-            avio_seek(pb, next, SEEK_SET);
-            id = avio_rb32(pb);
-            size = avio_rb32(pb);
-            next = avio_tell(pb) + size;
-            switch(id) {
-            case MKBETAG('S', 'T', 'V', 'I'):
-                codec->time_base.num = avio_rb32(pb);
-                codec->time_base.den = avio_rb32(pb);
-                codec->width = avio_rb16(pb);
-                codec->height = avio_rb16(pb);
-                codec->gop_size = avio_rb16(pb);
-                codec->pix_fmt = avio_rb32(pb);
-                codec->qmin = avio_r8(pb);
-                codec->qmax = avio_r8(pb);
-                codec->max_qdiff = avio_r8(pb);
-                codec->qcompress = avio_rb16(pb) / 10000.0;
-                codec->qblur = avio_rb16(pb) / 10000.0;
-                codec->bit_rate_tolerance = avio_rb32(pb);
-                avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
-                codec->rc_eq = av_strdup(rc_eq_buf);
-                codec->rc_max_rate = avio_rb32(pb);
-                codec->rc_min_rate = avio_rb32(pb);
-                codec->rc_buffer_size = avio_rb32(pb);
-                codec->i_quant_factor = av_int2double(avio_rb64(pb));
-                codec->b_quant_factor = av_int2double(avio_rb64(pb));
-                codec->i_quant_offset = av_int2double(avio_rb64(pb));
-                codec->b_quant_offset = av_int2double(avio_rb64(pb));
-                codec->dct_algo = avio_rb32(pb);
-                codec->strict_std_compliance = avio_rb32(pb);
-                codec->max_b_frames = avio_rb32(pb);
-                codec->mpeg_quant = avio_rb32(pb);
-                codec->intra_dc_precision = avio_rb32(pb);
-                codec->me_method = avio_rb32(pb);
-                codec->mb_decision = avio_rb32(pb);
-                codec->nsse_weight = avio_rb32(pb);
-                codec->frame_skip_cmp = avio_rb32(pb);
-                codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
-                codec->codec_tag = avio_rb32(pb);
-                codec->thread_count = avio_r8(pb);
-                codec->coder_type = avio_rb32(pb);
-                codec->me_cmp = avio_rb32(pb);
-                codec->me_subpel_quality = avio_rb32(pb);
-                codec->me_range = avio_rb32(pb);
-                codec->keyint_min = avio_rb32(pb);
-                codec->scenechange_threshold = avio_rb32(pb);
-                codec->b_frame_strategy = avio_rb32(pb);
-                codec->qcompress = av_int2double(avio_rb64(pb));
-                codec->qblur = av_int2double(avio_rb64(pb));
-                codec->max_qdiff = avio_rb32(pb);
-                codec->refs = avio_rb32(pb);
-                break;
-            case MKBETAG('S', 'T', 'A', 'U'):
-                codec->sample_rate = avio_rb32(pb);
-                codec->channels = avio_rl16(pb);
-                codec->frame_size = avio_rl16(pb);
-                break;
+            break;
+        case MKBETAG('S', 'T', 'V', 'I'):
+            if (f_stvi++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
             }
+            codec->time_base.num = avio_rb32(pb);
+            codec->time_base.den = avio_rb32(pb);
+            codec->width = avio_rb16(pb);
+            codec->height = avio_rb16(pb);
+            codec->gop_size = avio_rb16(pb);
+            codec->pix_fmt = avio_rb32(pb);
+            codec->qmin = avio_r8(pb);
+            codec->qmax = avio_r8(pb);
+            codec->max_qdiff = avio_r8(pb);
+            codec->qcompress = avio_rb16(pb) / 10000.0;
+            codec->qblur = avio_rb16(pb) / 10000.0;
+            codec->bit_rate_tolerance = avio_rb32(pb);
+            avio_get_str(pb, INT_MAX, rc_eq_buf, sizeof(rc_eq_buf));
+            codec->rc_eq = av_strdup(rc_eq_buf);
+            codec->rc_max_rate = avio_rb32(pb);
+            codec->rc_min_rate = avio_rb32(pb);
+            codec->rc_buffer_size = avio_rb32(pb);
+            codec->i_quant_factor = av_int2double(avio_rb64(pb));
+            codec->b_quant_factor = av_int2double(avio_rb64(pb));
+            codec->i_quant_offset = av_int2double(avio_rb64(pb));
+            codec->b_quant_offset = av_int2double(avio_rb64(pb));
+            codec->dct_algo = avio_rb32(pb);
+            codec->strict_std_compliance = avio_rb32(pb);
+            codec->max_b_frames = avio_rb32(pb);
+            codec->mpeg_quant = avio_rb32(pb);
+            codec->intra_dc_precision = avio_rb32(pb);
+            codec->me_method = avio_rb32(pb);
+            codec->mb_decision = avio_rb32(pb);
+            codec->nsse_weight = avio_rb32(pb);
+            codec->frame_skip_cmp = avio_rb32(pb);
+            codec->rc_buffer_aggressivity = av_int2double(avio_rb64(pb));
+            codec->codec_tag = avio_rb32(pb);
+            codec->thread_count = avio_r8(pb);
+            codec->coder_type = avio_rb32(pb);
+            codec->me_cmp = avio_rb32(pb);
+            codec->me_subpel_quality = avio_rb32(pb);
+            codec->me_range = avio_rb32(pb);
+            codec->keyint_min = avio_rb32(pb);
+            codec->scenechange_threshold = avio_rb32(pb);
+            codec->b_frame_strategy = avio_rb32(pb);
+            codec->qcompress = av_int2double(avio_rb64(pb));
+            codec->qblur = av_int2double(avio_rb64(pb));
+            codec->max_qdiff = avio_rb32(pb);
+            codec->refs = avio_rb32(pb);
+            break;
+        case MKBETAG('S', 'T', 'A', 'U'):
+            if (f_stau++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            codec->sample_rate = avio_rb32(pb);
+            codec->channels = avio_rl16(pb);
+            codec->frame_size = avio_rl16(pb);
+            break;
+        case MKBETAG('C', 'P', 'R', 'V'):
+            if (f_cprv++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            enc = avcodec_find_encoder(codec->codec_id);
+            if (enc && enc->priv_data_size && enc->priv_class) {
+                buffer = av_malloc(size + 1);
+                if (!buffer) {
+                    ret = AVERROR(ENOMEM);
+                    goto fail;
+                }
+                avio_get_str(pb, size, buffer, size + 1);
+                if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0)
+                    goto fail;
+            }
+            break;
+        case MKBETAG('S', '2', 'V', 'I'):
+            if (f_stvi++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            buffer = av_malloc(size);
+            if (!buffer) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            avio_get_str(pb, INT_MAX, buffer, size);
+            av_set_options_string(codec, buffer, "=", ",");
+            if ((ret = ffm_append_recommended_configuration(st, &buffer)) < 0)
+                goto fail;
+            break;
+        case MKBETAG('S', '2', 'A', 'U'):
+            if (f_stau++) {
+                ret = AVERROR(EINVAL);
+                goto fail;
+            }
+            buffer = av_malloc(size);
+            if (!buffer) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            avio_get_str(pb, INT_MAX, buffer, size);
+            av_set_options_string(codec, buffer, "=", ",");
+            ffm_append_recommended_configuration(st, &buffer);
             break;
         }
         avio_seek(pb, next, SEEK_SET);
diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c
index eb809eb..e6d1a31 100644
--- a/libavformat/ffmenc.c
+++ b/libavformat/ffmenc.c
@@ -23,6 +23,7 @@
 #include "libavutil/intfloat.h"
 #include "libavutil/avassert.h"
 #include "libavutil/parseutils.h"
+#include "libavutil/opt.h"
 #include "avformat.h"
 #include "internal.h"
 #include "ffm.h"
@@ -93,6 +94,128 @@
     av_free(dyn_buf);
 }
 
+static int ffm_write_header_codec_private_ctx(AVIOContext *pb, AVCodecContext *ctx, int type)
+{
+    AVIOContext *tmp;
+    char *buf = NULL;
+    int ret;
+    const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id);
+
+    if (!enc)
+        return AVERROR(EINVAL);
+    if (ctx->priv_data && enc->priv_class && enc->priv_data_size) {
+        if ((ret = av_opt_serialize(ctx->priv_data, AV_OPT_FLAG_ENCODING_PARAM | type,
+                                    AV_OPT_SERIALIZE_SKIP_DEFAULTS, &buf, '=', ',')) < 0)
+            return ret;
+        if (buf && strlen(buf)) {
+            if (avio_open_dyn_buf(&tmp) < 0) {
+                av_free(buf);
+                return AVERROR(ENOMEM);
+            }
+            avio_put_str(tmp, buf);
+            write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V'));
+        }
+        av_free(buf);
+    }
+    return 0;
+}
+
+static int ffm_write_header_codec_ctx(AVIOContext *pb, AVCodecContext *ctx, unsigned tag, int type)
+{
+    AVIOContext *tmp;
+    char *buf = NULL;
+    uint8_t *p = NULL;
+    int ret, need_coma = 0;
+
+#define SKIP_DEFAULTS   AV_OPT_SERIALIZE_SKIP_DEFAULTS
+#define OPT_FLAGS_EXACT AV_OPT_SERIALIZE_OPT_FLAGS_EXACT
+#define ENC             AV_OPT_FLAG_ENCODING_PARAM
+
+    if (avio_open_dyn_buf(&tmp) < 0)
+        return AVERROR(ENOMEM);
+    if ((ret = av_opt_serialize(ctx, ENC | type, SKIP_DEFAULTS, &buf, '=', ',')) < 0)
+        goto fail;
+    if (buf && strlen(buf)) {
+        avio_write(tmp, buf, strlen(buf));
+        av_free(buf);
+        need_coma = 1;
+    }
+    if ((ret = av_opt_serialize(ctx, 0, SKIP_DEFAULTS | OPT_FLAGS_EXACT, &buf, '=', ',')) < 0)
+        goto fail;
+    if (buf && strlen(buf)) {
+        if (need_coma)
+            avio_w8(tmp, ',');
+        avio_write(tmp, buf, strlen(buf));
+        av_free(buf);
+    }
+    avio_w8(tmp, 0);
+    write_header_chunk(pb, tmp, tag);
+    return 0;
+  fail:
+    av_free(buf);
+    avio_close_dyn_buf(tmp, &p);
+    av_free(p);
+    return ret;
+
+#undef SKIP_DEFAULTS
+#undef OPT_FLAGS_EXACT
+#undef ENC
+}
+
+static int ffm_write_recommended_config(AVIOContext *pb, AVCodecContext *ctx, unsigned tag,
+                                        const char *configuration)
+{
+    int ret;
+    const AVCodec *enc = ctx->codec ? ctx->codec : avcodec_find_encoder(ctx->codec_id);
+    AVIOContext *tmp;
+    AVDictionaryEntry *t = NULL;
+    AVDictionary *all = NULL, *comm = NULL, *prv = NULL;
+    char *buf = NULL;
+
+    if (!enc || !enc->priv_class || !enc->priv_data_size) {
+        /* codec is not known/has no private options, so save everything as common options */
+        if (avio_open_dyn_buf(&tmp) < 0)
+            return AVERROR(ENOMEM);
+        avio_put_str(tmp, configuration);
+        write_header_chunk(pb, tmp, tag);
+        return 0;
+    }
+
+    if ((ret = av_dict_parse_string(&all, configuration, "=", ",", 0)) < 0)
+        return ret;
+
+    while ((t = av_dict_get(all, "", t, AV_DICT_IGNORE_SUFFIX))) {
+        if (av_opt_find((void *)&enc->priv_class, t->key, NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)) {
+            if ((ret = av_dict_set(&prv, t->key, t->value, 0)) < 0)
+                goto fail;
+        } else if ((ret = av_dict_set(&comm, t->key, t->value, 0)) < 0)
+            goto fail;
+    }
+
+    if (comm) {
+        if ((ret = av_dict_get_string(comm, &buf, '=', ',')) < 0 ||
+            (ret = avio_open_dyn_buf(&tmp)) < 0)
+            goto fail;
+        avio_put_str(tmp, buf);
+        av_freep(&buf);
+        write_header_chunk(pb, tmp, tag);
+    }
+    if (prv) {
+        if ((ret = av_dict_get_string(prv, &buf, '=', ',')) < 0 ||
+            (ret = avio_open_dyn_buf(&tmp)) < 0)
+            goto fail;
+        avio_put_str(tmp, buf);
+        write_header_chunk(pb, tmp, MKBETAG('C', 'P', 'R', 'V'));
+    }
+
+  fail:
+    av_free(buf);
+    av_dict_free(&all);
+    av_dict_free(&comm);
+    av_dict_free(&prv);
+    return ret;
+}
+
 static int ffm_write_header(AVFormatContext *s)
 {
     FFMContext *ffm = s->priv_data;
@@ -100,10 +223,10 @@
     AVStream *st;
     AVIOContext *pb = s->pb;
     AVCodecContext *codec;
-    int bit_rate, i;
+    int bit_rate, i, ret;
 
     if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) {
-        int ret = av_parse_time(&ffm->start_time, t->value, 0);
+        ret = av_parse_time(&ffm->start_time, t->value, 0);
         if (ret < 0)
             return ret;
     }
@@ -148,61 +271,29 @@
             avio_write(pb, codec->extradata, codec->extradata_size);
         }
         write_header_chunk(s->pb, pb, MKBETAG('C', 'O', 'M', 'M'));
-        if(avio_open_dyn_buf(&pb) < 0)
-            return AVERROR(ENOMEM);
         /* specific info */
         switch(codec->codec_type) {
         case AVMEDIA_TYPE_VIDEO:
-            avio_wb32(pb, codec->time_base.num);
-            avio_wb32(pb, codec->time_base.den);
-            avio_wb16(pb, codec->width);
-            avio_wb16(pb, codec->height);
-            avio_wb16(pb, codec->gop_size);
-            avio_wb32(pb, codec->pix_fmt);
-            avio_w8(pb, codec->qmin);
-            avio_w8(pb, codec->qmax);
-            avio_w8(pb, codec->max_qdiff);
-            avio_wb16(pb, (int) (codec->qcompress * 10000.0));
-            avio_wb16(pb, (int) (codec->qblur * 10000.0));
-            avio_wb32(pb, codec->bit_rate_tolerance);
-            avio_put_str(pb, codec->rc_eq ? codec->rc_eq : "tex^qComp");
-            avio_wb32(pb, codec->rc_max_rate);
-            avio_wb32(pb, codec->rc_min_rate);
-            avio_wb32(pb, codec->rc_buffer_size);
-            avio_wb64(pb, av_double2int(codec->i_quant_factor));
-            avio_wb64(pb, av_double2int(codec->b_quant_factor));
-            avio_wb64(pb, av_double2int(codec->i_quant_offset));
-            avio_wb64(pb, av_double2int(codec->b_quant_offset));
-            avio_wb32(pb, codec->dct_algo);
-            avio_wb32(pb, codec->strict_std_compliance);
-            avio_wb32(pb, codec->max_b_frames);
-            avio_wb32(pb, codec->mpeg_quant);
-            avio_wb32(pb, codec->intra_dc_precision);
-            avio_wb32(pb, codec->me_method);
-            avio_wb32(pb, codec->mb_decision);
-            avio_wb32(pb, codec->nsse_weight);
-            avio_wb32(pb, codec->frame_skip_cmp);
-            avio_wb64(pb, av_double2int(codec->rc_buffer_aggressivity));
-            avio_wb32(pb, codec->codec_tag);
-            avio_w8(pb, codec->thread_count);
-            avio_wb32(pb, codec->coder_type);
-            avio_wb32(pb, codec->me_cmp);
-            avio_wb32(pb, codec->me_subpel_quality);
-            avio_wb32(pb, codec->me_range);
-            avio_wb32(pb, codec->keyint_min);
-            avio_wb32(pb, codec->scenechange_threshold);
-            avio_wb32(pb, codec->b_frame_strategy);
-            avio_wb64(pb, av_double2int(codec->qcompress));
-            avio_wb64(pb, av_double2int(codec->qblur));
-            avio_wb32(pb, codec->max_qdiff);
-            avio_wb32(pb, codec->refs);
-            write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'V', 'I'));
+            if (st->recommended_encoder_configuration) {
+                av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n",
+                       st->recommended_encoder_configuration);
+                if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'V', 'I'),
+                                                        st->recommended_encoder_configuration)) < 0)
+                return ret;
+            } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'V', 'I'), AV_OPT_FLAG_VIDEO_PARAM)) < 0 ||
+                       (ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_VIDEO_PARAM)) < 0)
+                return ret;
             break;
         case AVMEDIA_TYPE_AUDIO:
-            avio_wb32(pb, codec->sample_rate);
-            avio_wl16(pb, codec->channels);
-            avio_wl16(pb, codec->frame_size);
-            write_header_chunk(s->pb, pb, MKBETAG('S', 'T', 'A', 'U'));
+            if (st->recommended_encoder_configuration) {
+                av_log(NULL, AV_LOG_DEBUG, "writing recommended configuration: %s\n",
+                       st->recommended_encoder_configuration);
+                if ((ret = ffm_write_recommended_config(s->pb, codec, MKBETAG('S', '2', 'A', 'U'),
+                                                        st->recommended_encoder_configuration)) < 0)
+                return ret;
+            } else if ((ret = ffm_write_header_codec_ctx(s->pb, codec, MKBETAG('S', '2', 'A', 'U'), AV_OPT_FLAG_AUDIO_PARAM)) < 0 ||
+                     (ret = ffm_write_header_codec_private_ctx(s->pb, codec, AV_OPT_FLAG_AUDIO_PARAM)) < 0)
+                return ret;
             break;
         default:
             return -1;
diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c
index c291393..1a8dc19 100644
--- a/libavformat/flacdec.c
+++ b/libavformat/flacdec.c
@@ -27,7 +27,6 @@
 #include "oggdec.h"
 #include "vorbiscomment.h"
 #include "replaygain.h"
-#include "libavcodec/bytestream.h"
 
 static int flac_read_header(AVFormatContext *s)
 {
@@ -75,7 +74,9 @@
         }
 
         if (metadata_type == FLAC_METADATA_TYPE_STREAMINFO) {
-            FLACStreaminfo si;
+            uint32_t samplerate;
+            uint64_t samples;
+
             /* STREAMINFO can only occur once */
             if (found_streaminfo) {
                 RETURN_ERROR(AVERROR_INVALIDDATA);
@@ -88,14 +89,16 @@
             st->codec->extradata_size = metadata_size;
             buffer = NULL;
 
-            /* get codec params from STREAMINFO header */
-            avpriv_flac_parse_streaminfo(st->codec, &si, st->codec->extradata);
+            /* get sample rate and sample count from STREAMINFO header;
+             * other parameters will be extracted by the parser */
+            samplerate = AV_RB24(st->codec->extradata + 10) >> 4;
+            samples    = (AV_RB64(st->codec->extradata + 13) >> 24) & ((1ULL << 36) - 1);
 
             /* set time base and duration */
-            if (si.samplerate > 0) {
-                avpriv_set_pts_info(st, 64, 1, si.samplerate);
-                if (si.samples > 0)
-                    st->duration = si.samples;
+            if (samplerate > 0) {
+                avpriv_set_pts_info(st, 64, 1, samplerate);
+                if (samples > 0)
+                    st->duration = samples;
             }
         } else if (metadata_type == FLAC_METADATA_TYPE_CUESHEET) {
             uint8_t isrc[13];
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 1c70a72..17d1313 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -885,10 +885,14 @@
     if (s->pb->seekable && (!s->duration || s->duration == AV_NOPTS_VALUE) && !flv->searched_for_end) {
         int size;
         const int64_t pos   = avio_tell(s->pb);
+        // Read the last 4 bytes of the file, this should be the size of the
+        // previous FLV tag. Use the timestamp of its payload as duration.
         int64_t fsize       = avio_size(s->pb);
 retry_duration:
         avio_seek(s->pb, fsize - 4, SEEK_SET);
         size = avio_rb32(s->pb);
+        // Seek to the start of the last FLV tag at position (fsize - 4 - size)
+        // but skip the byte indicating the type.
         avio_seek(s->pb, fsize - 3 - size, SEEK_SET);
         if (size == avio_rb24(s->pb) + 11) {
             uint32_t ts = avio_rb24(s->pb);
diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c
index 31a5c9e..5468c4d 100644
--- a/libavformat/flvenc.c
+++ b/libavformat/flvenc.c
@@ -63,6 +63,11 @@
     int64_t filesize_offset;
     int64_t duration;
     int64_t delay;      ///< first dts delay (needed for AVC & Speex)
+
+    AVCodecContext *audio_enc;
+    AVCodecContext *video_enc;
+    double framerate;
+    AVCodecContext *data_enc;
 } FLVContext;
 
 typedef struct FLVStreamContext {
@@ -191,108 +196,19 @@
     avio_w8(pb, !!b);
 }
 
-static int flv_write_header(AVFormatContext *s)
+static void write_metadata(AVFormatContext *s, unsigned int ts)
 {
     AVIOContext *pb = s->pb;
     FLVContext *flv = s->priv_data;
-    AVCodecContext *audio_enc = NULL, *video_enc = NULL, *data_enc = NULL;
-    int i, metadata_count = 0;
-    double framerate = 0.0;
+    int metadata_count = 0;
     int64_t metadata_size_pos, data_size, metadata_count_pos;
     AVDictionaryEntry *tag = NULL;
 
-    for (i = 0; i < s->nb_streams; i++) {
-        AVCodecContext *enc = s->streams[i]->codec;
-        FLVStreamContext *sc;
-        switch (enc->codec_type) {
-        case AVMEDIA_TYPE_VIDEO:
-            if (s->streams[i]->avg_frame_rate.den &&
-                s->streams[i]->avg_frame_rate.num) {
-                framerate = av_q2d(s->streams[i]->avg_frame_rate);
-            }
-            if (video_enc) {
-                av_log(s, AV_LOG_ERROR,
-                       "at most one video stream is supported in flv\n");
-                return AVERROR(EINVAL);
-            }
-            video_enc = enc;
-            if (enc->codec_tag == 0) {
-                av_log(s, AV_LOG_ERROR, "Video codec '%s' for stream %d is not compatible with FLV\n",
-                       avcodec_get_name(enc->codec_id), i);
-                return AVERROR(EINVAL);
-            }
-            if (enc->codec_id == AV_CODEC_ID_MPEG4 ||
-                enc->codec_id == AV_CODEC_ID_H263) {
-                int error = enc->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL;
-                av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
-                       "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(enc->codec_id));
-
-                if (error) {
-                    av_log(s, AV_LOG_ERROR,
-                           "use vstrict=-1 / -strict -1 to use it anyway.\n");
-                    return AVERROR(EINVAL);
-                }
-            }
-            break;
-        case AVMEDIA_TYPE_AUDIO:
-            if (audio_enc) {
-                av_log(s, AV_LOG_ERROR,
-                       "at most one audio stream is supported in flv\n");
-                return AVERROR(EINVAL);
-            }
-            audio_enc = enc;
-            if (get_audio_flags(s, enc) < 0)
-                return AVERROR_INVALIDDATA;
-            if (enc->codec_id == AV_CODEC_ID_PCM_S16BE)
-                av_log(s, AV_LOG_WARNING,
-                       "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
-            break;
-        case AVMEDIA_TYPE_DATA:
-            if (enc->codec_id != AV_CODEC_ID_TEXT && enc->codec_id != AV_CODEC_ID_NONE) {
-                av_log(s, AV_LOG_ERROR, "Data codec '%s' for stream %d is not compatible with FLV\n",
-                       avcodec_get_name(enc->codec_id), i);
-                return AVERROR_INVALIDDATA;
-            }
-            data_enc = enc;
-            break;
-        default:
-            av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n",
-                   av_get_media_type_string(enc->codec_type), i);
-            return AVERROR(EINVAL);
-        }
-        avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */
-
-        sc = av_mallocz(sizeof(FLVStreamContext));
-        if (!sc)
-            return AVERROR(ENOMEM);
-        s->streams[i]->priv_data = sc;
-        sc->last_ts = -1;
-    }
-
-    flv->delay = AV_NOPTS_VALUE;
-
-    avio_write(pb, "FLV", 3);
-    avio_w8(pb, 1);
-    avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!audio_enc +
-                FLV_HEADER_FLAG_HASVIDEO * !!video_enc);
-    avio_wb32(pb, 9);
-    avio_wb32(pb, 0);
-
-    for (i = 0; i < s->nb_streams; i++)
-        if (s->streams[i]->codec->codec_tag == 5) {
-            avio_w8(pb, 8);     // message type
-            avio_wb24(pb, 0);   // include flags
-            avio_wb24(pb, 0);   // time stamp
-            avio_wb32(pb, 0);   // reserved
-            avio_wb32(pb, 11);  // size
-            flv->reserved = 5;
-        }
-
     /* write meta_tag */
     avio_w8(pb, 18);            // tag type META
     metadata_size_pos = avio_tell(pb);
     avio_wb24(pb, 0);           // size of data part (sum of all parts below)
-    avio_wb24(pb, 0);           // timestamp
+    avio_wb24(pb, ts);          // timestamp
     avio_wb32(pb, 0);           // reserved
 
     /* now data of data_size size */
@@ -304,57 +220,57 @@
     /* mixed array (hash) with size and string/type/data tuples */
     avio_w8(pb, AMF_DATA_TYPE_MIXEDARRAY);
     metadata_count_pos = avio_tell(pb);
-    metadata_count = 4 * !!video_enc +
-                     5 * !!audio_enc +
-                     1 * !!data_enc  +
+    metadata_count = 4 * !!flv->video_enc +
+                     5 * !!flv->audio_enc +
+                     1 * !!flv->data_enc  +
                      2; // +2 for duration and file size
 
     avio_wb32(pb, metadata_count);
 
     put_amf_string(pb, "duration");
-    flv->duration_offset= avio_tell(pb);
+    flv->duration_offset = avio_tell(pb);
 
     // fill in the guessed duration, it'll be corrected later if incorrect
     put_amf_double(pb, s->duration / AV_TIME_BASE);
 
-    if (video_enc) {
+    if (flv->video_enc) {
         put_amf_string(pb, "width");
-        put_amf_double(pb, video_enc->width);
+        put_amf_double(pb, flv->video_enc->width);
 
         put_amf_string(pb, "height");
-        put_amf_double(pb, video_enc->height);
+        put_amf_double(pb, flv->video_enc->height);
 
         put_amf_string(pb, "videodatarate");
-        put_amf_double(pb, video_enc->bit_rate / 1024.0);
+        put_amf_double(pb, flv->video_enc->bit_rate / 1024.0);
 
-        if (framerate != 0.0) {
+        if (flv->framerate != 0.0) {
             put_amf_string(pb, "framerate");
-            put_amf_double(pb, framerate);
+            put_amf_double(pb, flv->framerate);
             metadata_count++;
         }
 
         put_amf_string(pb, "videocodecid");
-        put_amf_double(pb, video_enc->codec_tag);
+        put_amf_double(pb, flv->video_enc->codec_tag);
     }
 
-    if (audio_enc) {
+    if (flv->audio_enc) {
         put_amf_string(pb, "audiodatarate");
-        put_amf_double(pb, audio_enc->bit_rate / 1024.0);
+        put_amf_double(pb, flv->audio_enc->bit_rate / 1024.0);
 
         put_amf_string(pb, "audiosamplerate");
-        put_amf_double(pb, audio_enc->sample_rate);
+        put_amf_double(pb, flv->audio_enc->sample_rate);
 
         put_amf_string(pb, "audiosamplesize");
-        put_amf_double(pb, audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
+        put_amf_double(pb, flv->audio_enc->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16);
 
         put_amf_string(pb, "stereo");
-        put_amf_bool(pb, audio_enc->channels == 2);
+        put_amf_bool(pb, flv->audio_enc->channels == 2);
 
         put_amf_string(pb, "audiocodecid");
-        put_amf_double(pb, audio_enc->codec_tag);
+        put_amf_double(pb, flv->audio_enc->codec_tag);
     }
 
-    if (data_enc) {
+    if (flv->data_enc) {
         put_amf_string(pb, "datastream");
         put_amf_double(pb, 0.0);
     }
@@ -399,6 +315,106 @@
     avio_wb24(pb, data_size);
     avio_skip(pb, data_size + 10 - 3);
     avio_wb32(pb, data_size + 11);
+}
+
+static int flv_write_header(AVFormatContext *s)
+{
+    int i;
+    AVIOContext *pb = s->pb;
+    FLVContext *flv = s->priv_data;
+    int64_t data_size;
+
+    for (i = 0; i < s->nb_streams; i++) {
+        AVCodecContext *enc = s->streams[i]->codec;
+        FLVStreamContext *sc;
+        switch (enc->codec_type) {
+        case AVMEDIA_TYPE_VIDEO:
+            if (s->streams[i]->avg_frame_rate.den &&
+                s->streams[i]->avg_frame_rate.num) {
+                flv->framerate = av_q2d(s->streams[i]->avg_frame_rate);
+            }
+            if (flv->video_enc) {
+                av_log(s, AV_LOG_ERROR,
+                       "at most one video stream is supported in flv\n");
+                return AVERROR(EINVAL);
+            }
+            flv->video_enc = enc;
+            if (enc->codec_tag == 0) {
+                av_log(s, AV_LOG_ERROR, "Video codec '%s' for stream %d is not compatible with FLV\n",
+                       avcodec_get_name(enc->codec_id), i);
+                return AVERROR(EINVAL);
+            }
+            if (enc->codec_id == AV_CODEC_ID_MPEG4 ||
+                enc->codec_id == AV_CODEC_ID_H263) {
+                int error = s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL;
+                av_log(s, error ? AV_LOG_ERROR : AV_LOG_WARNING,
+                       "Codec %s is not supported in the official FLV specification,\n", avcodec_get_name(enc->codec_id));
+
+                if (error) {
+                    av_log(s, AV_LOG_ERROR,
+                           "use vstrict=-1 / -strict -1 to use it anyway.\n");
+                    return AVERROR(EINVAL);
+                }
+            } else if (enc->codec_id == AV_CODEC_ID_VP6) {
+                av_log(s, AV_LOG_WARNING,
+                       "Muxing VP6 in flv will produce flipped video on playback.\n");
+            }
+            break;
+        case AVMEDIA_TYPE_AUDIO:
+            if (flv->audio_enc) {
+                av_log(s, AV_LOG_ERROR,
+                       "at most one audio stream is supported in flv\n");
+                return AVERROR(EINVAL);
+            }
+            flv->audio_enc = enc;
+            if (get_audio_flags(s, enc) < 0)
+                return AVERROR_INVALIDDATA;
+            if (enc->codec_id == AV_CODEC_ID_PCM_S16BE)
+                av_log(s, AV_LOG_WARNING,
+                       "16-bit big-endian audio in flv is valid but most likely unplayable (hardware dependent); use s16le\n");
+            break;
+        case AVMEDIA_TYPE_DATA:
+            if (enc->codec_id != AV_CODEC_ID_TEXT && enc->codec_id != AV_CODEC_ID_NONE) {
+                av_log(s, AV_LOG_ERROR, "Data codec '%s' for stream %d is not compatible with FLV\n",
+                       avcodec_get_name(enc->codec_id), i);
+                return AVERROR_INVALIDDATA;
+            }
+            flv->data_enc = enc;
+            break;
+        default:
+            av_log(s, AV_LOG_ERROR, "Codec type '%s' for stream %d is not compatible with FLV\n",
+                   av_get_media_type_string(enc->codec_type), i);
+            return AVERROR(EINVAL);
+        }
+        avpriv_set_pts_info(s->streams[i], 32, 1, 1000); /* 32 bit pts in ms */
+
+        sc = av_mallocz(sizeof(FLVStreamContext));
+        if (!sc)
+            return AVERROR(ENOMEM);
+        s->streams[i]->priv_data = sc;
+        sc->last_ts = -1;
+    }
+
+    flv->delay = AV_NOPTS_VALUE;
+
+    avio_write(pb, "FLV", 3);
+    avio_w8(pb, 1);
+    avio_w8(pb, FLV_HEADER_FLAG_HASAUDIO * !!flv->audio_enc +
+                FLV_HEADER_FLAG_HASVIDEO * !!flv->video_enc);
+    avio_wb32(pb, 9);
+    avio_wb32(pb, 0);
+
+    for (i = 0; i < s->nb_streams; i++)
+        if (s->streams[i]->codec->codec_tag == 5) {
+            avio_w8(pb, 8);     // message type
+            avio_wb24(pb, 0);   // include flags
+            avio_wb24(pb, 0);   // time stamp
+            avio_wb32(pb, 0);   // reserved
+            avio_wb32(pb, 11);  // size
+            flv->reserved = 5;
+        }
+
+    write_metadata(s, 0);
 
     for (i = 0; i < s->nb_streams; i++) {
         AVCodecContext *enc = s->streams[i]->codec;
@@ -484,6 +500,22 @@
     else
         flags_size = 1;
 
+    if (flv->delay == AV_NOPTS_VALUE)
+        flv->delay = -pkt->dts;
+
+    if (pkt->dts < -flv->delay) {
+        av_log(s, AV_LOG_WARNING,
+               "Packets are not in the proper order with respect to DTS\n");
+        return AVERROR(EINVAL);
+    }
+
+    ts = pkt->dts + flv->delay; // add delay to force positive dts
+
+    if (s->event_flags & AVSTREAM_EVENT_FLAG_METADATA_UPDATED) {
+        write_metadata(s, ts);
+        s->event_flags &= ~AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
+    }
+
     switch (enc->codec_type) {
     case AVMEDIA_TYPE_VIDEO:
         avio_w8(pb, FLV_TAG_TYPE_VIDEO);
@@ -528,17 +560,6 @@
         av_log(s, AV_LOG_WARNING, "aac bitstream error\n");
     }
 
-    if (flv->delay == AV_NOPTS_VALUE)
-        flv->delay = -pkt->dts;
-
-    if (pkt->dts < -flv->delay) {
-        av_log(s, AV_LOG_WARNING,
-               "Packets are not in the proper order with respect to DTS\n");
-        return AVERROR(EINVAL);
-    }
-
-    ts = pkt->dts + flv->delay; // add delay to force positive dts
-
     /* check Speex packet duration */
     if (enc->codec_id == AV_CODEC_ID_SPEEX && ts - sc->last_ts > 160)
         av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "
@@ -548,6 +569,12 @@
     if (sc->last_ts < ts)
         sc->last_ts = ts;
 
+    if (size + flags_size >= 1<<24) {
+        av_log(s, AV_LOG_ERROR, "Too large packet with size %u >= %u\n",
+               size + flags_size, 1<<24);
+        return AVERROR(EINVAL);
+    }
+
     avio_wb24(pb, size + flags_size);
     avio_wb24(pb, ts & 0xFFFFFF);
     avio_w8(pb, (ts >> 24) & 0x7F); // timestamps are 32 bits _signed_
diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c
index eec9bb8..33d7c3a 100644
--- a/libavformat/hdsenc.c
+++ b/libavformat/hdsenc.c
@@ -174,7 +174,7 @@
     ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
                      &s->interrupt_callback, NULL);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", filename);
+        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
         return ret;
     }
     avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
@@ -396,6 +396,7 @@
             goto fail;
         }
         avcodec_copy_context(st->codec, s->streams[i]->codec);
+        st->codec->codec_tag = 0;
         st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
         st->time_base = s->streams[i]->time_base;
     }
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 0525e70..e13f438 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -389,9 +389,10 @@
     av_write_trailer(oc);
     hls->size = avio_tell(hls->avf->pb) - hls->start_pos;
     avio_closep(&oc->pb);
-    avformat_free_context(oc);
     av_free(hls->basename);
     hls_append_segment(hls, hls->duration, hls->start_pos, hls->size);
+    avformat_free_context(oc);
+    hls->avf = NULL;
     hls_window(s, 1);
 
     hls_free_segments(hls);
diff --git a/libavformat/http.c b/libavformat/http.c
index dfc01ee..d9de05c 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -207,6 +207,8 @@
     HTTPContext *s = h->priv_data;
     int location_changed, attempts = 0, redirects = 0;
 redo:
+    av_dict_copy(options, s->chained_options, 0);
+
     cur_auth_type       = s->auth_state.auth_type;
     cur_proxy_auth_type = s->auth_state.auth_type;
 
@@ -268,7 +270,6 @@
     if (!s->location)
         return AVERROR(ENOMEM);
 
-    av_dict_copy(&options, s->chained_options, 0);
     ret = http_open_cnx(h, &options);
     av_dict_free(&options);
     return ret;
@@ -1136,7 +1137,6 @@
     s->hd = NULL;
 
     /* if it fails, continue on old connection */
-    av_dict_copy(&options, s->chained_options, 0);
     if ((ret = http_open_cnx(h, &options)) < 0) {
         av_dict_free(&options);
         memcpy(s->buffer, old_buf, old_buf_size);
diff --git a/libavformat/icecast.c b/libavformat/icecast.c
index 7d60e44..a7c7001 100644
--- a/libavformat/icecast.c
+++ b/libavformat/icecast.c
@@ -115,8 +115,11 @@
     av_dict_set(&opt_dict, "auth_type", "basic", 0);
     av_dict_set(&opt_dict, "headers", headers, 0);
     av_dict_set(&opt_dict, "chunked_post", "0", 0);
+    av_dict_set(&opt_dict, "send_expect_100", s->legacy_icecast ? "0" : "1", 0);
     if (NOT_EMPTY(s->content_type))
         av_dict_set(&opt_dict, "content_type", s->content_type, 0);
+    else
+        av_dict_set(&opt_dict, "content_type", "audio/mpeg", 0);
     if (NOT_EMPTY(s->user_agent))
         av_dict_set(&opt_dict, "user_agent", s->user_agent, 0);
 
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 3e54620..cbf4375 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -60,8 +60,8 @@
 
 const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
     { "TCMP", "compilation"   },
-    { "TDRL", "date"          },
     { "TDRC", "date"          },
+    { "TDRL", "date"          },
     { "TDEN", "creation_time" },
     { "TSOA", "album-sort"    },
     { "TSOP", "artist-sort"   },
diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c
index 37dfbec..2b8b2d0 100644
--- a/libavformat/img2enc.c
+++ b/libavformat/img2enc.c
@@ -26,6 +26,7 @@
 #include "libavutil/log.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
+#include "libavutil/time_internal.h"
 #include "avformat.h"
 #include "avio_internal.h"
 #include "internal.h"
@@ -83,9 +84,9 @@
             av_strlcpy(filename, img->path, sizeof(filename));
         } else if (img->use_strftime) {
             time_t now0;
-            struct tm *tm;
+            struct tm *tm, tmpbuf;
             time(&now0);
-            tm = localtime(&now0);
+            tm = localtime_r(&now0, &tmpbuf);
             if (!strftime(filename, sizeof(filename), img->path, tm)) {
                 av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n");
                 return AVERROR(EINVAL);
@@ -194,7 +195,7 @@
     .long_name      = NULL_IF_CONFIG_SMALL("image2 sequence"),
     .extensions     = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
                       "ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24,"
-                      "sunras,webp,xbm,xface,pix,y",
+                      "sunras,xbm,xface,pix,y",
     .priv_data_size = sizeof(VideoMuxData),
     .video_codec    = AV_CODEC_ID_MJPEG,
     .write_header   = write_header,
diff --git a/libavformat/internal.h b/libavformat/internal.h
index f7a79dd..ce03dac 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -23,6 +23,7 @@
 
 #include <stdint.h>
 #include "avformat.h"
+#include "os_support.h"
 
 #define MAX_URL_SIZE 4096
 
diff --git a/libavformat/jacosubdec.c b/libavformat/jacosubdec.c
index 9a28870..1ca0055 100644
--- a/libavformat/jacosubdec.c
+++ b/libavformat/jacosubdec.c
@@ -232,7 +232,7 @@
     /* general/essential directives in the extradata */
     ret = avpriv_bprint_to_extradata(st->codec, &header);
     if (ret < 0)
-        return ret;
+        goto fail;
 
     /* SHIFT and TIMERES affect the whole script so packet timing can only be
      * done in a second pass */
@@ -243,6 +243,9 @@
     ff_subtitles_queue_finalize(&jacosub->q);
 
     return 0;
+fail:
+    jacosub_read_close(s);
+    return ret;
 }
 
 static int jacosub_read_packet(AVFormatContext *s, AVPacket *pkt)
diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c
index c57699c..67939b9 100644
--- a/libavformat/librtmp.c
+++ b/libavformat/librtmp.c
@@ -169,7 +169,7 @@
     }
     if (ctx->swfurl) {
         av_strlcat(filename, " swfUrl=", len);
-        av_strlcat(filename, ctx->pageurl, len);
+        av_strlcat(filename, ctx->swfurl, len);
     }
     if (ctx->flashver) {
         av_strlcat(filename, " flashVer=", len);
diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c
index 11d6da5..fb37da7 100644
--- a/libavformat/lxfdec.c
+++ b/libavformat/lxfdec.c
@@ -83,7 +83,7 @@
  * @param[out] header where to copy the ident to
  * @return 0 if an ident was found, < 0 on I/O error
  */
-static int sync(AVFormatContext *s, uint8_t *header)
+static int lxf_sync(AVFormatContext *s, uint8_t *header)
 {
     uint8_t buf[LXF_IDENT_LENGTH];
     int ret;
@@ -120,7 +120,7 @@
     const uint8_t *p = header + LXF_IDENT_LENGTH;
 
     //find and read the ident
-    if ((ret = sync(s, header)) < 0)
+    if ((ret = lxf_sync(s, header)) < 0)
         return ret;
 
     ret = avio_read(pb, header + LXF_IDENT_LENGTH, 8);
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 78b81b7..e7d10d8 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -32,12 +32,6 @@
 
 #include <inttypes.h>
 #include <stdio.h>
-#if CONFIG_BZLIB
-#include <bzlib.h>
-#endif
-#if CONFIG_ZLIB
-#include <zlib.h>
-#endif
 
 #include "libavutil/avstring.h"
 #include "libavutil/base64.h"
@@ -46,6 +40,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/lzo.h"
 #include "libavutil/mathematics.h"
+#include "libavutil/time_internal.h"
 
 #include "libavcodec/bytestream.h"
 #include "libavcodec/flac.h"
@@ -65,6 +60,13 @@
 
 static int matroska_read_close(AVFormatContext *s);
 
+#if CONFIG_BZLIB
+#include <bzlib.h>
+#endif
+#if CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
 typedef enum {
     EBML_NONE,
     EBML_UINT,
@@ -1511,7 +1513,7 @@
     char buffer[32];
     /* Convert to seconds and adjust by number of seconds between 2001-01-01 and Epoch */
     time_t creation_time = date_utc / 1000000000 + 978307200;
-    struct tm *ptm = gmtime(&creation_time);
+    struct tm tmpbuf, *ptm = gmtime_r(&creation_time, &tmpbuf);
     if (!ptm) return;
     if (strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ptm))
         av_dict_set(metadata, "creation_time", buffer, 0);
diff --git a/libavformat/mmf.c b/libavformat/mmf.c
index f557eeb..e963112 100644
--- a/libavformat/mmf.c
+++ b/libavformat/mmf.c
@@ -82,7 +82,7 @@
 
     mmf->stereo = s->streams[0]->codec->channels > 1;
     if (mmf->stereo &&
-        s->streams[0]->codec->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+        s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
         av_log(s, AV_LOG_ERROR, "Yamaha SMAF stereo is experimental, "
                "add '-strict %d' if you want to use it.\n",
                FF_COMPLIANCE_EXPERIMENTAL);
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 6ba7b96..64c2c10 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -691,16 +691,16 @@
 static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom)
 {
     AVStream *st;
+    int ret;
 
     if (c->fc->nb_streams < 1)
         return 0;
     st = c->fc->streams[c->fc->nb_streams-1];
 
-    if (ff_get_wav_header(pb, st->codec, atom.size) < 0) {
+    if ((ret = ff_get_wav_header(pb, st->codec, atom.size)) < 0)
         av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n");
-    }
 
-    return 0;
+    return ret;
 }
 
 static int mov_read_pasp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
@@ -1272,10 +1272,12 @@
 
     if (!entries)
         return 0;
-    if (entries >= UINT_MAX/sizeof(int64_t))
-        return AVERROR_INVALIDDATA;
 
-    sc->chunk_offsets = av_malloc(entries * sizeof(int64_t));
+    if (sc->chunk_offsets)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated STCO atom\n");
+    av_free(sc->chunk_offsets);
+    sc->chunk_count = 0;
+    sc->chunk_offsets = av_malloc_array(entries, sizeof(*sc->chunk_offsets));
     if (!sc->chunk_offsets)
         return AVERROR(ENOMEM);
     sc->chunk_count = entries;
@@ -1869,9 +1871,11 @@
 
     if (!entries)
         return 0;
-    if (entries >= UINT_MAX / sizeof(*sc->stsc_data))
-        return AVERROR_INVALIDDATA;
-    sc->stsc_data = av_malloc(entries * sizeof(*sc->stsc_data));
+    if (sc->stsc_data)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated STSC atom\n");
+    av_free(sc->stsc_data);
+    sc->stsc_count = 0;
+    sc->stsc_data = av_malloc_array(entries, sizeof(*sc->stsc_data));
     if (!sc->stsc_data)
         return AVERROR(ENOMEM);
 
@@ -1903,9 +1907,11 @@
     avio_rb32(pb); // version + flags
 
     entries = avio_rb32(pb);
-    if (entries >= UINT_MAX / sizeof(*sc->stps_data))
-        return AVERROR_INVALIDDATA;
-    sc->stps_data = av_malloc(entries * sizeof(*sc->stps_data));
+    if (sc->stps_data)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated STPS atom\n");
+    av_free(sc->stps_data);
+    sc->stps_count = 0;
+    sc->stps_data = av_malloc_array(entries, sizeof(*sc->stps_data));
     if (!sc->stps_data)
         return AVERROR(ENOMEM);
 
@@ -1947,9 +1953,11 @@
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
         return 0;
     }
-    if (entries >= UINT_MAX / sizeof(int))
-        return AVERROR_INVALIDDATA;
-    sc->keyframes = av_malloc(entries * sizeof(int));
+    if (sc->keyframes)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated STSS atom\n");
+    av_free(sc->keyframes);
+    sc->keyframe_count = 0;
+    sc->keyframes = av_malloc_array(entries, sizeof(*sc->keyframes));
     if (!sc->keyframes)
         return AVERROR(ENOMEM);
 
@@ -2008,9 +2016,13 @@
 
     if (!entries)
         return 0;
-    if (entries >= UINT_MAX / sizeof(int) || entries >= (UINT_MAX - 4) / field_size)
+    if (entries >= (UINT_MAX - 4) / field_size)
         return AVERROR_INVALIDDATA;
-    sc->sample_sizes = av_malloc(entries * sizeof(int));
+    if (sc->sample_sizes)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated STSZ atom\n");
+    av_free(sc->sample_sizes);
+    sc->sample_count = 0;
+    sc->sample_sizes = av_malloc_array(entries, sizeof(*sc->sample_sizes));
     if (!sc->sample_sizes)
         return AVERROR(ENOMEM);
 
@@ -2064,11 +2076,11 @@
     av_dlog(c->fc, "track[%i].stts.entries = %i\n",
             c->fc->nb_streams-1, entries);
 
-    if (entries >= UINT_MAX / sizeof(*sc->stts_data))
-        return -1;
-
+    if (sc->stts_data)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated STTS atom\n");
     av_free(sc->stts_data);
-    sc->stts_data = av_malloc(entries * sizeof(*sc->stts_data));
+    sc->stts_count = 0;
+    sc->stts_data = av_malloc_array(entries, sizeof(*sc->stts_data));
     if (!sc->stts_data)
         return AVERROR(ENOMEM);
 
@@ -2207,9 +2219,11 @@
     entries = avio_rb32(pb);
     if (!entries)
         return 0;
-    if (entries >= UINT_MAX / sizeof(*sc->rap_group))
-        return AVERROR_INVALIDDATA;
-    sc->rap_group = av_malloc(entries * sizeof(*sc->rap_group));
+    if (sc->rap_group)
+        av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n");
+    av_free(sc->rap_group);
+    sc->rap_group_count = 0;
+    sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group));
     if (!sc->rap_group)
         return AVERROR(ENOMEM);
 
@@ -3819,36 +3833,42 @@
 {
     int64_t stream_size = avio_size(f);
     int64_t original_pos = avio_tell(f);
+    int64_t seek_ret;
     int32_t mfra_size;
     int ret = -1;
-    if ((ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) goto fail;
+    if ((seek_ret = avio_seek(f, stream_size - 4, SEEK_SET)) < 0) {
+        ret = seek_ret;
+        goto fail;
+    }
     mfra_size = avio_rb32(f);
     if (mfra_size < 0 || mfra_size > stream_size) {
         av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (unreasonable size)\n");
-        ret = -1;
         goto fail;
     }
-    if ((ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) goto fail;
+    if ((seek_ret = avio_seek(f, -mfra_size, SEEK_CUR)) < 0) {
+        ret = seek_ret;
+        goto fail;
+    }
     if (avio_rb32(f) != mfra_size) {
         av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (size mismatch)\n");
-        ret = -1;
         goto fail;
     }
     if (avio_rb32(f) != MKBETAG('m', 'f', 'r', 'a')) {
         av_log(c->fc, AV_LOG_DEBUG, "doesn't look like mfra (tag mismatch)\n");
         goto fail;
     }
+    ret = 0;
     av_log(c->fc, AV_LOG_VERBOSE, "stream has mfra\n");
     while (!read_tfra(c, f)) {
         /* Empty */
     }
 fail:
-    ret = avio_seek(f, original_pos, SEEK_SET);
-    if (ret < 0)
+    seek_ret = avio_seek(f, original_pos, SEEK_SET);
+    if (seek_ret < 0) {
         av_log(c->fc, AV_LOG_ERROR,
                "failed to seek back after looking for mfra\n");
-    else
-        ret = 0;
+        ret = seek_ret;
+    }
     return ret;
 }
 
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index a43752a..6e51424 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -55,7 +55,7 @@
     { "movflags", "MOV muxer flags", offsetof(MOVMuxContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "rtphint", "Add RTP hint tracks", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_RTP_HINT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "moov_size", "maximum moov size so it can be placed at the begin", offsetof(MOVMuxContext, reserved_moov_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, 0 },
-    { "empty_moov", "Make the initial moov atom empty (not supported by QuickTime)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "empty_moov", "Make the initial moov atom empty", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_EMPTY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "frag_keyframe", "Fragment at video keyframes", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_KEYFRAME}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
@@ -63,6 +63,9 @@
     { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "omit_tfhd_offset", "Omit the base data offset in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_OMIT_TFHD_OFFSET}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     { "disable_chpl", "Disable Nero chapter atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DISABLE_CHPL}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "default_base_moof", "Set the default-base-is-moof flag in tfhd atoms", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DEFAULT_BASE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "dash", "Write DASH compatible fragmented MP4", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DASH}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
+    { "frag_discont", "Signal that the next fragment is discontinuous from earlier ones", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_DISCONT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" },
     FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags),
     { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
     { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM},
@@ -71,9 +74,10 @@
     { "min_frag_duration", "Minimum fragment duration", offsetof(MOVMuxContext, min_fragment_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
     { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
     { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
-    { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
     { "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext, video_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
     { "brand",    "Override major brand", offsetof(MOVMuxContext, major_brand),   AV_OPT_TYPE_STRING, {.str = NULL}, .flags = AV_OPT_FLAG_ENCODING_PARAM },
+    { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM},
+    { "fragment_index", "Fragment number of the next fragment", offsetof(MOVMuxContext, fragments), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM},
     { NULL },
 };
 
@@ -109,13 +113,6 @@
     return curpos - pos;
 }
 
-static int supports_edts(MOVMuxContext *mov)
-{
-    // EDTS with fragments is tricky as we don't know the duration when its written
-    // also we might end up having to write the EDTS before the first packet, which would fail
-    return (mov->use_editlist<0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) || mov->use_editlist>0;
-}
-
 static int co64_required(const MOVTrack *track)
 {
     if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX)
@@ -937,6 +934,8 @@
             if (track->enc->codec_id == AV_CODEC_ID_PCM_U8 ||
                 track->enc->codec_id == AV_CODEC_ID_PCM_S8)
                 avio_wb16(pb, 8); /* bits per sample */
+            else if (track->enc->codec_id == AV_CODEC_ID_ADPCM_G726)
+                avio_wb16(pb, track->enc->bits_per_coded_sample);
             else
                 avio_wb16(pb, 16);
             avio_wb16(pb, track->audio_vbr ? -2 : 0); /* compression ID */
@@ -1336,7 +1335,7 @@
 {
     int tag = track->enc->codec_tag;
 
-    if (!tag || (track->enc->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
+    if (!tag || (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL &&
                  (track->enc->codec_id == AV_CODEC_ID_DVVIDEO ||
                   track->enc->codec_id == AV_CODEC_ID_RAWVIDEO ||
                   track->enc->codec_id == AV_CODEC_ID_H263 ||
@@ -2031,7 +2030,8 @@
     return update_size(pb, pos);
 }
 
-static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov,
+                              MOVTrack *track)
 {
     int version = track->track_duration < INT32_MAX ? 0 : 1;
 
@@ -2050,8 +2050,10 @@
         avio_wb32(pb, track->time); /* modification time */
     }
     avio_wb32(pb, track->timescale); /* time scale (sample rate for audio) */
-    if (!track->entry)
+    if (!track->entry && mov->mode == MODE_ISM)
         (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
+    else if (!track->entry)
+        (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
     else
         (version == 1) ? avio_wb64(pb, track->track_duration) : avio_wb32(pb, track->track_duration); /* duration */
     avio_wb16(pb, track->language); /* language */
@@ -2067,12 +2069,13 @@
     return 32;
 }
 
-static int mov_write_mdia_tag(AVIOContext *pb, MOVTrack *track)
+static int mov_write_mdia_tag(AVIOContext *pb, MOVMuxContext *mov,
+                              MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "mdia");
-    mov_write_mdhd_tag(pb, track);
+    mov_write_mdhd_tag(pb, mov, track);
     mov_write_hdlr_tag(pb, track);
     mov_write_minf_tag(pb, track);
     return update_size(pb, pos);
@@ -2133,8 +2136,10 @@
     }
     avio_wb32(pb, track->track_id); /* track-id */
     avio_wb32(pb, 0); /* reserved */
-    if (!track->entry)
+    if (!track->entry && mov->mode == MODE_ISM)
         (version == 1) ? avio_wb64(pb, UINT64_C(0xffffffffffffffff)) : avio_wb32(pb, 0xffffffff);
+    else if (!track->entry)
+        (version == 1) ? avio_wb64(pb, 0) : avio_wb32(pb, 0);
     else
         (version == 1) ? avio_wb64(pb, duration) : avio_wb32(pb, duration);
 
@@ -2384,11 +2389,21 @@
     avio_wb32(pb, 0); /* size */
     ffio_wfourcc(pb, "trak");
     mov_write_tkhd_tag(pb, mov, track, st);
-    if (supports_edts(mov))
-        mov_write_edts_tag(pb, mov, track);  // PSP Movies and several other cases require edts box
+
+    av_assert2(mov->use_editlist >= 0);
+
+
+    if (track->entry) {
+        if (mov->use_editlist)
+            mov_write_edts_tag(pb, mov, track);  // PSP Movies and several other cases require edts box
+        else if ((track->entry && track->cluster[0].dts) || track->mode == MODE_PSP || is_clcp_track(track))
+            av_log(mov->fc, AV_LOG_WARNING,
+                   "Not writing any edit list even though one would have been required\n");
+    }
+
     if (track->tref_tag)
         mov_write_tref_tag(pb, track);
-    mov_write_mdia_tag(pb, track);
+    mov_write_mdia_tag(pb, mov, track);
     if (track->mode == MODE_PSP)
         mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box
     if (track->tag == MKTAG('r','t','p',' '))
@@ -2415,7 +2430,7 @@
     int audio_profile = mov->iods_audio_profile;
     int video_profile = mov->iods_video_profile;
     for (i = 0; i < mov->nb_streams; i++) {
-        if (mov->tracks[i].entry > 0) {
+        if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
             has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO;
             has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO;
         }
@@ -3117,6 +3132,10 @@
     }
     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET)
         flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
+    if (mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) {
+        flags &= ~MOV_TFHD_BASE_DATA_OFFSET;
+        flags |= MOV_TFHD_DEFAULT_BASE_IS_MOOF;
+    }
 
     /* Don't set a default sample size, the silverlight player refuses
      * to play files with that set. Don't set a default sample duration,
@@ -3188,8 +3207,8 @@
 
     avio_wb32(pb, track->entry); /* sample count */
     if (mov->flags & FF_MOV_FLAG_OMIT_TFHD_OFFSET &&
-        !(mov->flags & FF_MOV_FLAG_SEPARATE_MOOF) &&
-        track->track_id != 1)
+        !(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) &&
+        !mov->first_trun)
         avio_wb32(pb, 0); /* Later tracks follow immediately after the previous one */
     else
         avio_wb32(pb, moof_size + 8 + track->data_offset +
@@ -3208,6 +3227,7 @@
             avio_wb32(pb, track->cluster[i].cts);
     }
 
+    mov->first_trun = 0;
     return update_size(pb, pos);
 }
 
@@ -3280,6 +3300,44 @@
     return 0;
 }
 
+static int mov_add_tfra_entries(AVIOContext *pb, MOVMuxContext *mov, int tracks,
+                                int size)
+{
+    int i;
+    for (i = 0; i < mov->nb_streams; i++) {
+        MOVTrack *track = &mov->tracks[i];
+        MOVFragmentInfo *info;
+        if ((tracks >= 0 && i != tracks) || !track->entry)
+            continue;
+        track->nb_frag_info++;
+        if (track->nb_frag_info >= track->frag_info_capacity) {
+            unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
+            if (av_reallocp_array(&track->frag_info,
+                                  new_capacity,
+                                  sizeof(*track->frag_info)))
+                return AVERROR(ENOMEM);
+            track->frag_info_capacity = new_capacity;
+        }
+        info = &track->frag_info[track->nb_frag_info - 1];
+        info->offset   = avio_tell(pb);
+        info->size     = size;
+        // Try to recreate the original pts for the first packet
+        // from the fields we have stored
+        info->time     = track->start_dts + track->frag_start +
+                         track->cluster[0].cts;
+        // If the pts is less than zero, we will have trimmed
+        // away parts of the media track using an edit list,
+        // and the corresponding start presentation time is zero.
+        if (info->time < 0)
+            info->time = 0;
+        info->duration = track->start_dts + track->track_duration -
+                         track->cluster[0].dts;
+        info->tfrf_offset = 0;
+        mov_write_tfrf_tags(pb, mov, track);
+    }
+    return 0;
+}
+
 static int mov_write_tfdt_tag(AVIOContext *pb, MOVTrack *track)
 {
     int64_t pos = avio_tell(pb);
@@ -3301,7 +3359,8 @@
     ffio_wfourcc(pb, "traf");
 
     mov_write_tfhd_tag(pb, mov, track, moof_offset);
-    mov_write_tfdt_tag(pb, track);
+    if (mov->mode != MODE_ISM)
+        mov_write_tfdt_tag(pb, track);
     mov_write_trun_tag(pb, mov, track, moof_size);
     if (mov->mode == MODE_ISM) {
         mov_write_tfxd_tag(pb, track);
@@ -3309,7 +3368,11 @@
         if (mov->ism_lookahead) {
             int i, size = 16 + 4 + 1 + 16 * mov->ism_lookahead;
 
-            track->tfrf_offset = avio_tell(pb);
+            if (track->nb_frag_info > 0) {
+                MOVFragmentInfo *info = &track->frag_info[track->nb_frag_info - 1];
+                if (!info->tfrf_offset)
+                    info->tfrf_offset = avio_tell(pb);
+            }
             avio_wb32(pb, 8 + size);
             ffio_wfourcc(pb, "free");
             for (i = 0; i < size; i++)
@@ -3328,6 +3391,7 @@
 
     avio_wb32(pb, 0); /* size placeholder */
     ffio_wfourcc(pb, "moof");
+    mov->first_trun = 1;
 
     mov_write_mfhd_tag(pb, mov);
     for (i = 0; i < mov->nb_streams; i++) {
@@ -3342,7 +3406,100 @@
     return update_size(pb, pos);
 }
 
-static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks)
+static int mov_write_sidx_tag(AVIOContext *pb,
+                              MOVTrack *track, int ref_size, int total_sidx_size)
+{
+    int64_t pos = avio_tell(pb), offset_pos, end_pos;
+    int64_t presentation_time, duration, offset;
+    int starts_with_SAP, i, entries;
+
+    if (track->entry) {
+        entries = 1;
+        presentation_time = track->start_dts + track->frag_start +
+                            track->cluster[0].cts;
+        duration = track->start_dts + track->track_duration -
+                   track->cluster[0].dts;
+        starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
+    } else {
+        entries = track->nb_frag_info;
+        presentation_time = track->frag_info[0].time;
+    }
+
+    // pts<0 should be cut away using edts
+    if (presentation_time < 0)
+        presentation_time = 0;
+
+    avio_wb32(pb, 0); /* size */
+    ffio_wfourcc(pb, "sidx");
+    avio_w8(pb, 1); /* version */
+    avio_wb24(pb, 0);
+    avio_wb32(pb, track->track_id); /* reference_ID */
+    avio_wb32(pb, track->timescale); /* timescale */
+    avio_wb64(pb, presentation_time); /* earliest_presentation_time */
+    offset_pos = avio_tell(pb);
+    avio_wb64(pb, 0); /* first_offset (offset to referenced moof) */
+    avio_wb16(pb, 0); /* reserved */
+
+    avio_wb16(pb, entries); /* reference_count */
+    for (i = 0; i < entries; i++) {
+        if (!track->entry) {
+            if (i > 1 && track->frag_info[i].offset != track->frag_info[i - 1].offset + track->frag_info[i - 1].size) {
+               av_log(NULL, AV_LOG_ERROR, "Non-consecutive fragments, writing incorrect sidx\n");
+            }
+            duration = track->frag_info[i].duration;
+            ref_size = track->frag_info[i].size;
+            starts_with_SAP = 1;
+        }
+        avio_wb32(pb, (0 << 31) | (ref_size & 0x7fffffff)); /* reference_type (0 = media) | referenced_size */
+        avio_wb32(pb, duration); /* subsegment_duration */
+        avio_wb32(pb, (starts_with_SAP << 31) | (0 << 28) | 0); /* starts_with_SAP | SAP_type | SAP_delta_time */
+    }
+
+    end_pos = avio_tell(pb);
+    offset = pos + total_sidx_size - end_pos;
+    avio_seek(pb, offset_pos, SEEK_SET);
+    avio_wb64(pb, offset);
+    avio_seek(pb, end_pos, SEEK_SET);
+    return update_size(pb, pos);
+}
+
+static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov,
+                               int tracks, int ref_size)
+{
+    int i, round, ret;
+    AVIOContext *avio_buf;
+    int total_size = 0;
+    for (round = 0; round < 2; round++) {
+        // First run one round to calculate the total size of all
+        // sidx atoms.
+        // This would be much simpler if we'd only write one sidx
+        // atom, for the first track in the moof.
+        if (round == 0) {
+            if ((ret = ffio_open_null_buf(&avio_buf)) < 0)
+                return ret;
+        } else {
+            avio_buf = pb;
+        }
+        for (i = 0; i < mov->nb_streams; i++) {
+            MOVTrack *track = &mov->tracks[i];
+            if (tracks >= 0 && i != tracks)
+                continue;
+            // When writing a sidx for the full file, entry is 0, but
+            // we want to include all tracks. ref_size is 0 in this case,
+            // since we read it from frag_info instead.
+            if (!track->entry && ref_size > 0)
+                continue;
+            total_size -= mov_write_sidx_tag(avio_buf, track, ref_size,
+                                             total_size);
+        }
+        if (round == 0)
+            total_size = ffio_close_null_buf(avio_buf);
+    }
+    return 0;
+}
+
+static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks,
+                              int64_t mdat_size)
 {
     AVIOContext *avio_buf;
     int ret, moof_size;
@@ -3351,6 +3508,13 @@
         return ret;
     mov_write_moof_tag_internal(avio_buf, mov, tracks, 0);
     moof_size = ffio_close_null_buf(avio_buf);
+
+    if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_FASTSTART))
+        mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size);
+
+    if ((ret = mov_add_tfra_entries(pb, mov, tracks, moof_size + 8 + mdat_size)) < 0)
+        return ret;
+
     return mov_write_moof_tag_internal(pb, mov, tracks, moof_size);
 }
 
@@ -3369,7 +3533,7 @@
     avio_wb32(pb, track->nb_frag_info);
     for (i = 0; i < track->nb_frag_info; i++) {
         avio_wb64(pb, track->frag_info[i].time);
-        avio_wb64(pb, track->frag_info[i].offset);
+        avio_wb64(pb, track->frag_info[i].offset + track->data_offset);
         avio_w8(pb, 1); /* traf number */
         avio_w8(pb, 1); /* trun number */
         avio_w8(pb, 1); /* sample number */
@@ -3445,6 +3609,8 @@
         minor =     has_h264 ? 0x20000 : 0x10000;
     } else if (mov->mode == MODE_PSP)
         ffio_wfourcc(pb, "MSNV");
+    else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)
+        ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof
     else if (mov->mode == MODE_MP4)
         ffio_wfourcc(pb, "isom");
     else if (mov->mode == MODE_IPOD)
@@ -3462,14 +3628,18 @@
         ffio_wfourcc(pb, "qt  ");
     else if (mov->mode == MODE_ISM) {
         ffio_wfourcc(pb, "piff");
-        ffio_wfourcc(pb, "iso2");
-    } else {
+    } else if (!(mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF)) {
         ffio_wfourcc(pb, "isom");
         ffio_wfourcc(pb, "iso2");
         if (has_h264)
             ffio_wfourcc(pb, "avc1");
     }
 
+    // We add tfdt atoms when fragmenting, signal this with the iso6 compatible
+    // brand. This is compatible with users that don't understand tfdt.
+    if (mov->flags & FF_MOV_FLAG_FRAGMENT && mov->mode != MODE_ISM)
+        ffio_wfourcc(pb, "iso6");
+
     if (mov->mode == MODE_3GP)
         ffio_wfourcc(pb, has_h264 ? "3gp6":"3gp4");
     else if (mov->mode & MODE_3G2)
@@ -3478,6 +3648,10 @@
         ffio_wfourcc(pb, "MSNV");
     else if (mov->mode == MODE_MP4)
         ffio_wfourcc(pb, "mp41");
+
+    if (mov->flags & FF_MOV_FLAG_DASH && mov->flags & FF_MOV_FLAG_FASTSTART)
+        ffio_wfourcc(pb, "dash");
+
     return update_size(pb, pos);
 }
 
@@ -3704,25 +3878,9 @@
         }
 
         if (write_moof) {
-            MOVFragmentInfo *info;
             avio_flush(s->pb);
-            track->nb_frag_info++;
-            if (track->nb_frag_info >= track->frag_info_capacity) {
-                unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT;
-                if (av_reallocp_array(&track->frag_info,
-                                      new_capacity,
-                                      sizeof(*track->frag_info)))
-                    return AVERROR(ENOMEM);
-                track->frag_info_capacity = new_capacity;
-            }
-            info = &track->frag_info[track->nb_frag_info - 1];
-            info->offset   = avio_tell(s->pb);
-            info->time     = track->frag_start;
-            info->duration = duration;
-            mov_write_tfrf_tags(s->pb, mov, track);
 
-            mov_write_moof_tag(s->pb, mov, moof_tracks);
-            info->tfrf_offset = track->tfrf_offset;
+            mov_write_moof_tag(s->pb, mov, moof_tracks, mdat_size);
             mov->fragments++;
 
             avio_wb32(s->pb, mdat_size + 8);
@@ -3754,7 +3912,7 @@
     MOVTrack *trk = &mov->tracks[pkt->stream_index];
     AVCodecContext *enc = trk->enc;
     unsigned int samples_in_chunk = 0;
-    int size = pkt->size;
+    int size = pkt->size, ret = 0;
     uint8_t *reformatted_data = NULL;
 
     if (trk->entry) {
@@ -3863,16 +4021,20 @@
         /* copy frame to create needed atoms */
         trk->vos_len  = size;
         trk->vos_data = av_malloc(size);
-        if (!trk->vos_data)
-            return AVERROR(ENOMEM);
+        if (!trk->vos_data) {
+            ret = AVERROR(ENOMEM);
+            goto err;
+        }
         memcpy(trk->vos_data, pkt->data, size);
     }
 
     if (trk->entry >= trk->cluster_capacity) {
         unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE);
         if (av_reallocp_array(&trk->cluster, new_capacity,
-                              sizeof(*trk->cluster)))
-            return AVERROR(ENOMEM);
+                              sizeof(*trk->cluster))) {
+            ret = AVERROR(ENOMEM);
+            goto err;
+        }
         trk->cluster_capacity = new_capacity;
     }
 
@@ -3883,18 +4045,39 @@
     trk->cluster[trk->entry].entries          = samples_in_chunk;
     trk->cluster[trk->entry].dts              = pkt->dts;
     if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) {
-        /* First packet of a new fragment. We already wrote the duration
-         * of the last packet of the previous fragment based on track_duration,
-         * which might not exactly match our dts. Therefore adjust the dts
-         * of this packet to be what the previous packets duration implies. */
-        trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
+        if (!trk->frag_discont) {
+            /* First packet of a new fragment. We already wrote the duration
+             * of the last packet of the previous fragment based on track_duration,
+             * which might not exactly match our dts. Therefore adjust the dts
+             * of this packet to be what the previous packets duration implies. */
+            trk->cluster[trk->entry].dts = trk->start_dts + trk->track_duration;
+        } else {
+            /* New fragment, but discontinuous from previous fragments.
+             * Pretend the duration sum of the earlier fragments is
+             * pkt->dts - trk->start_dts. */
+            trk->frag_start = pkt->dts - trk->start_dts;
+            trk->frag_discont = 0;
+        }
     }
-    if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !supports_edts(mov)) {
+
+    if (!trk->entry && trk->start_dts == AV_NOPTS_VALUE && !mov->use_editlist &&
+        s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
+        /* Not using edit lists and shifting the first track to start from zero.
+         * If the other streams start from a later timestamp, we won't be able
+         * to signal the difference in starting time without an edit list.
+         * Thus move the timestamp for this first sample to 0, increasing
+         * its duration instead. */
         trk->cluster[trk->entry].dts = trk->start_dts = 0;
     }
     if (trk->start_dts == AV_NOPTS_VALUE) {
         trk->start_dts = pkt->dts;
-        if (pkt->dts && mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
+        if (trk->frag_discont) {
+            /* Pretend the whole stream started at dts=0, with earlier framgents
+             * already written, with a duration summing up to pkt->dts. */
+            trk->frag_start   = pkt->dts;
+            trk->start_dts    = 0;
+            trk->frag_discont = 0;
+        } else if (pkt->dts && mov->flags & FF_MOV_FLAG_EMPTY_MOOV)
             av_log(s, AV_LOG_WARNING,
                    "Track %d starts with a nonzero dts %"PRId64". This "
                    "currently isn't handled correctly in combination with "
@@ -3932,9 +4115,12 @@
     if (trk->hint_track >= 0 && trk->hint_track < mov->nb_streams)
         ff_mov_add_hinted_packet(s, pkt, trk->hint_track, trk->entry,
                                  reformatted_data, size);
+
 end:
+err:
+
     av_free(reformatted_data);
-    return 0;
+    return ret;
 }
 
 static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt)
@@ -3948,6 +4134,13 @@
         if (!pkt->size)
             return 0;             /* Discard 0 sized packets */
 
+        if (mov->flags & FF_MOV_FLAG_FRAG_DISCONT) {
+            int i;
+            for (i = 0; i < s->nb_streams; i++)
+                mov->tracks[i].frag_discont = 1;
+            mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT;
+        }
+
         if (trk->entry && pkt->stream_index < s->nb_streams)
             frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts,
                                          s->streams[pkt->stream_index]->time_base,
@@ -4352,21 +4545,30 @@
     if (mov->mode == MODE_ISM)
         mov->flags |= FF_MOV_FLAG_EMPTY_MOOV | FF_MOV_FLAG_SEPARATE_MOOF |
                       FF_MOV_FLAG_FRAGMENT;
+    if (mov->flags & FF_MOV_FLAG_DASH)
+        mov->flags |= FF_MOV_FLAG_FRAGMENT | FF_MOV_FLAG_EMPTY_MOOV |
+                      FF_MOV_FLAG_DEFAULT_BASE_MOOF;
 
-    /* faststart: moov at the beginning of the file, if supported */
     if (mov->flags & FF_MOV_FLAG_FASTSTART) {
-        if ((mov->flags & FF_MOV_FLAG_FRAGMENT) ||
-            (s->flags & AVFMT_FLAG_CUSTOM_IO)) {
-            av_log(s, AV_LOG_WARNING, "The faststart flag is incompatible "
-                   "with fragmentation and custom IO, disabling faststart\n");
-            mov->flags &= ~FF_MOV_FLAG_FASTSTART;
-        } else
-            mov->reserved_moov_size = -1;
+        mov->reserved_moov_size = -1;
     }
 
-    if (!supports_edts(mov) && s->avoid_negative_ts < 0) {
-        s->avoid_negative_ts = 2;
+    if (mov->use_editlist < 0) {
+        mov->use_editlist = 1;
+        if (mov->flags & FF_MOV_FLAG_FRAGMENT) {
+            // If we can avoid needing an edit list by shifting the
+            // tracks, prefer that over (trying to) write edit lists
+            // in fragmented output.
+            if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO ||
+                s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)
+                mov->use_editlist = 0;
+        }
     }
+    if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && mov->use_editlist)
+        av_log(s, AV_LOG_WARNING, "No meaningful edit list will be written when using empty_moov\n");
+
+    if (!mov->use_editlist && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO)
+        s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_ZERO;
 
     /* Non-seekable output is ok if using fragmentation. If ism_lookahead
      * is enabled, we don't support non-seekable output at all. */
@@ -4647,6 +4849,8 @@
     if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV) {
         mov_write_moov_tag(pb, mov, s);
         mov->fragments++;
+        if (mov->flags & FF_MOV_FLAG_FASTSTART)
+            mov->reserved_moov_pos = avio_tell(pb);
     }
 
     return 0;
@@ -4667,6 +4871,18 @@
     return ffio_close_null_buf(moov_buf);
 }
 
+static int get_sidx_size(AVFormatContext *s)
+{
+    int ret;
+    AVIOContext *buf;
+    MOVMuxContext *mov = s->priv_data;
+
+    if ((ret = ffio_open_null_buf(&buf)) < 0)
+        return ret;
+    mov_write_sidx_tags(buf, mov, -1, 0);
+    return ffio_close_null_buf(buf);
+}
+
 /*
  * This function gets the moov size if moved to the top of the file: the chunk
  * offset table can switch between stco (32-bit entries) to co64 (64-bit
@@ -4698,6 +4914,21 @@
     return moov_size2;
 }
 
+static int compute_sidx_size(AVFormatContext *s)
+{
+    int i, sidx_size;
+    MOVMuxContext *mov = s->priv_data;
+
+    sidx_size = get_sidx_size(s);
+    if (sidx_size < 0)
+        return sidx_size;
+
+    for (i = 0; i < mov->nb_streams; i++)
+        mov->tracks[i].data_offset += sidx_size;
+
+    return sidx_size;
+}
+
 static int shift_data(AVFormatContext *s)
 {
     int ret = 0, moov_size;
@@ -4708,7 +4939,10 @@
     int read_size[2];
     AVIOContext *read_pb;
 
-    moov_size = compute_moov_size(s);
+    if (mov->flags & FF_MOV_FLAG_FRAGMENT)
+        moov_size = compute_sidx_size(s);
+    else
+        moov_size = compute_moov_size(s);
     if (moov_size < 0)
         return moov_size;
 
@@ -4815,7 +5049,7 @@
             av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n");
             res = shift_data(s);
             if (res == 0) {
-                avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET);
+                avio_seek(pb, mov->reserved_moov_pos, SEEK_SET);
                 mov_write_moov_tag(pb, mov, s);
             }
         } else if (mov->reserved_moov_size > 0) {
@@ -4835,7 +5069,21 @@
         }
     } else {
         mov_flush_fragment(s);
-        mov_write_mfra_tag(pb, mov);
+        for (i = 0; i < mov->nb_streams; i++)
+           mov->tracks[i].data_offset = 0;
+        if (mov->flags & FF_MOV_FLAG_FASTSTART) {
+            av_log(s, AV_LOG_INFO, "Starting second pass: inserting sidx atoms\n");
+            res = shift_data(s);
+            if (res == 0) {
+                int64_t end = avio_tell(pb);
+                avio_seek(pb, mov->reserved_moov_pos, SEEK_SET);
+                mov_write_sidx_tags(pb, mov, -1, 0);
+                avio_seek(pb, end, SEEK_SET);
+                mov_write_mfra_tag(pb, mov);
+            }
+        } else {
+            mov_write_mfra_tag(pb, mov);
+        }
     }
 
     for (i = 0; i < mov->nb_streams; i++) {
diff --git a/libavformat/movenc.h b/libavformat/movenc.h
index 4e7db7a..4cf6e3b 100644
--- a/libavformat/movenc.h
+++ b/libavformat/movenc.h
@@ -74,6 +74,7 @@
     int64_t time;
     int64_t duration;
     int64_t tfrf_offset;
+    int size;
 } MOVFragmentInfo;
 
 typedef struct MOVTrack {
@@ -128,7 +129,7 @@
     AVIOContext *mdat_buf;
     int64_t     data_offset;
     int64_t     frag_start;
-    int64_t     tfrf_offset;
+    int         frag_discont;
 
     int         nb_frag_info;
     MOVFragmentInfo *frag_info;
@@ -171,8 +172,8 @@
     int max_fragment_size;
     int ism_lookahead;
     AVIOContext *mdat_buf;
+    int first_trun;
 
-    int use_editlist;
     int video_track_timescale;
 
     int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise
@@ -182,18 +183,23 @@
 
     int per_stream_grouping;
     AVFormatContext *fc;
+
+    int use_editlist;
 } MOVMuxContext;
 
-#define FF_MOV_FLAG_RTP_HINT 1
-#define FF_MOV_FLAG_FRAGMENT 2
-#define FF_MOV_FLAG_EMPTY_MOOV 4
-#define FF_MOV_FLAG_FRAG_KEYFRAME 8
-#define FF_MOV_FLAG_SEPARATE_MOOF 16
-#define FF_MOV_FLAG_FRAG_CUSTOM 32
-#define FF_MOV_FLAG_ISML 64
-#define FF_MOV_FLAG_FASTSTART 128
-#define FF_MOV_FLAG_OMIT_TFHD_OFFSET 256
-#define FF_MOV_FLAG_DISABLE_CHPL 512
+#define FF_MOV_FLAG_RTP_HINT              (1 <<  0)
+#define FF_MOV_FLAG_FRAGMENT              (1 <<  1)
+#define FF_MOV_FLAG_EMPTY_MOOV            (1 <<  2)
+#define FF_MOV_FLAG_FRAG_KEYFRAME         (1 <<  3)
+#define FF_MOV_FLAG_SEPARATE_MOOF         (1 <<  4)
+#define FF_MOV_FLAG_FRAG_CUSTOM           (1 <<  5)
+#define FF_MOV_FLAG_ISML                  (1 <<  6)
+#define FF_MOV_FLAG_FASTSTART             (1 <<  7)
+#define FF_MOV_FLAG_OMIT_TFHD_OFFSET      (1 <<  8)
+#define FF_MOV_FLAG_DISABLE_CHPL          (1 <<  9)
+#define FF_MOV_FLAG_DEFAULT_BASE_MOOF     (1 << 10)
+#define FF_MOV_FLAG_DASH                  (1 << 11)
+#define FF_MOV_FLAG_FRAG_DISCONT          (1 << 12)
 
 int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);
 
diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c
index f617125..876e3a7 100644
--- a/libavformat/mp3dec.c
+++ b/libavformat/mp3dec.c
@@ -438,6 +438,10 @@
         int64_t pos = ie->pos + (dir > 0 ? i - 1024 : -i);
         int64_t candidate = -1;
         int score = 999;
+
+        if (pos < 0)
+            continue;
+
         for(j=0; j<MIN_VALID; j++) {
             ret = check(s, pos);
             if(ret < 0)
diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c
index a691f75..d4b6af0 100644
--- a/libavformat/mp3enc.c
+++ b/libavformat/mp3enc.c
@@ -58,7 +58,7 @@
     count += id3v1_set_string(s, "TIT2",    buf +  3, 30 + 1);       //title
     count += id3v1_set_string(s, "TPE1",    buf + 33, 30 + 1);       //author|artist
     count += id3v1_set_string(s, "TALB",    buf + 63, 30 + 1);       //album
-    count += id3v1_set_string(s, "TDRL",    buf + 93,  4 + 1);       //date
+    count += id3v1_set_string(s, "TDRC",    buf + 93,  4 + 1);       //date
     count += id3v1_set_string(s, "comment", buf + 97, 30 + 1);
     if ((tag = av_dict_get(s->metadata, "TRCK", NULL, 0))) { //track
         buf[125] = 0;
diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c
index e8e1b08..827a3c2 100644
--- a/libavformat/mpeg.c
+++ b/libavformat/mpeg.c
@@ -697,12 +697,16 @@
     memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3);
     av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->filename, sub_name);
 
-    if (!(iformat = av_find_input_format("mpeg")))
-        return AVERROR_DEMUXER_NOT_FOUND;
+    if (!(iformat = av_find_input_format("mpeg"))) {
+        ret = AVERROR_DEMUXER_NOT_FOUND;
+        goto end;
+    }
 
     vobsub->sub_ctx = avformat_alloc_context();
-    if (!vobsub->sub_ctx)
-        return AVERROR(ENOMEM);
+    if (!vobsub->sub_ctx) {
+        ret = AVERROR(ENOMEM);
+        goto end;
+    }
 
     if ((ret = ff_copy_whitelists(vobsub->sub_ctx, s)) < 0)
         goto end;
diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c
index d3af9e1..b151506 100644
--- a/libavformat/mpegenc.c
+++ b/libavformat/mpegenc.c
@@ -1080,8 +1080,10 @@
         es_size              -= stream->premux_packet->unwritten_size;
         stream->premux_packet = stream->premux_packet->next;
     }
-    if (es_size)
+    if (es_size) {
+        av_assert0(stream->premux_packet);
         stream->premux_packet->unwritten_size -= es_size;
+    }
 
     if (remove_decoded_packets(ctx, s->last_scr) < 0)
         return -1;
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index c01f954..97da0a3 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -141,6 +141,8 @@
     int skip_changes;
     int skip_clear;
 
+    int scan_all_pmts;
+
     int resync_size;
 
     /******************************************/
@@ -165,6 +167,8 @@
      {.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM },
     {"ts_packetsize", "Output option carrying the raw packet size.", offsetof(MpegTSContext, raw_packet_size), AV_OPT_TYPE_INT,
      {.i64 = 0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
+    {"scan_all_pmts",   "Scan and combine all PMTs", offsetof(MpegTSContext, scan_all_pmts), AV_OPT_TYPE_INT,
+     { .i64 =  -1}, -1, 1,  AV_OPT_FLAG_DECODING_PARAM },
     {"skip_changes", "Skip changing / adding streams / programs.", offsetof(MpegTSContext, skip_changes), AV_OPT_TYPE_INT,
      {.i64 = 0}, 0, 1, 0 },
     {"skip_clear", "Skip clearing programs.", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_INT,
@@ -299,11 +303,17 @@
                            unsigned int pid)
 {
     struct Program *p = get_program(ts, programid);
+    int i;
     if (!p)
         return;
 
     if (p->nb_pids >= MAX_PIDS_PER_PROGRAM)
         return;
+
+    for (i = 0; i < p->nb_pids; i++)
+        if (p->pids[i] == pid)
+            return;
+
     p->pids[p->nb_pids++] = pid;
 }
 
@@ -1792,15 +1802,17 @@
     if (parse_section_header(h, &p, p_end) < 0)
         return;
 
-    av_dlog(ts->stream, "sid=0x%x sec_num=%d/%d\n",
-            h->id, h->sec_num, h->last_sec_num);
+    av_dlog(ts->stream, "sid=0x%x sec_num=%d/%d version=%d\n",
+            h->id, h->sec_num, h->last_sec_num, h->version);
 
     if (h->tid != PMT_TID)
         return;
-    if (ts->skip_changes)
+    if (!ts->scan_all_pmts && ts->skip_changes)
         return;
 
-    clear_program(ts, h->id);
+    if (!ts->skip_clear)
+        clear_program(ts, h->id);
+
     pcr_pid = get16(&p, p_end);
     if (pcr_pid < 0)
         return;
@@ -2188,14 +2200,19 @@
 
         // stop find_stream_info from waiting for more streams
         // when all programs have received a PMT
-        if (ts->stream->ctx_flags & AVFMTCTX_NOHEADER) {
+        if (ts->stream->ctx_flags & AVFMTCTX_NOHEADER && ts->scan_all_pmts <= 0) {
             int i;
             for (i = 0; i < ts->nb_prg; i++) {
                 if (!ts->prg[i].pmt_found)
                     break;
             }
             if (i == ts->nb_prg && ts->nb_prg > 0) {
-                if (ts->stream->nb_streams > 1 || pos > 100000) {
+                int types = 0;
+                for (i = 0; i < ts->stream->nb_streams; i++) {
+                    AVStream *st = ts->stream->streams[i];
+                    types |= 1<<st->codec->codec_type;
+                }
+                if ((types & (1<<AVMEDIA_TYPE_AUDIO) && types & (1<<AVMEDIA_TYPE_VIDEO)) || pos > 100000) {
                     av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n");
                     ts->stream->ctx_flags &= ~AVFMTCTX_NOHEADER;
                 }
diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index d73b75f..7670fc6 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -1438,7 +1438,7 @@
       { .i64 = 0x1000 }, 0x0010, 0x1f00, AV_OPT_FLAG_ENCODING_PARAM },
     { "mpegts_start_pid", "Set the first pid.",
       offsetof(MpegTSWrite, start_pid), AV_OPT_TYPE_INT,
-      { .i64 = 0x0100 }, 0x0100, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
+      { .i64 = 0x0100 }, 0x0020, 0x0f00, AV_OPT_FLAG_ENCODING_PARAM },
     { "mpegts_m2ts_mode", "Enable m2ts mode.",
       offsetof(MpegTSWrite, m2ts_mode), AV_OPT_TYPE_INT,
       { .i64 = -1 }, -1, 1, AV_OPT_FLAG_ENCODING_PARAM },
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 54da2e7..8111f77 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -199,7 +199,7 @@
     }
     if (id != AV_CODEC_ID_NONE)
         return 0;
-    if (tag >= 0 && (st->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL))
+    if (tag >= 0 && (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL))
         return 0;
     return 1;
 }
@@ -423,10 +423,11 @@
         return ret;
 
     if (s->avoid_negative_ts < 0) {
+        av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
         if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
             s->avoid_negative_ts = 0;
         } else
-            s->avoid_negative_ts = 1;
+            s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
     }
 
     return 0;
@@ -576,12 +577,13 @@
         AVStream *st = s->streams[pkt->stream_index];
         int64_t offset = st->mux_ts_offset;
 
-        if ((pkt->dts < 0 || s->avoid_negative_ts == 2) && pkt->dts != AV_NOPTS_VALUE && !s->offset) {
+        if (s->offset == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE &&
+            (pkt->dts < 0 || s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)) {
             s->offset = -pkt->dts;
             s->offset_timebase = st->time_base;
         }
 
-        if (s->offset && !offset) {
+        if (s->offset != AV_NOPTS_VALUE && !offset) {
             offset = st->mux_ts_offset =
                 av_rescale_q_rnd(s->offset,
                                  s->offset_timebase,
@@ -597,8 +599,9 @@
         av_assert2(pkt->dts == AV_NOPTS_VALUE || pkt->dts >= 0 || s->max_interleave_delta > 0);
         if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) {
             av_log(s, AV_LOG_WARNING,
-                   "Packets poorly interleaved, failed to avoid negative timestamp %s in stream %d\n"
-                   "try -max_interleave_delta 0 as a possible workaround\n",
+                   "Packets poorly interleaved, failed to avoid negative "
+                   "timestamp %s in stream %d.\n"
+                   "Try -max_interleave_delta 0 as a possible workaround.\n",
                    av_ts2str(pkt->dts),
                    pkt->stream_index
             );
@@ -943,7 +946,7 @@
     for (;; ) {
         AVPacket pkt;
         ret = interleave_packet(s, &pkt, NULL, 1);
-        if (ret < 0) //FIXME cleanup needed for ret<0 ?
+        if (ret < 0)
             goto fail;
         if (!ret)
             break;
@@ -960,10 +963,14 @@
             goto fail;
     }
 
-    if (s->oformat->write_trailer)
-        ret = s->oformat->write_trailer(s);
-
 fail:
+    if (s->oformat->write_trailer)
+        if (ret >= 0) {
+        ret = s->oformat->write_trailer(s);
+        } else {
+            s->oformat->write_trailer(s);
+        }
+
     if (s->pb)
        avio_flush(s->pb);
     if (ret == 0)
diff --git a/libavformat/mxf.c b/libavformat/mxf.c
index 4dc54d7..14d143e 100644
--- a/libavformat/mxf.c
+++ b/libavformat/mxf.c
@@ -94,6 +94,7 @@
     {AV_PIX_FMT_RGB565BE,{'R', 5,  'G', 6,  'B', 5                         }},
     {AV_PIX_FMT_RGBA,    {'R', 8,  'G', 8,  'B', 8, 'A', 8                 }},
     {AV_PIX_FMT_PAL8,    {'P', 8                                           }},
+    {AV_PIX_FMT_GRAY8,   {'A', 8                                           }},
 };
 
 static const int num_pixel_layouts = FF_ARRAY_ELEMS(ff_mxf_pixel_layouts);
diff --git a/libavformat/mxf.h b/libavformat/mxf.h
index 5b95efa..d9e17c6 100644
--- a/libavformat/mxf.h
+++ b/libavformat/mxf.h
@@ -46,6 +46,7 @@
     IndexTableSegment,
     EssenceContainerData,
     TypeBottom,// add metadata type before this
+    EssenceGroup,
 };
 
 enum MXFFrameLayout {
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index b533e2a..0c88a8a 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -136,6 +136,14 @@
 typedef struct {
     UID uid;
     enum MXFMetadataSetType type;
+    UID *structural_components_refs;
+    int structural_components_count;
+    int64_t duration;
+} MXFEssenceGroup;
+
+typedef struct {
+    UID uid;
+    enum MXFMetadataSetType type;
     MXFSequence *sequence; /* mandatory, and only one */
     UID sequence_ref;
     int track_id;
@@ -161,6 +169,7 @@
     int field_dominance;
     int channels;
     int bits_per_sample;
+    int64_t duration; /* ContainerDuration optional property */
     unsigned int component_depth;
     unsigned int horiz_subsampling;
     unsigned int vert_subsampling;
@@ -668,22 +677,6 @@
     return 0;
 }
 
-static int mxf_read_material_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
-{
-    MXFPackage *package = arg;
-    switch(tag) {
-    case 0x4403:
-        package->tracks_count = avio_rb32(pb);
-        package->tracks_refs = av_calloc(package->tracks_count, sizeof(UID));
-        if (!package->tracks_refs)
-            return AVERROR(ENOMEM);
-        avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
-        avio_read(pb, (uint8_t *)package->tracks_refs, package->tracks_count * sizeof(UID));
-        break;
-    }
-    return 0;
-}
-
 static int mxf_read_timecode_component(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
 {
     MXFTimecodeComponent *mxf_timecode = arg;
@@ -749,8 +742,10 @@
     case 0x1001:
         sequence->structural_components_count = avio_rb32(pb);
         sequence->structural_components_refs = av_calloc(sequence->structural_components_count, sizeof(UID));
-        if (!sequence->structural_components_refs)
+        if (!sequence->structural_components_refs) {
+            sequence->structural_components_count = 0;
             return AVERROR(ENOMEM);
+        }
         avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
         avio_read(pb, (uint8_t *)sequence->structural_components_refs, sequence->structural_components_count * sizeof(UID));
         break;
@@ -758,6 +753,27 @@
     return 0;
 }
 
+static int mxf_read_essence_group(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
+{
+    MXFEssenceGroup *essence_group = arg;
+    switch (tag) {
+    case 0x0202:
+        essence_group->duration = avio_rb64(pb);
+        break;
+    case 0x0501:
+        essence_group->structural_components_count = avio_rb32(pb);
+        essence_group->structural_components_refs = av_calloc(essence_group->structural_components_count, sizeof(UID));
+        if (!essence_group->structural_components_refs) {
+            essence_group->structural_components_count = 0;
+            return AVERROR(ENOMEM);
+        }
+        avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
+        avio_read(pb, (uint8_t *)essence_group->structural_components_refs, essence_group->structural_components_count * sizeof(UID));
+        break;
+    }
+    return 0;
+}
+
 static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str)
 {
     int ret;
@@ -779,7 +795,7 @@
     return ret;
 }
 
-static int mxf_read_source_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
+static int mxf_read_package(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
 {
     MXFPackage *package = arg;
     switch(tag) {
@@ -888,7 +904,6 @@
 static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset)
 {
     MXFDescriptor *descriptor = arg;
-    descriptor->pix_fmt = AV_PIX_FMT_NONE;
     switch(tag) {
     case 0x3F01:
         descriptor->sub_descriptors_count = avio_rb32(pb);
@@ -898,6 +913,9 @@
         avio_skip(pb, 4); /* useless size of objects, always 16 according to specs */
         avio_read(pb, (uint8_t *)descriptor->sub_descriptors_refs, descriptor->sub_descriptors_count * sizeof(UID));
         break;
+    case 0x3002: /* ContainerDuration */
+        descriptor->duration = avio_rb64(pb);
+        break;
     case 0x3004:
         avio_read(pb, descriptor->essence_container_ul, 16);
         break;
@@ -1010,6 +1028,7 @@
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14,    AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Uncompressed Picture */
+    { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,      AV_CODEC_ID_NONE },
 };
 
@@ -1416,6 +1435,34 @@
                             &descriptor->essence_codec_ul)->id     != AV_CODEC_ID_NONE;
 }
 
+static int mxf_uid_to_str(UID uid, char **str)
+{
+    int i;
+    char *p;
+    p = *str = av_mallocz(sizeof(UID) * 2 + 4 + 1);
+    if (!p)
+        return AVERROR(ENOMEM);
+    for (i = 0; i < sizeof(UID); i++) {
+        snprintf(p, 2 + 1, "%.2x", uid[i]);
+        p += 2;
+        if (i == 3 || i == 5 || i == 7 || i == 9) {
+            snprintf(p, 1 + 1, "-");
+            p++;
+        }
+    }
+    return 0;
+}
+
+static int mxf_add_uid_metadata(AVDictionary **pm, const char *key, UID uid)
+{
+    char *str;
+    int ret;
+    if ((ret = mxf_uid_to_str(uid, &str)) < 0)
+        return ret;
+    av_dict_set(pm, key, str, AV_DICT_DONT_STRDUP_VAL);
+    return 0;
+}
+
 static int mxf_add_timecode_metadata(AVDictionary **pm, const char *key, AVTimecode *tc)
 {
     char buf[AV_TIMECODE_STR_SIZE];
@@ -1424,38 +1471,113 @@
     return 0;
 }
 
+static MXFTimecodeComponent* mxf_resolve_timecode_component(MXFContext *mxf, UID *strong_ref)
+{
+    MXFStructuralComponent *component = NULL;
+    MXFPulldownComponent *pulldown = NULL;
+
+    component = mxf_resolve_strong_ref(mxf, strong_ref, AnyType);
+    if (!component)
+        return NULL;
+
+    switch (component->type) {
+    case TimecodeComponent:
+        return (MXFTimecodeComponent*)component;
+    case PulldownComponent: /* timcode component may be located on a pulldown component */
+        pulldown = (MXFPulldownComponent*)component;
+        return mxf_resolve_strong_ref(mxf, &pulldown->input_segment_ref, TimecodeComponent);
+    default:
+        break;
+    }
+    return NULL;
+}
+
+static MXFPackage* mxf_resolve_source_package(MXFContext *mxf, UID package_uid)
+{
+    MXFPackage *package = NULL;
+    int i;
+
+    for (i = 0; i < mxf->packages_count; i++) {
+        package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[i], SourcePackage);
+        if (!package)
+            continue;
+
+        if (!memcmp(package->package_uid, package_uid, 16))
+            return package;
+    }
+    return NULL;
+}
+
+static MXFStructuralComponent* mxf_resolve_essence_group_choice(MXFContext *mxf, MXFEssenceGroup *essence_group)
+{
+    MXFStructuralComponent *component = NULL;
+    MXFPackage *package = NULL;
+    MXFDescriptor *descriptor = NULL;
+    int i;
+
+    if (!essence_group || !essence_group->structural_components_count)
+        return NULL;
+
+    /* essence groups contains multiple representations of the same media,
+       this return the first components with a valid Descriptor typically index 0 */
+    for (i =0; i < essence_group->structural_components_count; i++){
+        component = mxf_resolve_strong_ref(mxf, &essence_group->structural_components_refs[i], SourceClip);
+        if (!component)
+            continue;
+
+        if (!(package = mxf_resolve_source_package(mxf, component->source_package_uid)))
+            continue;
+
+        descriptor = mxf_resolve_strong_ref(mxf, &package->descriptor_ref, Descriptor);
+        if (descriptor){
+            /* HACK: force the duration of the component to match the duration of the descriptor */
+            if (descriptor->duration != AV_NOPTS_VALUE)
+                component->duration = descriptor->duration;
+            return component;
+        }
+    }
+    return NULL;
+}
+
+static MXFStructuralComponent* mxf_resolve_sourceclip(MXFContext *mxf, UID *strong_ref)
+{
+    MXFStructuralComponent *component = NULL;
+
+    component = mxf_resolve_strong_ref(mxf, strong_ref, AnyType);
+    if (!component)
+        return NULL;
+    switch (component->type) {
+        case SourceClip:
+            return component;
+        case EssenceGroup:
+            return mxf_resolve_essence_group_choice(mxf, (MXFEssenceGroup*) component);
+        default:
+            break;
+    }
+    return NULL;
+}
+
 static int mxf_parse_physical_source_package(MXFContext *mxf, MXFTrack *source_track, AVStream *st)
 {
-    MXFPackage *temp_package = NULL;
     MXFPackage *physical_package = NULL;
     MXFTrack *physical_track = NULL;
-    MXFStructuralComponent *component = NULL;
     MXFStructuralComponent *sourceclip = NULL;
     MXFTimecodeComponent *mxf_tc = NULL;
-    MXFPulldownComponent *mxf_pulldown = NULL;
     int i, j, k;
     AVTimecode tc;
     int flags;
     int64_t start_position;
 
     for (i = 0; i < source_track->sequence->structural_components_count; i++) {
-        component = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
-        if (!component)
+        sourceclip = mxf_resolve_strong_ref(mxf, &source_track->sequence->structural_components_refs[i], SourceClip);
+        if (!sourceclip)
             continue;
 
-        for (j = 0; j < mxf->packages_count; j++) {
-            temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[j], SourcePackage);
-            if (!temp_package)
-                continue;
-            if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)){
-                physical_package = temp_package;
-                sourceclip = component;
-                break;
-            }
-        }
-        if (!physical_package)
+        if (!(physical_package = mxf_resolve_source_package(mxf, sourceclip->source_package_uid)))
             break;
 
+        mxf_add_uid_metadata(&st->metadata, "reel_uid", physical_package->package_uid);
+
         /* the name of physical source package is name of the reel or tape */
         if (physical_package->name && physical_package->name[0])
             av_dict_set(&st->metadata, "reel_name", physical_package->name, 0);
@@ -1475,19 +1597,9 @@
             }
 
             for (k = 0; k < physical_track->sequence->structural_components_count; k++) {
-                component = mxf_resolve_strong_ref(mxf, &physical_track->sequence->structural_components_refs[k], TimecodeComponent);
-                if (!component){
-                    /* timcode component may be located on a pulldown component */
-                    component = mxf_resolve_strong_ref(mxf, &physical_track->sequence->structural_components_refs[k], PulldownComponent);
-                    if (!component)
-                        continue;
-                    mxf_pulldown = (MXFPulldownComponent*)component;
-                    component = mxf_resolve_strong_ref(mxf, &mxf_pulldown->input_segment_ref, TimecodeComponent);
-                    if (!component)
-                        continue;
-                }
+                if (!(mxf_tc = mxf_resolve_timecode_component(mxf, &physical_track->sequence->structural_components_refs[k])))
+                    continue;
 
-                mxf_tc = (MXFTimecodeComponent*)component;
                 flags = mxf_tc->drop_frame == 1 ? AV_TIMECODE_FLAG_DROPFRAME : 0;
                 /* scale sourceclip start_position to match physical track edit rate */
                 start_position = av_rescale_q(sourceclip->start_position,
@@ -1508,7 +1620,6 @@
 static int mxf_parse_structural_metadata(MXFContext *mxf)
 {
     MXFPackage *material_package = NULL;
-    MXFPackage *temp_package = NULL;
     int i, j, k, ret;
 
     av_dlog(mxf->fc, "metadata sets count %d\n", mxf->metadata_sets_count);
@@ -1522,6 +1633,10 @@
         return AVERROR_INVALIDDATA;
     }
 
+    mxf_add_uid_metadata(&mxf->fc->metadata, "material_package_uid", material_package->package_uid);
+    if (material_package->name && material_package->name[0])
+        av_dict_set(&mxf->fc->metadata, "material_package_name", material_package->name, 0);
+
     for (i = 0; i < material_package->tracks_count; i++) {
         MXFPackage *source_package = NULL;
         MXFTrack *material_track = NULL;
@@ -1571,19 +1686,11 @@
 
         /* TODO: handle multiple source clips */
         for (j = 0; j < material_track->sequence->structural_components_count; j++) {
-            component = mxf_resolve_strong_ref(mxf, &material_track->sequence->structural_components_refs[j], SourceClip);
+            component = mxf_resolve_sourceclip(mxf, &material_track->sequence->structural_components_refs[j]);
             if (!component)
                 continue;
 
-            for (k = 0; k < mxf->packages_count; k++) {
-                temp_package = mxf_resolve_strong_ref(mxf, &mxf->packages_refs[k], SourcePackage);
-                if (!temp_package)
-                    continue;
-                if (!memcmp(temp_package->package_uid, component->source_package_uid, 16)) {
-                    source_package = temp_package;
-                    break;
-                }
-            }
+            source_package = mxf_resolve_source_package(mxf, component->source_package_uid);
             if (!source_package) {
                 av_dlog(mxf->fc, "material track %d: no corresponding source package found\n", material_track->track_id);
                 break;
@@ -1702,6 +1809,10 @@
         }
         av_log(mxf->fc, AV_LOG_VERBOSE, "\n");
 
+        mxf_add_uid_metadata(&st->metadata, "file_package_uid", source_package->package_uid);
+        if (source_package->name && source_package->name[0])
+            av_dict_set(&st->metadata, "file_package_name", source_package->name, 0);
+
         mxf_parse_physical_source_package(mxf, source_track, st);
 
         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -1739,6 +1850,7 @@
                         avpriv_request_sample(mxf->fc,
                                               "Field dominance %d support",
                                               descriptor->field_dominance);
+                    case 0: // we already have many samples with field_dominance == unknown
                         break;
                     }
                     /* Turn field height into frame height. */
@@ -1771,6 +1883,8 @@
             if (source_track->sequence->origin) {
                 av_dict_set_int(&st->metadata, "source_track_origin", source_track->sequence->origin, 0);
             }
+            if (descriptor->aspect_ratio.num && descriptor->aspect_ratio.den)
+                st->display_aspect_ratio = descriptor->aspect_ratio;
         } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
             container_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
             /* Only overwrite existing codec ID if it is unset or A-law, which is the default according to SMPTE RP 224. */
@@ -1839,24 +1953,6 @@
     return ret;
 }
 
-static int mxf_uid_to_str(UID uid, char **str)
-{
-    int i;
-    char *p;
-    p = *str = av_mallocz(sizeof(UID) * 2 + 4 + 1);
-    if (!p)
-        return AVERROR(ENOMEM);
-    for (i = 0; i < sizeof(UID); i++) {
-        snprintf(p, 2 + 1, "%.2x", uid[i]);
-        p += 2;
-        if (i == 3 || i == 5 || i == 7 || i == 9) {
-            snprintf(p, 1 + 1, "-");
-            p++;
-        }
-    }
-    return 0;
-}
-
 static int mxf_timestamp_to_str(uint64_t timestamp, char **str)
 {
     struct tm time = { 0 };
@@ -1956,9 +2052,10 @@
     { { 0x06,0x0e,0x2b,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType },
-    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage },
-    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage },
+    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_package, sizeof(MXFPackage), SourcePackage },
+    { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_package, sizeof(MXFPackage), MaterialPackage },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x0f,0x00 }, mxf_read_sequence, sizeof(MXFSequence), Sequence },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x05,0x00 }, mxf_read_essence_group, sizeof(MXFEssenceGroup), EssenceGroup},
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x11,0x00 }, mxf_read_source_clip, sizeof(MXFStructuralComponent), SourceClip },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x44,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), MultipleDescriptor },
     { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x42,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* Generic Sound */
@@ -1979,6 +2076,20 @@
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, 0, AnyType },
 };
 
+static int mxf_metadataset_init(MXFMetadataSet *ctx, enum MXFMetadataSetType type)
+{
+    switch (type){
+    case MultipleDescriptor:
+    case Descriptor:
+        ((MXFDescriptor*)ctx)->pix_fmt = AV_PIX_FMT_NONE;
+        ((MXFDescriptor*)ctx)->duration = AV_NOPTS_VALUE;
+        break;
+    default:
+        break;
+    }
+    return 0;
+}
+
 static int mxf_read_local_tags(MXFContext *mxf, KLVPacket *klv, MXFMetadataReadFunc *read_child, int ctx_size, enum MXFMetadataSetType type)
 {
     AVIOContext *pb = mxf->fc->pb;
@@ -1987,6 +2098,7 @@
 
     if (!ctx)
         return AVERROR(ENOMEM);
+    mxf_metadataset_init(ctx, type);
     while (avio_tell(pb) + 4 < klv_end && !avio_feof(pb)) {
         int ret;
         int tag = avio_rb16(pb);
@@ -2609,7 +2721,7 @@
             pkt->stream_index = index;
             pkt->pos = klv.offset;
 
-            codec = s->streams[index]->codec;
+            codec = st->codec;
 
             if (codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) {
                 /* mxf->current_edit_unit good - see if we have an
@@ -2724,6 +2836,9 @@
         case Sequence:
             av_freep(&((MXFSequence *)mxf->metadata_sets[i])->structural_components_refs);
             break;
+        case EssenceGroup:
+            av_freep(&((MXFEssenceGroup *)mxf->metadata_sets[i])->structural_components_refs);
+            break;
         case SourcePackage:
         case MaterialPackage:
             av_freep(&((MXFPackage *)mxf->metadata_sets[i])->tracks_refs);
diff --git a/libavformat/nut.c b/libavformat/nut.c
index 9224a96..86a0301 100644
--- a/libavformat/nut.c
+++ b/libavformat/nut.c
@@ -40,6 +40,7 @@
 };
 
 const AVCodecTag ff_nut_video_tags[] = {
+    { AV_CODEC_ID_XFACE,            MKTAG('X', 'F', 'A', 'C') },
     { AV_CODEC_ID_VP9,              MKTAG('V', 'P', '9', '0') },
     { AV_CODEC_ID_RAWVIDEO,         MKTAG('R', 'G', 'B', 15 ) },
     { AV_CODEC_ID_RAWVIDEO,         MKTAG('B', 'G', 'R', 15 ) },
diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c
index fbbe320..dda229e 100644
--- a/libavformat/oggenc.c
+++ b/libavformat/oggenc.c
@@ -307,12 +307,10 @@
                                   OGGStreamContext *oggstream, int bitexact,
                                   AVDictionary **m)
 {
-    enum FLACExtradataFormat format;
-    uint8_t *streaminfo;
     uint8_t *p;
 
-    if (!avpriv_flac_is_extradata_valid(avctx, &format, &streaminfo))
-        return -1;
+    if (avctx->extradata_size < FLAC_STREAMINFO_SIZE)
+        return AVERROR(EINVAL);
 
     // first packet: STREAMINFO
     oggstream->header_len[0] = 51;
@@ -328,7 +326,7 @@
     bytestream_put_buffer(&p, "fLaC", 4);
     bytestream_put_byte(&p, 0x00); // streaminfo
     bytestream_put_be24(&p, 34);
-    bytestream_put_buffer(&p, streaminfo, FLAC_STREAMINFO_SIZE);
+    bytestream_put_buffer(&p, avctx->extradata, FLAC_STREAMINFO_SIZE);
 
     // second packet: VorbisComment
     p = ogg_write_vorbiscomment(4, bitexact, &oggstream->header_len[1], m, 0);
diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c
index 9f0f808..c7fb446 100644
--- a/libavformat/oggparseflac.c
+++ b/libavformat/oggparseflac.c
@@ -34,7 +34,6 @@
     struct ogg_stream *os = ogg->streams + idx;
     AVStream *st = s->streams[idx];
     GetBitContext gb;
-    FLACStreaminfo si;
     int mdt;
 
     if (os->buf[os->pstart] == 0xff)
@@ -46,6 +45,8 @@
 
     if (mdt == OGG_FLAC_METADATA_TYPE_STREAMINFO) {
         uint8_t *streaminfo_start = os->buf + os->pstart + 5 + 4 + 4 + 4;
+        uint32_t samplerate;
+
         skip_bits_long(&gb, 4*8); /* "FLAC" */
         if(get_bits(&gb, 8) != 1) /* unsupported major version */
             return -1;
@@ -56,8 +57,6 @@
         if (get_bits_long(&gb, 32) != FLAC_STREAMINFO_SIZE)
             return -1;
 
-        avpriv_flac_parse_streaminfo(st->codec, &si, streaminfo_start);
-
         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
         st->codec->codec_id = AV_CODEC_ID_FLAC;
         st->need_parsing = AVSTREAM_PARSE_HEADERS;
@@ -66,7 +65,11 @@
             return AVERROR(ENOMEM);
         memcpy(st->codec->extradata, streaminfo_start, st->codec->extradata_size);
 
-        avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
+        samplerate = AV_RB24(st->codec->extradata + 10) >> 4;
+        if (!samplerate)
+            return AVERROR_INVALIDDATA;
+
+        avpriv_set_pts_info(st, 64, 1, samplerate);
     } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
         ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 4, os->psize - 4);
     }
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 5e34be5..dd44337 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -213,7 +213,7 @@
 struct oggvorbis_private {
     unsigned int len[3];
     unsigned char *packet[3];
-    VorbisParseContext vp;
+    AVVorbisParseContext *vp;
     int64_t final_pts;
     int final_duration;
 };
@@ -253,9 +253,11 @@
     struct ogg_stream *os = ogg->streams + idx;
     struct oggvorbis_private *priv = os->private;
     int i;
-    if (os->private)
+    if (os->private) {
+        av_vorbis_parse_free(&priv->vp);
         for (i = 0; i < 3; i++)
             av_freep(&priv->packet[i]);
+    }
 }
 
 static int vorbis_update_metadata(AVFormatContext *s, int idx)
@@ -302,14 +304,14 @@
             return AVERROR(ENOMEM);
     }
 
+    priv = os->private;
+
     if (!(pkt_type & 1))
-        return 0;
+        return priv->vp ? 0 : AVERROR_INVALIDDATA;
 
     if (os->psize < 1 || pkt_type > 5)
         return AVERROR_INVALIDDATA;
 
-    priv = os->private;
-
     if (priv->packet[pkt_type >> 1])
         return AVERROR_INVALIDDATA;
     if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
@@ -385,10 +387,12 @@
             return ret;
         }
         st->codec->extradata_size = ret;
-        if ((ret = avpriv_vorbis_parse_extradata(st->codec, &priv->vp))) {
+
+        priv->vp = av_vorbis_parse_init(st->codec->extradata, st->codec->extradata_size);
+        if (!priv->vp) {
             av_freep(&st->codec->extradata);
             st->codec->extradata_size = 0;
-            return ret;
+            return AVERROR_UNKNOWN;
         }
     }
 
@@ -411,10 +415,10 @@
         uint8_t *last_pkt  = os->buf + os->pstart;
         uint8_t *next_pkt  = last_pkt;
 
-        avpriv_vorbis_parse_reset(&priv->vp);
+        av_vorbis_parse_reset(priv->vp);
         duration = 0;
         seg = os->segp;
-        d = avpriv_vorbis_parse_frame_flags(&priv->vp, last_pkt, 1, &flags);
+        d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &flags);
         if (d < 0) {
             os->pflags |= AV_PKT_FLAG_CORRUPT;
             return 0;
@@ -426,7 +430,7 @@
         last_pkt = next_pkt =  next_pkt + os->psize;
         for (; seg < os->nsegs; seg++) {
             if (os->segments[seg] < 255) {
-                int d = avpriv_vorbis_parse_frame_flags(&priv->vp, last_pkt, 1, &flags);
+                int d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &flags);
                 if (d < 0) {
                     duration = os->granule;
                     break;
@@ -451,12 +455,12 @@
                 s->streams[idx]->duration -= s->streams[idx]->start_time;
         }
         priv->final_pts          = AV_NOPTS_VALUE;
-        avpriv_vorbis_parse_reset(&priv->vp);
+        av_vorbis_parse_reset(priv->vp);
     }
 
     /* parse packet duration */
     if (os->psize > 0) {
-        duration = avpriv_vorbis_parse_frame_flags(&priv->vp, os->buf + os->pstart, 1, &flags);
+        duration = av_vorbis_parse_frame_flags(priv->vp, os->buf + os->pstart, 1, &flags);
         if (duration < 0) {
             os->pflags |= AV_PKT_FLAG_CORRUPT;
             return 0;
diff --git a/libavformat/options.c b/libavformat/options.c
index e0d6df6..5044043 100644
--- a/libavformat/options.c
+++ b/libavformat/options.c
@@ -110,6 +110,7 @@
     ic = av_malloc(sizeof(AVFormatContext));
     if (!ic) return ic;
     avformat_get_context_defaults(ic);
+    ic->offset = AV_NOPTS_VALUE;
 
     ic->internal = av_mallocz(sizeof(*ic->internal));
     if (!ic->internal) {
diff --git a/libavformat/options_table.h b/libavformat/options_table.h
index 5ac3fba..40f1e0a 100644
--- a/libavformat/options_table.h
+++ b/libavformat/options_table.h
@@ -78,11 +78,6 @@
 {"compliant",  "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"},
 {"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"},
 {"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D},
-{"avoid_negative_ts", "shift timestamps so they start at 0", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, E, "avoid_negative_ts"},
-{"auto",                "enabled when required by target format",    0, AV_OPT_TYPE_CONST, {.i64 = -1 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
-{"disabled",            "do not change timestamps",                  0, AV_OPT_TYPE_CONST, {.i64 =  0 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
-{"make_zero",           "shift timestamps so they start at 0",       0, AV_OPT_TYPE_CONST, {.i64 =  2 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
-{"make_non_negative",   "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 =  1 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
 {"skip_initial_bytes", "set number of bytes to skip before reading header and frames", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX-1, D},
 {"correct_ts_overflow", "correct single timestamp overflows", OFFSET(correct_ts_overflow), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, D},
 {"flush_packets", "enable flushing of the I/O context after each packet", OFFSET(flush_packets), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E},
@@ -96,6 +91,11 @@
 {"unofficial", "allow unofficial extensions", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_UNOFFICIAL }, INT_MIN, INT_MAX, D|E, "strict"},
 {"experimental", "allow non-standardized experimental variants", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, D|E, "strict"},
 {"max_ts_probe", "maximum number of packets to read while waiting for the first timestamp", OFFSET(max_ts_probe), AV_OPT_TYPE_INT, { .i64 = 50 }, 0, INT_MAX, D },
+{"avoid_negative_ts", "shift timestamps so they start at 0", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, E, "avoid_negative_ts"},
+{"auto",              "enabled when required by target format",    0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_AUTO },              INT_MIN, INT_MAX, E, "avoid_negative_ts"},
+{"disabled",          "do not change timestamps",                  0, AV_OPT_TYPE_CONST, {.i64 = 0 },                                    INT_MIN, INT_MAX, E, "avoid_negative_ts"},
+{"make_non_negative", "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE }, INT_MIN, INT_MAX, E, "avoid_negative_ts"},
+{"make_zero",         "shift timestamps so they start at 0",       0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_ZERO },         INT_MIN, INT_MAX, E, "avoid_negative_ts"},
 {"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, CHAR_MIN, CHAR_MAX, D|E},
 {"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
 {"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL },  CHAR_MIN, CHAR_MAX, D },
diff --git a/libavformat/os_support.h b/libavformat/os_support.h
index bc72e96..ffae4b7 100644
--- a/libavformat/os_support.h
+++ b/libavformat/os_support.h
@@ -31,6 +31,15 @@
 
 #include <sys/stat.h>
 
+#ifdef _WIN32
+#if HAVE_DIRECT_H
+#include <direct.h>
+#endif
+#if HAVE_IO_H
+#include <io.h>
+#endif
+#endif
+
 #if defined(_WIN32) && !defined(__MINGW32CE__)
 #  include <fcntl.h>
 #  ifdef lseek
@@ -47,14 +56,6 @@
 #  define fstat(f,s) _fstati64((f), (s))
 #endif /* defined(_WIN32) && !defined(__MINGW32CE__) */
 
-#ifdef _WIN32
-#if HAVE_DIRECT_H
-#include <direct.h>
-#elif HAVE_IO_H
-#include <io.h>
-#endif
-#define mkdir(a, b) _mkdir(a)
-#endif
 
 #ifdef __ANDROID__
 #  if HAVE_UNISTD_H
@@ -138,4 +139,86 @@
 #endif /* HAVE_POLL_H */
 #endif /* CONFIG_NETWORK */
 
+#if defined(__MINGW32CE__)
+#define mkdir(a, b) _mkdir(a)
+#elif defined(_WIN32)
+#include <stdio.h>
+#include <windows.h>
+#include "libavutil/wchar_filename.h"
+
+#define DEF_FS_FUNCTION(name, wfunc, afunc)               \
+static inline int win32_##name(const char *filename_utf8) \
+{                                                         \
+    wchar_t *filename_w;                                  \
+    int ret;                                              \
+                                                          \
+    if (utf8towchar(filename_utf8, &filename_w))          \
+        return -1;                                        \
+    if (!filename_w)                                      \
+        goto fallback;                                    \
+                                                          \
+    ret = wfunc(filename_w);                              \
+    av_free(filename_w);                                  \
+    return ret;                                           \
+                                                          \
+fallback:                                                 \
+    /* filename may be be in CP_ACP */                    \
+    return afunc(filename_utf8);                          \
+}
+
+DEF_FS_FUNCTION(unlink, _wunlink, _unlink)
+DEF_FS_FUNCTION(mkdir,  _wmkdir,  _mkdir)
+DEF_FS_FUNCTION(rmdir,  _wrmdir , _rmdir)
+
+static inline int win32_rename(const char *src_utf8, const char *dest_utf8)
+{
+    wchar_t *src_w, *dest_w;
+    int ret;
+
+    if (utf8towchar(src_utf8, &src_w))
+        return -1;
+    if (utf8towchar(dest_utf8, &dest_w)) {
+        av_free(src_w);
+        return -1;
+    }
+    if (!src_w || !dest_w) {
+        av_free(src_w);
+        av_free(dest_w);
+        goto fallback;
+    }
+
+    ret = MoveFileExW(src_w, dest_w, MOVEFILE_REPLACE_EXISTING);
+    av_free(src_w);
+    av_free(dest_w);
+    // Lacking proper mapping from GetLastError() error codes to errno codes
+    if (ret)
+        errno = EPERM;
+    return ret;
+
+fallback:
+    /* filename may be be in CP_ACP */
+#if HAVE_MOVEFILEEXA
+    ret = MoveFileExA(src_utf8, dest_utf8, MOVEFILE_REPLACE_EXISTING);
+    if (ret)
+        errno = EPERM;
+#else
+    /* Windows Phone doesn't have MoveFileExA. However, it's unlikely
+     * that anybody would input filenames in CP_ACP there, so this
+     * fallback is kept mostly for completeness. Alternatively we could
+     * do MultiByteToWideChar(CP_ACP) and use MoveFileExW, but doing
+     * explicit conversions with CP_ACP is allegedly forbidden in windows
+     * store apps (or windows phone), and the notion of a native code page
+     * doesn't make much sense there. */
+    ret = rename(src_utf8, dest_utf8);
+#endif
+    return ret;
+}
+
+#define mkdir(a, b) win32_mkdir(a)
+#define rename      win32_rename
+#define rmdir       win32_rmdir
+#define unlink      win32_unlink
+
+#endif
+
 #endif /* AVFORMAT_OS_SUPPORT_H */
diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c
index 69b95bc..bbb76b6 100644
--- a/libavformat/rawdec.c
+++ b/libavformat/rawdec.c
@@ -119,6 +119,7 @@
     .read_header    = ff_raw_data_read_header,
     .read_packet    = ff_raw_read_partial_packet,
     .raw_codec_id   = AV_CODEC_ID_NONE,
+    .flags          = AVFMT_NOTIMESTAMPS,
 };
 #endif
 
@@ -129,7 +130,7 @@
     .long_name      = NULL_IF_CONFIG_SMALL("raw LOAS/LATM"),
     .read_header    = ff_raw_audio_read_header,
     .read_packet    = ff_raw_read_partial_packet,
-    .flags          = AVFMT_GENERIC_INDEX,
+    .flags          = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS,
     .extensions     = "latm",
     .raw_codec_id   = AV_CODEC_ID_AAC_LATM,
 };
@@ -211,7 +212,7 @@
     .long_name      = NULL_IF_CONFIG_SMALL("raw MLP"),
     .read_header    = ff_raw_audio_read_header,
     .read_packet    = ff_raw_read_partial_packet,
-    .flags          = AVFMT_GENERIC_INDEX,
+    .flags          = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS,
     .extensions     = "mlp",
     .raw_codec_id   = AV_CODEC_ID_MLP,
 };
@@ -223,7 +224,7 @@
     .long_name      = NULL_IF_CONFIG_SMALL("raw TrueHD"),
     .read_header    = ff_raw_audio_read_header,
     .read_packet    = ff_raw_read_partial_packet,
-    .flags          = AVFMT_GENERIC_INDEX,
+    .flags          = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS,
     .extensions     = "thd",
     .raw_codec_id   = AV_CODEC_ID_TRUEHD,
 };
@@ -235,7 +236,7 @@
     .long_name      = NULL_IF_CONFIG_SMALL("raw Shorten"),
     .read_header    = ff_raw_audio_read_header,
     .read_packet    = ff_raw_read_partial_packet,
-    .flags          = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK,
+    .flags          = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK|AVFMT_NOTIMESTAMPS,
     .extensions     = "shn",
     .raw_codec_id   = AV_CODEC_ID_SHORTEN,
 };
diff --git a/libavformat/riff.c b/libavformat/riff.c
index c63e406..8d7b1c2 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -362,6 +362,7 @@
     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '4') },
     { AV_CODEC_ID_G2M,          MKTAG('G', '2', 'M', '5') },
     { AV_CODEC_ID_FIC,          MKTAG('F', 'I', 'C', 'V') },
+    { AV_CODEC_ID_PRORES,       MKTAG('A', 'P', 'C', 'N') },
     { AV_CODEC_ID_NONE,         0 }
 };
 
diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c
index 09fee9d..88e2229 100644
--- a/libavformat/riffdec.c
+++ b/libavformat/riffdec.c
@@ -84,6 +84,9 @@
 {
     int id;
 
+    if (size < 14)
+        avpriv_request_sample(codec, "wav header size < 14");
+
     id                 = avio_rl16(pb);
     codec->codec_type  = AVMEDIA_TYPE_AUDIO;
     codec->channels    = avio_rl16(pb);
diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c
index 2eb2ae1..5e85800 100644
--- a/libavformat/riffenc.c
+++ b/libavformat/riffenc.c
@@ -68,8 +68,6 @@
      * fall back on using AVCodecContext.frame_size, which is not as reliable
      * for indicating packet duration. */
     frame_size = av_get_audio_frame_duration(enc, enc->block_align);
-    if (!frame_size)
-        frame_size = enc->frame_size;
 
     waveformatextensible = (enc->channels > 2 && enc->channel_layout) ||
                            enc->sample_rate > 48000 ||
@@ -104,12 +102,10 @@
                enc->bits_per_coded_sample, bps);
     }
 
-    if (enc->codec_id == AV_CODEC_ID_MP2 ||
-        enc->codec_id == AV_CODEC_ID_MP3) {
-        /* This is wrong, but it seems many demuxers do not work if this
-         * is set correctly. */
+    if (enc->codec_id == AV_CODEC_ID_MP2) {
         blkalign = frame_size;
-        // blkalign = 144 * enc->bit_rate/enc->sample_rate;
+    } else if (enc->codec_id == AV_CODEC_ID_MP3) {
+        blkalign = 576 * (enc->sample_rate <= (24000 + 32000)/2 ? 1 : 2);
     } else if (enc->codec_id == AV_CODEC_ID_AC3) {
         blkalign = 3840;                /* maximum bytes per frame */
     } else if (enc->codec_id == AV_CODEC_ID_AAC) {
diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c
index 96b9e7f..c46b53f 100644
--- a/libavformat/rmdec.c
+++ b/libavformat/rmdec.c
@@ -610,7 +610,7 @@
 /* multiple of 20 bytes for ra144 (ugly) */
 #define RAW_PACKET_SIZE 1000
 
-static int sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
+static int rm_sync(AVFormatContext *s, int64_t *timestamp, int *flags, int *stream_index, int64_t *pos){
     RMDemuxContext *rm = s->priv_data;
     AVIOContext *pb = s->pb;
     AVStream *st;
@@ -964,7 +964,7 @@
                 flags = (seq++ == 1) ? 2 : 0;
                 pos = avio_tell(s->pb);
             } else {
-                len=sync(s, &timestamp, &flags, &i, &pos);
+                len = rm_sync(s, &timestamp, &flags, &i, &pos);
                 if (len > 0)
                     st = s->streams[i];
             }
@@ -1035,7 +1035,7 @@
         int seq=1;
         AVStream *st;
 
-        len=sync(s, &dts, &flags, &stream_index2, &pos);
+        len = rm_sync(s, &dts, &flags, &stream_index2, &pos);
         if(len<0)
             return AV_NOPTS_VALUE;
 
diff --git a/libavformat/rtmppkt.c b/libavformat/rtmppkt.c
index 92172dc..4f79487 100644
--- a/libavformat/rtmppkt.c
+++ b/libavformat/rtmppkt.c
@@ -396,7 +396,7 @@
                           int timestamp, int size)
 {
     if (size) {
-        pkt->data = av_malloc(size);
+        pkt->data = av_realloc(NULL, size);
         if (!pkt->data)
             return AVERROR(ENOMEM);
     }
diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c
index 72d6341..ebc1628 100644
--- a/libavformat/rtmpproto.c
+++ b/libavformat/rtmpproto.c
@@ -1822,6 +1822,9 @@
             /* Gracefully ignore Adobe-specific historical artifact errors. */
             level = AV_LOG_WARNING;
             ret = 0;
+        } else if (tracked_method && !strcmp(tracked_method, "getStreamLength")) {
+            level = rt->live ? AV_LOG_DEBUG : AV_LOG_WARNING;
+            ret = 0;
         } else if (tracked_method && !strcmp(tracked_method, "connect")) {
             ret = handle_connect_error(s, tmpstr);
             if (!ret) {
@@ -2951,7 +2954,7 @@
 {
     RTMPContext *rt = s->priv_data;
     int size_temp = size;
-    int pktsize, pkttype;
+    int pktsize, pkttype, copy;
     uint32_t ts;
     const uint8_t *buf_temp = buf;
     uint8_t c;
@@ -2968,8 +2971,9 @@
 
         if (rt->flv_header_bytes < RTMP_HEADER) {
             const uint8_t *header = rt->flv_header;
-            int copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
             int channel = RTMP_AUDIO_CHANNEL;
+
+            copy = FFMIN(RTMP_HEADER - rt->flv_header_bytes, size_temp);
             bytestream_get_buffer(&buf_temp, rt->flv_header + rt->flv_header_bytes, copy);
             rt->flv_header_bytes += copy;
             size_temp            -= copy;
@@ -2986,15 +2990,15 @@
             if (pkttype == RTMP_PT_VIDEO)
                 channel = RTMP_VIDEO_CHANNEL;
 
-            //force 12bytes header
             if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) ||
                 pkttype == RTMP_PT_NOTIFY) {
-                if (pkttype == RTMP_PT_NOTIFY)
-                    pktsize += 16;
                 if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
                                                      &rt->nb_prev_pkt[1],
                                                      channel)) < 0)
                     return ret;
+                // Force sending a full 12 bytes header by clearing the
+                // channel id, to make it not match a potential earlier
+                // packet in the same channel.
                 rt->prev_pkt[1][channel].channel_id = 0;
             }
 
@@ -3005,24 +3009,43 @@
 
             rt->out_pkt.extra = rt->stream_id;
             rt->flv_data = rt->out_pkt.data;
-
-            if (pkttype == RTMP_PT_NOTIFY)
-                ff_amf_write_string(&rt->flv_data, "@setDataFrame");
         }
 
-        if (rt->flv_size - rt->flv_off > size_temp) {
-            bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, size_temp);
-            rt->flv_off += size_temp;
-            size_temp = 0;
-        } else {
-            bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, rt->flv_size - rt->flv_off);
-            size_temp   -= rt->flv_size - rt->flv_off;
-            rt->flv_off += rt->flv_size - rt->flv_off;
-        }
+        copy = FFMIN(rt->flv_size - rt->flv_off, size_temp);
+        bytestream_get_buffer(&buf_temp, rt->flv_data + rt->flv_off, copy);
+        rt->flv_off += copy;
+        size_temp   -= copy;
 
         if (rt->flv_off == rt->flv_size) {
             rt->skip_bytes = 4;
 
+            if (rt->out_pkt.type == RTMP_PT_NOTIFY) {
+                // For onMetaData and |RtmpSampleAccess packets, we want
+                // @setDataFrame prepended to the packet before it gets sent.
+                // However, not all RTMP_PT_NOTIFY packets (e.g., onTextData
+                // and onCuePoint).
+                uint8_t commandbuffer[64];
+                int stringlen = 0;
+                GetByteContext gbc;
+
+                bytestream2_init(&gbc, rt->flv_data, rt->flv_size);
+                if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer),
+                                        &stringlen)) {
+                    if (!strcmp(commandbuffer, "onMetaData") ||
+                        !strcmp(commandbuffer, "|RtmpSampleAccess")) {
+                        uint8_t *ptr;
+                        if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) {
+                            rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0;
+                            return ret;
+                        }
+                        memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size);
+                        rt->out_pkt.size += 16;
+                        ptr = rt->out_pkt.data;
+                        ff_amf_write_string(&ptr, "@setDataFrame");
+                    }
+                }
+            }
+
             if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0)
                 return ret;
             rt->flv_size = 0;
diff --git a/libavformat/rtpdec_h261.c b/libavformat/rtpdec_h261.c
index b902d2a..43244bb 100644
--- a/libavformat/rtpdec_h261.c
+++ b/libavformat/rtpdec_h261.c
@@ -32,7 +32,7 @@
     uint32_t     timestamp;
 };
 
-static PayloadContext *h261_new_context(void)
+static av_cold PayloadContext *h261_new_context(void)
 {
     return av_mallocz(sizeof(PayloadContext));
 }
@@ -45,7 +45,7 @@
     *dyn_buf = NULL;
 }
 
-static void h261_free_context(PayloadContext *pl_ctx)
+static av_cold void h261_free_context(PayloadContext *pl_ctx)
 {
     /* return if context is invalid */
     if (!pl_ctx)
@@ -80,16 +80,14 @@
     int sbit, ebit, gobn, mbap, quant;
     int res;
 
-    //av_log(ctx, AV_LOG_DEBUG, "got h261 RTP packet with time: %u\n", timestamp);
-
     /* drop data of previous packets in case of non-continuous (loss) packet stream */
     if (data->buf && data->timestamp != *timestamp) {
         h261_free_dyn_buffer(&data->buf);
     }
 
-    /* sanity check for size of input packet */
-    if (len < 5 /* 4 bytes header and 1 byte payload at least */) {
-        av_log(ctx, AV_LOG_ERROR, "Too short H.261 RTP packet\n");
+    /* sanity check for size of input packet: 1 byte payload at least */
+    if (len < RTP_H261_PAYLOAD_HEADER_SIZE + 1) {
+        av_log(ctx, AV_LOG_ERROR, "Too short RTP/H.261 packet, got %d bytes\n", len);
         return AVERROR_INVALIDDATA;
     }
 
diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c
index 71e6f03..0ea9568 100644
--- a/libavformat/rtpproto.c
+++ b/libavformat/rtpproto.c
@@ -192,6 +192,7 @@
                           const char *hostname, int port,
                           int local_port, int ttl,
                           int max_packet_size, int connect,
+                          int dscp,
                           const char *include_sources,
                           const char *exclude_sources)
 {
@@ -204,6 +205,8 @@
         url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size);
     if (connect)
         url_add_option(buf, buf_size, "connect=1");
+    if (dscp >= 0)
+        url_add_option(buf, buf_size, "dscp=%d", dscp);
     url_add_option(buf, buf_size, "fifo_size=0");
     if (include_sources && include_sources[0])
         url_add_option(buf, buf_size, "sources=%s", include_sources);
@@ -264,6 +267,7 @@
  *         'sources=ip[,ip]'  : list allowed source IP addresses
  *         'block=ip[,ip]'    : list disallowed source IP addresses
  *         'write_to_source=0/1' : send packets to the source address of the latest received packet
+ *         'dscp=n'           : set DSCP value to n (QoS)
  * deprecated option:
  *         'localport=n'      : set the local port to n
  *
@@ -278,7 +282,7 @@
     RTPContext *s = h->priv_data;
     int rtp_port, rtcp_port,
         ttl, connect,
-        local_rtp_port, local_rtcp_port, max_packet_size;
+        local_rtp_port, local_rtcp_port, max_packet_size, dscp;
     char hostname[256], include_sources[1024] = "", exclude_sources[1024] = "";
     char buf[1024];
     char path[1024];
@@ -294,6 +298,7 @@
     local_rtcp_port = -1;
     max_packet_size = -1;
     connect = 0;
+    dscp = -1;
 
     p = strchr(uri, '?');
     if (p) {
@@ -321,6 +326,9 @@
         if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) {
             s->write_to_source = strtol(buf, NULL, 10);
         }
+        if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) {
+            dscp = strtol(buf, NULL, 10);
+        }
         if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
             av_strlcpy(include_sources, buf, sizeof(include_sources));
             rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs);
@@ -334,7 +342,7 @@
     for (i = 0;i < max_retry_count;i++) {
         build_udp_url(buf, sizeof(buf),
                       hostname, rtp_port, local_rtp_port, ttl, max_packet_size,
-                      connect, include_sources, exclude_sources);
+                      connect, dscp, include_sources, exclude_sources);
         if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
             goto fail;
         local_rtp_port = ff_udp_get_local_port(s->rtp_hd);
@@ -346,7 +354,7 @@
             local_rtcp_port = local_rtp_port + 1;
             build_udp_url(buf, sizeof(buf),
                           hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size,
-                          connect, include_sources, exclude_sources);
+                          connect, dscp, include_sources, exclude_sources);
             if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) {
                 local_rtp_port = local_rtcp_port = -1;
                 continue;
@@ -355,7 +363,7 @@
         }
         build_udp_url(buf, sizeof(buf),
                       hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size,
-                      connect, include_sources, exclude_sources);
+                      connect, dscp, include_sources, exclude_sources);
         if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0)
             goto fail;
         break;
diff --git a/libavformat/sbgdec.c b/libavformat/sbgdec.c
index 36cd8a3..32822fb 100644
--- a/libavformat/sbgdec.c
+++ b/libavformat/sbgdec.c
@@ -25,6 +25,7 @@
 #include "libavutil/intreadwrite.h"
 #include "libavutil/log.h"
 #include "libavutil/opt.h"
+#include "libavutil/time_internal.h"
 #include "avformat.h"
 #include "internal.h"
 
@@ -905,14 +906,14 @@
     } else {
         /* Mixed relative/absolute ts: expand */
         time_t now0;
-        struct tm *tm;
+        struct tm *tm, tmpbuf;
 
         av_log(log, AV_LOG_WARNING,
                "Scripts with mixed absolute and relative timestamps can give "
                "unexpected results (pause, seeking, time zone change).\n");
 #undef time
         time(&now0);
-        tm = localtime(&now0);
+        tm = localtime_r(&now0, &tmpbuf);
         now = tm ? tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec :
                    now0 % DAY;
         av_log(log, AV_LOG_INFO, "Using %02d:%02d:%02d as NOW.\n",
diff --git a/libavformat/segment.c b/libavformat/segment.c
index 9db2607..2cad6e3 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -39,6 +39,7 @@
 #include "libavutil/parseutils.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/time.h"
+#include "libavutil/time_internal.h"
 #include "libavutil/timestamp.h"
 
 typedef struct SegmentListEntry {
@@ -569,6 +570,7 @@
     AVFormatContext *oc = NULL;
     AVDictionary *options = NULL;
     int ret;
+    int i;
 
     seg->segment_count = 0;
     if (!seg->write_header_trailer)
@@ -674,6 +676,13 @@
     }
     seg->segment_frame_count = 0;
 
+    av_assert0(s->nb_streams == oc->nb_streams);
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *inner_st  = oc->streams[i];
+        AVStream *outer_st = s->streams[i];
+        avpriv_set_pts_info(outer_st, inner_st->pts_wrap_bits, inner_st->time_base.num, inner_st->time_base.den);
+    }
+
     if (oc->avoid_negative_ts > 0 && s->avoid_negative_ts < 0)
         s->avoid_negative_ts = 1;
 
@@ -716,11 +725,7 @@
         if (seg->use_clocktime) {
             int64_t avgt = av_gettime();
             time_t sec = avgt / 1000000;
-#if HAVE_LOCALTIME_R
             localtime_r(&sec, &ti);
-#else
-            ti = *localtime(&sec);
-#endif
             usecs = (int64_t)(ti.tm_hour*3600 + ti.tm_min*60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
             wrapped_val = usecs % seg->time;
             if (seg->last_cut != usecs && wrapped_val < seg->last_val) {
diff --git a/libavformat/sol.c b/libavformat/sol.c
index 27d3551..c943453 100644
--- a/libavformat/sol.c
+++ b/libavformat/sol.c
@@ -50,18 +50,15 @@
 
 static enum AVCodecID sol_codec_id(int magic, int type)
 {
-    if (magic == 0x0B8D)
-    {
-        if (type & SOL_DPCM) return AV_CODEC_ID_SOL_DPCM;
-        else return AV_CODEC_ID_PCM_U8;
-    }
     if (type & SOL_DPCM)
-    {
-        if (type & SOL_16BIT) return AV_CODEC_ID_SOL_DPCM;
-        else if (magic == 0x0C8D) return AV_CODEC_ID_SOL_DPCM;
-        else return AV_CODEC_ID_SOL_DPCM;
-    }
-    if (type & SOL_16BIT) return AV_CODEC_ID_PCM_S16LE;
+        return AV_CODEC_ID_SOL_DPCM;
+
+    if (magic == 0x0B8D)
+        return AV_CODEC_ID_PCM_U8;
+
+    if (type & SOL_16BIT)
+        return AV_CODEC_ID_PCM_S16LE;
+
     return AV_CODEC_ID_PCM_U8;
 }
 
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index a1b1856..0aabc9d 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -45,7 +45,7 @@
 #define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
     { "listen",          "Listen for incoming connections",  OFFSET(listen),         AV_OPT_TYPE_INT, { .i64 = 0 },     0,       1,       .flags = D|E },
-    { "timeout",     "set timeout of socket I/O operations", OFFSET(rw_timeout),     AV_OPT_TYPE_INT, { .i64 = -1 },         -1, INT_MAX, .flags = D|E },
+    { "timeout",     "set timeout (in microseconds) of socket I/O operations", OFFSET(rw_timeout),     AV_OPT_TYPE_INT, { .i64 = -1 },         -1, INT_MAX, .flags = D|E },
     { "listen_timeout",  "Connection awaiting timeout",      OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 },         -1, INT_MAX, .flags = D|E },
     { NULL }
 };
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 376a544..91c7910 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -40,6 +40,20 @@
 #include "os_support.h"
 #include "url.h"
 
+#if HAVE_UDPLITE_H
+#include "udplite.h"
+#else
+/* On many Linux systems, udplite.h is missing but the kernel supports UDP-Lite.
+ * So, we provide a fallback here.
+ */
+#define UDPLITE_SEND_CSCOV                               10
+#define UDPLITE_RECV_CSCOV                               11
+#endif
+
+#ifndef IPPROTO_UDPLITE
+#define IPPROTO_UDPLITE                                  136
+#endif
+
 #if HAVE_PTHREAD_CANCEL
 #include <pthread.h>
 #endif
@@ -55,11 +69,13 @@
 
 #define UDP_TX_BUF_SIZE 32768
 #define UDP_MAX_PKT_SIZE 65536
+#define UDP_HEADER_SIZE 8
 
 typedef struct {
     const AVClass *class;
     int udp_fd;
     int ttl;
+    int udplite_coverage;
     int buffer_size;
     int is_multicast;
     int is_broadcast;
@@ -95,6 +111,7 @@
 {"buffer_size", "set packet buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
 {"localport", "set local port to bind to", OFFSET(local_port), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
 {"localaddr", "choose local IP address", OFFSET(local_addr), AV_OPT_TYPE_STRING, {.str = ""}, 0, 0, D|E },
+{"udplite_coverage", "choose UDPLite head size which should be validated by checksum", OFFSET(udplite_coverage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E },
 {"pkt_size", "set size of UDP packets", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64 = 1472}, 0, INT_MAX, D|E },
 {"reuse", "explicitly allow or disallow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E },
 {"broadcast", "explicitly allow or disallow broadcast destination", OFFSET(is_broadcast), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E },
@@ -114,6 +131,13 @@
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
+static const AVClass udplite_context_class = {
+    .class_name     = "udplite",
+    .item_name      = av_default_item_name,
+    .option         = options,
+    .version        = LIBAVUTIL_VERSION_INT,
+};
+
 static void log_net_error(void *ctx, int level, const char* prefix)
 {
     char errbuf[100];
@@ -335,7 +359,10 @@
     if (!res0)
         goto fail;
     for (res = res0; res; res=res->ai_next) {
-        udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
+        if (s->udplite_coverage)
+            udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, IPPROTO_UDPLITE);
+        else
+            udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
         if (udp_fd != -1) break;
         log_net_error(NULL, AV_LOG_ERROR, "socket");
     }
@@ -529,7 +556,7 @@
 static int udp_open(URLContext *h, const char *uri, int flags)
 {
     char hostname[1024], localaddr[1024] = "";
-    int port, udp_fd = -1, tmp, bind_ret = -1;
+    int port, udp_fd = -1, tmp, bind_ret = -1, dscp = -1;
     UDPContext *s = h->priv_data;
     int is_output;
     const char *p;
@@ -570,6 +597,9 @@
         if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
             s->ttl = strtol(buf, NULL, 10);
         }
+        if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) {
+            s->udplite_coverage = strtol(buf, NULL, 10);
+        }
         if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
             s->local_port = strtol(buf, NULL, 10);
         }
@@ -582,6 +612,9 @@
         if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
             s->is_connected = strtol(buf, NULL, 10);
         }
+        if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) {
+            dscp = strtol(buf, NULL, 10);
+        }
         if (av_find_info_tag(buf, sizeof(buf), "fifo_size", p)) {
             s->circular_buffer_size = strtol(buf, NULL, 10);
             if (!HAVE_PTHREAD_CANCEL)
@@ -653,6 +686,24 @@
            goto fail;
     }
 
+    /* Set the checksum coverage for UDP-Lite (RFC 3828) for sending and receiving.
+     * The receiver coverage has to be less than or equal to the sender coverage.
+     * Otherwise, the receiver will drop all packets.
+     */
+    if (s->udplite_coverage) {
+        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
+            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_SEND_CSCOV not available");
+
+        if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0)
+            av_log(h, AV_LOG_WARNING, "socket option UDPLITE_RECV_CSCOV not available");
+    }
+
+    if (dscp >= 0) {
+        dscp <<= 2;
+        if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) != 0)
+            goto fail;
+    }
+
     /* If multicast, try binding the multicast address first, to avoid
      * receiving UDP packets from other sources aimed at the same UDP
      * port. This fails on windows. This makes sending to the same address
@@ -780,6 +831,16 @@
     return AVERROR(EIO);
 }
 
+static int udplite_open(URLContext *h, const char *uri, int flags)
+{
+    UDPContext *s = h->priv_data;
+
+    // set default checksum coverage
+    s->udplite_coverage = UDP_HEADER_SIZE;
+
+    return udp_open(h, uri, flags);
+}
+
 static int udp_read(URLContext *h, uint8_t *buf, int size)
 {
     UDPContext *s = h->priv_data;
@@ -893,3 +954,15 @@
     .priv_data_class     = &udp_context_class,
     .flags               = URL_PROTOCOL_FLAG_NETWORK,
 };
+
+URLProtocol ff_udplite_protocol = {
+    .name                = "udplite",
+    .url_open            = udplite_open,
+    .url_read            = udp_read,
+    .url_write           = udp_write,
+    .url_close           = udp_close,
+    .url_get_file_handle = udp_get_file_handle,
+    .priv_data_size      = sizeof(UDPContext),
+    .priv_data_class     = &udplite_context_class,
+    .flags               = URL_PROTOCOL_FLAG_NETWORK,
+};
diff --git a/libavformat/utils.c b/libavformat/utils.c
index d3e1e06..798c612 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -103,6 +103,7 @@
 }
 
 MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate)
+MAKE_ACCESSORS(AVStream, stream, char *, recommended_encoder_configuration)
 MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, video_codec)
 MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, audio_codec)
 MAKE_ACCESSORS(AVFormatContext, format, AVCodec *, subtitle_codec)
@@ -2786,10 +2787,16 @@
 
 static int get_std_framerate(int i)
 {
-    if (i < 60 * 12)
+    if (i < 30*12)
         return (i + 1) * 1001;
-    else
-        return ((const int[]) { 24, 30, 60, 12, 15, 48 })[i - 60 * 12] * 1000 * 12;
+    i -= 30*12;
+
+    if (i < 7)
+        return ((const int[]) { 40, 48, 50, 60, 80, 120, 240})[i] * 1001 * 12;
+
+    i -= 7;
+
+    return ((const int[]) { 24, 30, 60, 12, 15, 48 })[i] * 1000 * 12;
 }
 
 /* Is the time base unreliable?
@@ -2982,6 +2989,7 @@
     int orig_nb_streams = ic->nb_streams;
     int flush_codecs;
     int64_t max_analyze_duration = ic->max_analyze_duration2;
+    int64_t max_stream_analyze_duration;
     int64_t probesize = ic->probesize2;
 
     if (!max_analyze_duration)
@@ -2992,11 +3000,12 @@
 
     av_opt_set(ic, "skip_clear", "1", AV_OPT_SEARCH_CHILDREN);
 
+    max_stream_analyze_duration = max_analyze_duration;
     if (!max_analyze_duration) {
-        if (!strcmp(ic->iformat->name, "flv") && !(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
-            max_analyze_duration = 10*AV_TIME_BASE;
-        } else
-            max_analyze_duration = 5*AV_TIME_BASE;
+        max_stream_analyze_duration =
+        max_analyze_duration        = 5*AV_TIME_BASE;
+        if (!strcmp(ic->iformat->name, "flv"))
+            max_stream_analyze_duration = 30*AV_TIME_BASE;
     }
 
     if (ic->pb)
@@ -3069,6 +3078,7 @@
     count     = 0;
     read_size = 0;
     for (;;) {
+        int analyzed_all_streams;
         if (ff_check_interrupt(&ic->interrupt_callback)) {
             ret = AVERROR_EXIT;
             av_log(ic, AV_LOG_DEBUG, "interrupted\n");
@@ -3108,7 +3118,9 @@
                  st->codec->codec_type == AVMEDIA_TYPE_AUDIO))
                 break;
         }
+        analyzed_all_streams = 0;
         if (i == ic->nb_streams) {
+            analyzed_all_streams = 1;
             /* NOTE: If the format has no header, then we need to read some
              * packets to get most of the streams, so we cannot stop here. */
             if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
@@ -3216,7 +3228,7 @@
                 && st->info->fps_last_dts  != AV_NOPTS_VALUE)
                 t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q));
 
-            if (t >= max_analyze_duration) {
+            if (t >= (analyzed_all_streams ? max_analyze_duration : max_stream_analyze_duration)) {
                 av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %"PRId64" reached at %"PRId64" microseconds\n",
                        max_analyze_duration,
                        t);
@@ -3286,7 +3298,6 @@
             }
         }
     }
-    av_opt_set(ic, "skip_clear", "0", AV_OPT_SEARCH_CHILDREN);
 
     // close codecs which were opened in try_decode_frame()
     for (i = 0; i < ic->nb_streams; i++) {
@@ -3347,6 +3358,11 @@
                     st->r_frame_rate.den = st->time_base.num;
                 }
             }
+            if (st->display_aspect_ratio.num && st->display_aspect_ratio.den) {
+                AVRational hw_ratio = { st->codec->height, st->codec->width };
+                st->sample_aspect_ratio = av_mul_q(st->display_aspect_ratio,
+                                                   hw_ratio);
+            }
         } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
             if (!st->codec->bits_per_coded_sample)
                 st->codec->bits_per_coded_sample =
@@ -3375,6 +3391,8 @@
     if (probesize)
     estimate_timings(ic, old_offset);
 
+    av_opt_set(ic, "skip_clear", "0", AV_OPT_SEARCH_CHILDREN);
+
     if (ret >= 0 && ic->nb_streams)
         /* We could not have all the codec parameters before EOF. */
         ret = -1;
@@ -3536,6 +3554,7 @@
     if (st->info)
         av_freep(&st->info->duration_error);
     av_freep(&st->info);
+    av_freep(&st->recommended_encoder_configuration);
     av_freep(&s->streams[ --s->nb_streams ]);
 }
 
diff --git a/libavformat/version.h b/libavformat/version.h
index af49ffa..206b265 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -30,8 +30,8 @@
 #include "libavutil/version.h"
 
 #define LIBAVFORMAT_VERSION_MAJOR 56
-#define LIBAVFORMAT_VERSION_MINOR  11
-#define LIBAVFORMAT_VERSION_MICRO 100
+#define LIBAVFORMAT_VERSION_MINOR  15
+#define LIBAVFORMAT_VERSION_MICRO 101
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \
diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c
index c73c900..bce4876 100644
--- a/libavformat/wavenc.c
+++ b/libavformat/wavenc.c
@@ -38,6 +38,7 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "libavutil/time.h"
+#include "libavutil/time_internal.h"
 
 #include "avformat.h"
 #include "avio.h"
@@ -267,10 +268,11 @@
 
     memset(timestamp, 0, sizeof(timestamp));
     if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
+        struct tm tmpbuf;
         av_log(s, AV_LOG_INFO, "Writing local time and date to Peak Envelope Chunk\n");
         now0 = av_gettime();
         now_secs = now0 / 1000000;
-        strftime(timestamp, sizeof(timestamp), "%Y:%m:%d:%H:%M:%S:", localtime(&now_secs));
+        strftime(timestamp, sizeof(timestamp), "%Y:%m:%d:%H:%M:%S:", localtime_r(&now_secs, &tmpbuf));
         av_strlcatf(timestamp, sizeof(timestamp), "%03d", (int)((now0 / 1000) % 1000));
     }
 
diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c
index 768b5d2..4536b7d 100644
--- a/libavformat/webmdashenc.c
+++ b/libavformat/webmdashenc.c
@@ -46,6 +46,7 @@
     char *adaptation_sets;
     AdaptationSet *as;
     int nb_as;
+    int representation_id;
 } WebMDashMuxContext;
 
 static const char *get_codec_name(int codec_id)
@@ -259,7 +260,7 @@
     avio_printf(s->pb, ">\n");
 
     for (i = 0; i < as->nb_streams; i++) {
-        write_representation(s, s->streams[as->streams[i]], i,
+        write_representation(s, s->streams[as->streams[i]], w->representation_id++,
                              !width_in_as, !height_in_as, !sample_rate_in_as);
     }
     avio_printf(s->pb, "</AdaptationSet>\n");
diff --git a/libavformat/webpenc.c b/libavformat/webpenc.c
new file mode 100644
index 0000000..ee110de
--- /dev/null
+++ b/libavformat/webpenc.c
@@ -0,0 +1,169 @@
+/*
+ * webp muxer
+ * Copyright (c) 2014 Michael Niedermayer
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/intreadwrite.h"
+#include "libavutil/opt.h"
+#include "avformat.h"
+#include "internal.h"
+
+typedef struct WebpContext{
+    AVClass *class;
+    int frame_count;
+    AVPacket last_pkt;
+    int loop;
+} WebpContext;
+
+static int webp_write_header(AVFormatContext *s)
+{
+    AVStream *st;
+
+    if (s->nb_streams != 1) {
+        av_log(s, AV_LOG_ERROR, "Only exactly 1 stream is supported\n");
+        return AVERROR(EINVAL);
+    }
+    st = s->streams[0];
+    if (st->codec->codec_id != AV_CODEC_ID_WEBP) {
+        av_log(s, AV_LOG_ERROR, "Only WebP is supported\n");
+        return AVERROR(EINVAL);
+    }
+    avpriv_set_pts_info(st, 24, 1, 1000);
+
+    avio_write(s->pb, "RIFF\0\0\0\0WEBP", 12);
+
+    return 0;
+}
+
+static int flush(AVFormatContext *s, int trailer, int64_t pts)
+{
+    WebpContext *w = s->priv_data;
+    AVStream *st = s->streams[0];
+
+    if (w->last_pkt.size) {
+        int skip = 0;
+        unsigned flags = 0;
+        int vp8x = 0;
+
+        if (AV_RL32(w->last_pkt.data) == AV_RL32("RIFF"))
+            skip = 12;
+        if (AV_RL32(w->last_pkt.data + skip) == AV_RL32("VP8X")) {
+            flags |= w->last_pkt.data[skip + 4 + 4];
+            vp8x = 1;
+            skip += AV_RL32(w->last_pkt.data + skip + 4) + 8;
+        }
+
+        w->frame_count ++;
+
+        if (w->frame_count == 1) {
+            if (!trailer) {
+                vp8x = 1;
+                flags |= 2 + 16;
+            }
+
+            if (vp8x) {
+                avio_write(s->pb, "VP8X", 4);
+                avio_wl32(s->pb, 10);
+                avio_w8(s->pb, flags);
+                avio_wl24(s->pb, 0);
+                avio_wl24(s->pb, st->codec->width - 1);
+                avio_wl24(s->pb, st->codec->height - 1);
+            }
+            if (!trailer) {
+                avio_write(s->pb, "ANIM", 4);
+                avio_wl32(s->pb, 6);
+                avio_wl32(s->pb, 0xFFFFFFFF);
+                avio_wl16(s->pb, w->loop);
+            }
+        }
+
+        if (w->frame_count > trailer) {
+            avio_write(s->pb, "ANMF", 4);
+            avio_wl32(s->pb, 16 + w->last_pkt.size - skip);
+            avio_wl24(s->pb, 0);
+            avio_wl24(s->pb, 0);
+            avio_wl24(s->pb, st->codec->width - 1);
+            avio_wl24(s->pb, st->codec->height - 1);
+            if (w->last_pkt.pts != AV_NOPTS_VALUE && pts != AV_NOPTS_VALUE) {
+                avio_wl24(s->pb, pts - w->last_pkt.pts);
+            } else
+                avio_wl24(s->pb, w->last_pkt.duration);
+            avio_w8(s->pb, 0);
+        }
+        avio_write(s->pb, w->last_pkt.data + skip, w->last_pkt.size - skip);
+        av_free_packet(&w->last_pkt);
+    }
+
+    return 0;
+}
+
+static int webp_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    WebpContext *w = s->priv_data;
+    int ret;
+
+    if ((ret = flush(s, 0, pkt->pts)) < 0)
+        return ret;
+
+    av_copy_packet(&w->last_pkt, pkt);
+
+    return 0;
+}
+
+static int webp_write_trailer(AVFormatContext *s)
+{
+    unsigned filesize;
+    int ret;
+
+    if ((ret = flush(s, 1, AV_NOPTS_VALUE)) < 0)
+        return ret;
+
+    filesize = avio_tell(s->pb);
+    avio_seek(s->pb, 4, SEEK_SET);
+    avio_wl32(s->pb, filesize - 8);
+
+    return 0;
+}
+
+#define OFFSET(x) offsetof(WebpContext, x)
+#define ENC AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+    { "loop", "Number of times to loop the output: 0 - infinite loop", OFFSET(loop),
+      AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 65535, ENC },
+    { NULL },
+};
+
+static const AVClass webp_muxer_class = {
+    .class_name = "WebP muxer",
+    .item_name  = av_default_item_name,
+    .version    = LIBAVUTIL_VERSION_INT,
+    .option     = options,
+};
+AVOutputFormat ff_webp_muxer = {
+    .name           = "webp",
+    .long_name      = NULL_IF_CONFIG_SMALL("WebP"),
+    .extensions     = "webp",
+    .priv_data_size = sizeof(WebpContext),
+    .video_codec    = AV_CODEC_ID_WEBP,
+    .write_header   = webp_write_header,
+    .write_packet   = webp_write_packet,
+    .write_trailer  = webp_write_trailer,
+    .priv_class     = &webp_muxer_class,
+    .flags          = AVFMT_VARIABLE_FPS,
+};
diff --git a/libavformat/xwma.c b/libavformat/xwma.c
index 127c097..5d29d0b 100644
--- a/libavformat/xwma.c
+++ b/libavformat/xwma.c
@@ -44,7 +44,7 @@
 static int xwma_read_header(AVFormatContext *s)
 {
     int64_t size;
-    int ret;
+    int ret = 0;
     uint32_t dpds_table_size = 0;
     uint32_t *dpds_table = NULL;
     unsigned int tag;
@@ -132,7 +132,7 @@
     for (;;) {
         if (pb->eof_reached) {
             ret = AVERROR_EOF;
-            goto end;
+            goto fail;
         }
         /* read next chunk tag */
         tag = avio_rl32(pb);
@@ -155,7 +155,7 @@
             if (dpds_table) {
                 av_log(s, AV_LOG_ERROR, "two dpds chunks present\n");
                 ret = AVERROR_INVALIDDATA;
-                goto end;
+                goto fail;
             }
 
             /* Compute the number of entries in the dpds chunk. */
@@ -189,7 +189,7 @@
     /* Determine overall data length */
     if (size < 0) {
         ret = AVERROR_INVALIDDATA;
-        goto end;
+        goto fail;
     }
     if (!size) {
         xwma->data_end = INT64_MAX;
@@ -210,7 +210,7 @@
                    "Invalid bits_per_coded_sample %d for %d channels\n",
                    st->codec->bits_per_coded_sample, st->codec->channels);
             ret = AVERROR_INVALIDDATA;
-            goto end;
+            goto fail;
         }
 
         st->duration = total_decoded_bytes / bytes_per_sample;
@@ -245,7 +245,7 @@
         st->duration = (size<<3) * st->codec->sample_rate / st->codec->bit_rate;
     }
 
-end:
+fail:
     av_free(dpds_table);
 
     return ret;
diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c
index a7f2d8a..cc954fc 100644
--- a/libavformat/yuv4mpegenc.c
+++ b/libavformat/yuv4mpegenc.c
@@ -268,7 +268,7 @@
     case AV_PIX_FMT_YUV420P16:
     case AV_PIX_FMT_YUV422P16:
     case AV_PIX_FMT_YUV444P16:
-        if (s->streams[0]->codec->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
+        if (s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
             av_log(s, AV_LOG_ERROR, "'%s' is not a official yuv4mpegpipe pixel format. "
                    "Use '-strict -1' to encode to this pixel format.\n",
                    av_get_pix_fmt_name(s->streams[0]->codec->pix_fmt));
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 6f90301..c1aa8aa 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -157,6 +157,7 @@
             cpu                                                         \
             crc                                                         \
             des                                                         \
+            dict                                                        \
             error                                                       \
             eval                                                        \
             file                                                        \
diff --git a/libavutil/arm/float_dsp_init_vfp.c b/libavutil/arm/float_dsp_init_vfp.c
index 45508b8..e15abf3 100644
--- a/libavutil/arm/float_dsp_init_vfp.c
+++ b/libavutil/arm/float_dsp_init_vfp.c
@@ -32,7 +32,7 @@
 void ff_vector_fmul_reverse_vfp(float *dst, const float *src0,
                                 const float *src1, int len);
 
-void ff_butterflies_float_vfp(float *restrict v1, float *restrict v2, int len);
+void ff_butterflies_float_vfp(float *av_restrict v1, float *av_restrict v2, int len);
 
 av_cold void ff_float_dsp_init_vfp(AVFloatDSPContext *fdsp, int cpu_flags)
 {
diff --git a/libavutil/atomic_win32.h b/libavutil/atomic_win32.h
index 20b99df..f729933 100644
--- a/libavutil/atomic_win32.h
+++ b/libavutil/atomic_win32.h
@@ -21,6 +21,7 @@
 #ifndef AVUTIL_ATOMIC_WIN32_H
 #define AVUTIL_ATOMIC_WIN32_H
 
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
 #define avpriv_atomic_int_get atomic_int_get_win32
diff --git a/libavutil/avstring.h b/libavutil/avstring.h
index ea7d1dc..ffb7aa6 100644
--- a/libavutil/avstring.h
+++ b/libavutil/avstring.h
@@ -203,22 +203,22 @@
 /**
  * Locale-independent conversion of ASCII isdigit.
  */
-int av_isdigit(int c);
+av_const int av_isdigit(int c);
 
 /**
  * Locale-independent conversion of ASCII isgraph.
  */
-int av_isgraph(int c);
+av_const int av_isgraph(int c);
 
 /**
  * Locale-independent conversion of ASCII isspace.
  */
-int av_isspace(int c);
+av_const int av_isspace(int c);
 
 /**
  * Locale-independent conversion of ASCII characters to uppercase.
  */
-static inline int av_toupper(int c)
+static inline av_const int av_toupper(int c)
 {
     if (c >= 'a' && c <= 'z')
         c ^= 0x20;
@@ -228,7 +228,7 @@
 /**
  * Locale-independent conversion of ASCII characters to lowercase.
  */
-static inline int av_tolower(int c)
+static inline av_const int av_tolower(int c)
 {
     if (c >= 'A' && c <= 'Z')
         c ^= 0x20;
@@ -238,7 +238,7 @@
 /**
  * Locale-independent conversion of ASCII isxdigit.
  */
-int av_isxdigit(int c);
+av_const int av_isxdigit(int c);
 
 /**
  * Locale-independent case-insensitive compare.
diff --git a/libavutil/bprint.h b/libavutil/bprint.h
index d1682fc..c09b1ac 100644
--- a/libavutil/bprint.h
+++ b/libavutil/bprint.h
@@ -30,9 +30,13 @@
  * Define a structure with extra padding to a fixed size
  * This helps ensuring binary compatibility with future versions.
  */
-#define FF_PAD_STRUCTURE(size, ...) \
+
+#define FF_PAD_STRUCTURE(name, size, ...) \
+struct ff_pad_helper_##name { __VA_ARGS__ }; \
+typedef struct name { \
     __VA_ARGS__ \
-    char reserved_padding[size - sizeof(struct { __VA_ARGS__ })];
+    char reserved_padding[size - sizeof(struct ff_pad_helper_##name)]; \
+} name;
 
 /**
  * Buffer to print data progressively
@@ -74,15 +78,14 @@
  * internal buffer is large enough to hold a reasonable paragraph of text,
  * such as the current paragraph.
  */
-typedef struct AVBPrint {
-    FF_PAD_STRUCTURE(1024,
+
+FF_PAD_STRUCTURE(AVBPrint, 1024,
     char *str;         /**< string so far */
     unsigned len;      /**< length so far */
     unsigned size;     /**< allocated memory */
     unsigned size_max; /**< maximum allocated memory */
     char reserved_internal_buffer[1];
-    )
-} AVBPrint;
+)
 
 /**
  * Convenience macros for special values for av_bprint_init() size_max
diff --git a/libavutil/buffer.c b/libavutil/buffer.c
index e9bf54b..b114afc 100644
--- a/libavutil/buffer.c
+++ b/libavutil/buffer.c
@@ -23,6 +23,7 @@
 #include "buffer_internal.h"
 #include "common.h"
 #include "mem.h"
+#include "thread.h"
 
 AVBufferRef *av_buffer_create(uint8_t *data, int size,
                               void (*free)(void *opaque, uint8_t *data),
@@ -209,6 +210,8 @@
     if (!pool)
         return NULL;
 
+    ff_mutex_init(&pool->mutex, NULL);
+
     pool->size     = size;
     pool->alloc    = alloc ? alloc : av_buffer_alloc;
 
@@ -230,6 +233,7 @@
         buf->free(buf->opaque, buf->data);
         av_freep(&buf);
     }
+    ff_mutex_destroy(&pool->mutex);
     av_freep(&pool);
 }
 
@@ -290,7 +294,15 @@
     if(CONFIG_MEMORY_POISONING)
         memset(buf->data, FF_MEMORY_POISON, pool->size);
 
+#if USE_ATOMICS
     add_to_pool(buf);
+#else
+    ff_mutex_lock(&pool->mutex);
+    buf->next = pool->pool;
+    pool->pool = buf;
+    ff_mutex_unlock(&pool->mutex);
+#endif
+
     if (!avpriv_atomic_int_add_and_fetch(&pool->refcount, -1))
         buffer_pool_free(pool);
 }
@@ -320,8 +332,10 @@
     ret->buffer->opaque = buf;
     ret->buffer->free   = pool_release_buffer;
 
+#if USE_ATOMICS
     avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
     avpriv_atomic_int_add_and_fetch(&pool->nb_allocated, 1);
+#endif
 
     return ret;
 }
@@ -331,6 +345,7 @@
     AVBufferRef *ret;
     BufferPoolEntry *buf;
 
+#if USE_ATOMICS
     /* check whether the pool is empty */
     buf = get_pool(pool);
     if (!buf && pool->refcount <= pool->nb_allocated) {
@@ -352,7 +367,24 @@
         add_to_pool(buf);
         return NULL;
     }
-    avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
+#else
+    ff_mutex_lock(&pool->mutex);
+    buf = pool->pool;
+    if (buf) {
+        ret = av_buffer_create(buf->data, pool->size, pool_release_buffer,
+                               buf, 0);
+        if (ret) {
+            pool->pool = buf->next;
+            buf->next = NULL;
+        }
+    } else {
+        ret = pool_alloc_buffer(pool);
+    }
+    ff_mutex_unlock(&pool->mutex);
+#endif
+
+    if (ret)
+        avpriv_atomic_int_add_and_fetch(&pool->refcount, 1);
 
     return ret;
 }
diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h
index c291908..e653048 100644
--- a/libavutil/buffer_internal.h
+++ b/libavutil/buffer_internal.h
@@ -22,6 +22,7 @@
 #include <stdint.h>
 
 #include "buffer.h"
+#include "thread.h"
 
 /**
  * The buffer is always treated as read-only.
@@ -68,11 +69,12 @@
     void (*free)(void *opaque, uint8_t *data);
 
     AVBufferPool *pool;
-    struct BufferPoolEntry * volatile next;
+    struct BufferPoolEntry *next;
 } BufferPoolEntry;
 
 struct AVBufferPool {
-    BufferPoolEntry * volatile pool;
+    AVMutex mutex;
+    BufferPoolEntry *pool;
 
     /*
      * This is used to track when the pool is to be freed.
diff --git a/libavutil/dict.c b/libavutil/dict.c
index 475e906..2983ea5 100644
--- a/libavutil/dict.c
+++ b/libavutil/dict.c
@@ -24,6 +24,7 @@
 #include "dict.h"
 #include "internal.h"
 #include "mem.h"
+#include "bprint.h"
 
 struct AVDictionary {
     int count;
@@ -35,7 +36,7 @@
     return m ? m->count : 0;
 }
 
-AVDictionaryEntry *av_dict_get(FF_CONST_AVUTIL53 AVDictionary *m, const char *key,
+AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
                                const AVDictionaryEntry *prev, int flags)
 {
     unsigned int i, j;
@@ -200,10 +201,99 @@
     av_freep(pm);
 }
 
-void av_dict_copy(AVDictionary **dst, FF_CONST_AVUTIL53 AVDictionary *src, int flags)
+void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
 {
     AVDictionaryEntry *t = NULL;
 
     while ((t = av_dict_get(src, "", t, AV_DICT_IGNORE_SUFFIX)))
         av_dict_set(dst, t->key, t->value, flags);
 }
+
+int av_dict_get_string(const AVDictionary *m, char **buffer,
+                       const char key_val_sep, const char pairs_sep)
+{
+    AVDictionaryEntry *t = NULL;
+    AVBPrint bprint;
+    int cnt = 0;
+    char special_chars[] = {pairs_sep, key_val_sep, '\0'};
+
+    if (!buffer || pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
+        pairs_sep == '\\' || key_val_sep == '\\')
+        return AVERROR(EINVAL);
+
+    if (!av_dict_count(m)) {
+        *buffer = av_strdup("");
+        return *buffer ? 0 : AVERROR(ENOMEM);
+    }
+
+    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+    while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
+        if (cnt++)
+            av_bprint_append_data(&bprint, &pairs_sep, 1);
+        av_bprint_escape(&bprint, t->key, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+        av_bprint_append_data(&bprint, &key_val_sep, 1);
+        av_bprint_escape(&bprint, t->value, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+    }
+    return av_bprint_finalize(&bprint, buffer);
+}
+
+#ifdef TEST
+static void print_dict(const AVDictionary *m)
+{
+    AVDictionaryEntry *t = NULL;
+    while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX)))
+        printf("%s %s   ", t->key, t->value);
+    printf("\n");
+}
+
+static void test_separators(const AVDictionary *m, const char pair, const char val)
+{
+    AVDictionary *dict = NULL;
+    char pairs[] = {pair , '\0'};
+    char vals[]  = {val, '\0'};
+
+    char *buffer = NULL;
+    av_dict_copy(&dict, m, 0);
+    print_dict(dict);
+    av_dict_get_string(dict, &buffer, val, pair);
+    printf("%s\n", buffer);
+    av_dict_free(&dict);
+    av_dict_parse_string(&dict, buffer, vals, pairs, 0);
+    av_freep(&buffer);
+    print_dict(dict);
+    av_dict_free(&dict);
+}
+
+int main(void)
+{
+    AVDictionary *dict = NULL;
+    char *buffer = NULL;
+
+    printf("Testing av_dict_get_string() and av_dict_parse_string()\n");
+    av_dict_get_string(dict, &buffer, '=', ',');
+    printf("%s\n", buffer);
+    av_freep(&buffer);
+    av_dict_set(&dict, "aaa", "aaa", 0);
+    av_dict_set(&dict, "b,b", "bbb", 0);
+    av_dict_set(&dict, "c=c", "ccc", 0);
+    av_dict_set(&dict, "ddd", "d,d", 0);
+    av_dict_set(&dict, "eee", "e=e", 0);
+    av_dict_set(&dict, "f,f", "f=f", 0);
+    av_dict_set(&dict, "g=g", "g,g", 0);
+    test_separators(dict, ',', '=');
+    av_dict_free(&dict);
+    av_dict_set(&dict, "aaa", "aaa", 0);
+    av_dict_set(&dict, "bbb", "bbb", 0);
+    av_dict_set(&dict, "ccc", "ccc", 0);
+    av_dict_set(&dict, "\\,=\'\"", "\\,=\'\"", 0);
+    test_separators(dict, '"',  '=');
+    test_separators(dict, '\'', '=');
+    test_separators(dict, ',', '"');
+    test_separators(dict, ',', '\'');
+    test_separators(dict, '\'', '"');
+    test_separators(dict, '"', '\'');
+    av_dict_free(&dict);
+
+    return 0;
+}
+#endif
diff --git a/libavutil/dict.h b/libavutil/dict.h
index 9b3381b..f2df687 100644
--- a/libavutil/dict.h
+++ b/libavutil/dict.h
@@ -101,7 +101,7 @@
  * @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved
  * @return found entry or NULL in case no matching entry was found in the dictionary
  */
-AVDictionaryEntry *av_dict_get(FF_CONST_AVUTIL53 AVDictionary *m, const char *key,
+AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
                                const AVDictionaryEntry *prev, int flags);
 
 /**
@@ -163,7 +163,7 @@
  * @param flags flags to use when setting entries in *dst
  * @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag
  */
-void av_dict_copy(AVDictionary **dst, FF_CONST_AVUTIL53 AVDictionary *src, int flags);
+void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);
 
 /**
  * Free all the memory allocated for an AVDictionary struct
@@ -172,6 +172,24 @@
 void av_dict_free(AVDictionary **m);
 
 /**
+ * Get dictionary entries as a string.
+ *
+ * Create a string containing dictionary's entries.
+ * Such string may be passed back to av_dict_parse_string().
+ * @note String is escaped with backslashes ('\').
+ *
+ * @param[in]  m             dictionary
+ * @param[out] buffer        Pointer to buffer that will be allocated with string containg entries.
+ *                           Buffer must be freed by the caller when is no longer needed.
+ * @param[in]  key_val_sep   character used to separate key from value
+ * @param[in]  pairs_sep     character used to separate two pairs from each other
+ * @return                   >= 0 on success, negative on error
+ * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same.
+ */
+int av_dict_get_string(const AVDictionary *m, char **buffer,
+                       const char key_val_sep, const char pairs_sep);
+
+/**
  * @}
  */
 
diff --git a/libavutil/fifo.c b/libavutil/fifo.c
index 77391ee..4ff3194 100644
--- a/libavutil/fifo.c
+++ b/libavutil/fifo.c
@@ -74,12 +74,12 @@
     f->wndx = f->rndx = 0;
 }
 
-int av_fifo_size(FF_CONST_AVUTIL53 AVFifoBuffer *f)
+int av_fifo_size(const AVFifoBuffer *f)
 {
     return (uint32_t)(f->wndx - f->rndx);
 }
 
-int av_fifo_space(FF_CONST_AVUTIL53 AVFifoBuffer *f)
+int av_fifo_space(const AVFifoBuffer *f)
 {
     return f->end - f->buffer - av_fifo_size(f);
 }
diff --git a/libavutil/fifo.h b/libavutil/fifo.h
index dda7dd2..f3bdcbc 100644
--- a/libavutil/fifo.h
+++ b/libavutil/fifo.h
@@ -73,7 +73,7 @@
  * @param f AVFifoBuffer to read from
  * @return size
  */
-int av_fifo_size(FF_CONST_AVUTIL53 AVFifoBuffer *f);
+int av_fifo_size(const AVFifoBuffer *f);
 
 /**
  * Return the amount of space in bytes in the AVFifoBuffer, that is the
@@ -81,7 +81,7 @@
  * @param f AVFifoBuffer to write into
  * @return size
  */
-int av_fifo_space(FF_CONST_AVUTIL53 AVFifoBuffer *f);
+int av_fifo_space(const AVFifoBuffer *f);
 
 /**
  * Feed data from an AVFifoBuffer to a user-supplied callback.
diff --git a/libavutil/file.h b/libavutil/file.h
index a7364fe..1cae295 100644
--- a/libavutil/file.h
+++ b/libavutil/file.h
@@ -55,7 +55,8 @@
  * Wrapper to work around the lack of mkstemp() on mingw.
  * Also, tries to create file in /tmp first, if possible.
  * *prefix can be a character constant; *filename will be allocated internally.
- * @return file descriptor of opened file (or -1 on error)
+ * @return file descriptor of opened file (or negative value corresponding to an
+ * AVERROR code on error)
  * and opened file name in **filename.
  * @note On very old libcs it is necessary to set a secure umask before
  *       calling this, av_tempfile() can't call umask itself as it is used in
diff --git a/libavutil/file_open.c b/libavutil/file_open.c
index f3164eb..3f9a67c 100644
--- a/libavutil/file_open.c
+++ b/libavutil/file_open.c
@@ -37,23 +37,18 @@
 #include <windows.h>
 #include <share.h>
 #include <errno.h>
+#include "wchar_filename.h"
 
 static int win32_open(const char *filename_utf8, int oflag, int pmode)
 {
     int fd;
-    int num_chars;
     wchar_t *filename_w;
 
     /* convert UTF-8 to wide chars */
-    num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0);
-    if (num_chars <= 0)
-        goto fallback;
-    filename_w = av_mallocz_array(num_chars, sizeof(wchar_t));
-    if (!filename_w) {
-        errno = ENOMEM;
+    if (utf8towchar(filename_utf8, &filename_w))
         return -1;
-    }
-    MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, filename_w, num_chars);
+    if (!filename_w)
+        goto fallback;
 
     fd = _wsopen(filename_w, oflag, SH_DENYNO, pmode);
     av_freep(&filename_w);
diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c
index 78de1a1..467d7a7 100644
--- a/libavutil/float_dsp.c
+++ b/libavutil/float_dsp.c
@@ -22,6 +22,7 @@
 #include "config.h"
 #include "attributes.h"
 #include "float_dsp.h"
+#include "mem.h"
 
 static void vector_fmul_c(float *dst, const float *src0, const float *src1,
                           int len)
@@ -139,6 +140,15 @@
         ff_float_dsp_init_mips(fdsp);
 }
 
+av_cold AVFloatDSPContext *avpriv_float_dsp_alloc(int bit_exact)
+{
+    AVFloatDSPContext *ret = av_mallocz(sizeof(AVFloatDSPContext));
+    if (ret)
+        avpriv_float_dsp_init(ret, bit_exact);
+    return ret;
+}
+
+
 #ifdef TEST
 
 #include <float.h>
@@ -158,7 +168,6 @@
 #include "internal.h"
 #include "lfg.h"
 #include "log.h"
-#include "mem.h"
 #include "random_seed.h"
 
 #define LEN 240
diff --git a/libavutil/float_dsp.h b/libavutil/float_dsp.h
index 7fc851b..543f701 100644
--- a/libavutil/float_dsp.h
+++ b/libavutil/float_dsp.h
@@ -185,4 +185,11 @@
 void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp);
 void ff_float_dsp_init_mips(AVFloatDSPContext *fdsp);
 
+/**
+ * Allocate a float DSP context.
+ *
+ * @param strict  setting to non-zero avoids using functions which may not be IEEE-754 compliant
+ */
+AVFloatDSPContext *avpriv_float_dsp_alloc(int strict);
+
 #endif /* AVUTIL_FLOAT_DSP_H */
diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c
index 00b2031..7f3032b 100644
--- a/libavutil/imgutils.c
+++ b/libavutil/imgutils.c
@@ -331,9 +331,6 @@
     for (i = 0; i < 4; i++)
         dst_linesize[i] = FFALIGN(dst_linesize[i], align);
 
-    if ((ret = av_image_fill_pointers(dst_data, pix_fmt, width, NULL, dst_linesize)) < 0)
-        return ret;
-
     return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
 }
 
diff --git a/libavutil/internal.h b/libavutil/internal.h
index 612b5f2..77af6f9 100644
--- a/libavutil/internal.h
+++ b/libavutil/internal.h
@@ -80,9 +80,6 @@
 #    define FF_ENABLE_DEPRECATION_WARNINGS
 #endif
 
-#ifndef INT_BIT
-#    define INT_BIT (CHAR_BIT * sizeof(int))
-#endif
 
 #define FF_MEMORY_POISON 0x2a
 
diff --git a/libavutil/libm.h b/libavutil/libm.h
index 28d5df8..6c17b28 100644
--- a/libavutil/libm.h
+++ b/libavutil/libm.h
@@ -82,16 +82,6 @@
 #define exp2f(x) ((float)exp2(x))
 #endif /* HAVE_EXP2F */
 
-#if !HAVE_FMINF
-#undef fminf
-static av_always_inline av_const float fminf(float x, float y)
-{
-    //Note, the NaN special case is needed for C spec compliance, it should be
-    //optimized away if the users compiler is configured to assume no NaN
-    return x > y ? y : (x == x ? x : y);
-}
-#endif
-
 #if !HAVE_ISINF
 static av_always_inline av_const int isinf(float x)
 {
diff --git a/libavutil/opt.c b/libavutil/opt.c
index 6aabfe3..d873bd2 100644
--- a/libavutil/opt.c
+++ b/libavutil/opt.c
@@ -37,19 +37,23 @@
 #include "pixdesc.h"
 #include "mathematics.h"
 #include "samplefmt.h"
+#include "bprint.h"
 
 #include <float.h>
 
 #if FF_API_OLD_AVOPTIONS
-const AVOption *av_next_option(void *obj, const AVOption *last)
+const AVOption *av_next_option(FF_CONST_AVUTIL55 void *obj, const AVOption *last)
 {
     return av_opt_next(obj, last);
 }
 #endif
 
-const AVOption *av_opt_next(void *obj, const AVOption *last)
+const AVOption *av_opt_next(FF_CONST_AVUTIL55 void *obj, const AVOption *last)
 {
-    AVClass *class = *(AVClass**)obj;
+    const AVClass *class;
+    if (!obj)
+        return NULL;
+    class = *(const AVClass**)obj;
     if (!last && class && class->option && class->option[0].name)
         return class->option;
     if (last && last[1].name)
@@ -57,7 +61,7 @@
     return NULL;
 }
 
-static int read_number(const AVOption *o, void *dst, double *num, int *den, int64_t *intnum)
+static int read_number(const AVOption *o, const void *dst, double *num, int *den, int64_t *intnum)
 {
     switch (o->type) {
     case AV_OPT_TYPE_FLAGS:     *intnum = *(unsigned int*)dst;return 0;
@@ -126,11 +130,14 @@
 {
     int *lendst = (int *)(dst + 1);
     uint8_t *bin, *ptr;
-    int len = strlen(val);
+    int len;
 
     av_freep(dst);
     *lendst = 0;
 
+    if (!val || !(len = strlen(val)))
+        return 0;
+
     if (len & 1)
         return AVERROR(EINVAL);
     len /= 2;
@@ -711,6 +718,10 @@
             return AVERROR(EINVAL);
         if (!(*out_val = av_malloc(len*2 + 1)))
             return AVERROR(ENOMEM);
+        if (!len) {
+            *out_val[0] = '\0';
+            return 0;
+        }
         bin = *(uint8_t**)dst;
         for (i = 0; i < len; i++)
             snprintf(*out_val + i*2, 3, "%02X", bin[i]);
@@ -726,12 +737,14 @@
         break;
     case AV_OPT_TYPE_DURATION:
         i64 = *(int64_t *)dst;
-        ret = snprintf(buf, sizeof(buf), "%"PRIi64"d:%02d:%02d.%06d",
+        ret = snprintf(buf, sizeof(buf), "%"PRIi64":%02d:%02d.%06d",
                        i64 / 3600000000, (int)((i64 / 60000000) % 60),
                        (int)((i64 / 1000000) % 60), (int)(i64 % 1000000));
         break;
     case AV_OPT_TYPE_COLOR:
-        ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x", ((int *)dst)[0], ((int *)dst)[1], ((int *)dst)[2], ((int *)dst)[3]);
+        ret = snprintf(buf, sizeof(buf), "0x%02x%02x%02x%02x",
+                       (int)((uint8_t *)dst)[0], (int)((uint8_t *)dst)[1],
+                       (int)((uint8_t *)dst)[2], (int)((uint8_t *)dst)[3]);
         break;
     case AV_OPT_TYPE_CHANNEL_LAYOUT:
         i64 = *(int64_t *)dst;
@@ -1222,6 +1235,8 @@
                 write_number(s, opt, dst, 1, 1, opt->default_val.i64);
                 break;
             case AV_OPT_TYPE_BINARY:
+                set_string_binary(s, opt, opt->default_val.str, dst);
+                break;
             case AV_OPT_TYPE_DICT:
                 /* Cannot set defaults for these types */
             break;
@@ -1558,7 +1573,7 @@
     return 0;
 }
 
-int av_opt_copy(void *dst, void *src)
+int av_opt_copy(void *dst, FF_CONST_AVUTIL55 void *src)
 {
     const AVOption *o = NULL;
     const AVClass *c;
@@ -1595,6 +1610,15 @@
             *(int*)(field_dst8 + 1) = len;
         } else if (o->type == AV_OPT_TYPE_CONST) {
             // do nothing
+        } else if (o->type == AV_OPT_TYPE_DICT) {
+            AVDictionary **sdict = (AVDictionary **) field_src;
+            AVDictionary **ddict = (AVDictionary **) field_dst;
+            if (*sdict != *ddict)
+                av_dict_free(ddict);
+            *ddict = NULL;
+            av_dict_copy(ddict, *sdict, 0);
+            if (av_dict_count(*sdict) != av_dict_count(*ddict))
+                ret = AVERROR(ENOMEM);
         } else {
             memcpy(field_dst, field_src, opt_size(o->type));
         }
@@ -1712,6 +1736,156 @@
     av_freep(rangesp);
 }
 
+int av_opt_is_set_to_default(void *obj, const AVOption *o)
+{
+    int64_t i64;
+    double d, d2;
+    float f;
+    AVRational q;
+    int ret, w, h;
+    char *str;
+    void *dst;
+
+    if (!o || !obj)
+        return AVERROR(EINVAL);
+
+    dst = ((uint8_t*)obj) + o->offset;
+
+    switch (o->type) {
+    case AV_OPT_TYPE_CONST:
+        return 1;
+    case AV_OPT_TYPE_FLAGS:
+    case AV_OPT_TYPE_PIXEL_FMT:
+    case AV_OPT_TYPE_SAMPLE_FMT:
+    case AV_OPT_TYPE_INT:
+    case AV_OPT_TYPE_CHANNEL_LAYOUT:
+    case AV_OPT_TYPE_DURATION:
+    case AV_OPT_TYPE_INT64:
+        read_number(o, dst, NULL, NULL, &i64);
+        return o->default_val.i64 == i64;
+    case AV_OPT_TYPE_STRING:
+        str = *(char **)dst;
+        if (str == o->default_val.str) //2 NULLs
+            return 1;
+        if (!str || !o->default_val.str) //1 NULL
+            return 0;
+        return !strcmp(str, o->default_val.str);
+    case AV_OPT_TYPE_DOUBLE:
+        read_number(o, dst, &d, NULL, NULL);
+        return o->default_val.dbl == d;
+    case AV_OPT_TYPE_FLOAT:
+        read_number(o, dst, &d, NULL, NULL);
+        f = o->default_val.dbl;
+        d2 = f;
+        return d2 == d;
+    case AV_OPT_TYPE_RATIONAL:
+        q = av_d2q(o->default_val.dbl, INT_MAX);
+        return !av_cmp_q(*(AVRational*)dst, q);
+    case AV_OPT_TYPE_BINARY: {
+        struct {
+            uint8_t *data;
+            int size;
+        } tmp = {0};
+        int opt_size = *(int *)((void **)dst + 1);
+        void *opt_ptr = *(void **)dst;
+        if (!opt_ptr && (!o->default_val.str || !strlen(o->default_val.str)))
+            return 1;
+        if (opt_ptr && o->default_val.str && !strlen(o->default_val.str))
+            return 0;
+        if (opt_size != strlen(o->default_val.str) / 2)
+            return 0;
+        ret = set_string_binary(NULL, NULL, o->default_val.str, &tmp.data);
+        if (!ret)
+            ret = !memcmp(opt_ptr, tmp.data, tmp.size);
+        av_free(tmp.data);
+        return ret;
+    }
+    case AV_OPT_TYPE_DICT:
+        /* Binary and dict have not default support yet. Any pointer is not default. */
+        return !!(*(void **)dst);
+    case AV_OPT_TYPE_IMAGE_SIZE:
+        if (!o->default_val.str || !strcmp(o->default_val.str, "none"))
+            w = h = 0;
+        else if ((ret = av_parse_video_size(&w, &h, o->default_val.str)) < 0)
+            return ret;
+        return (w == *(int *)dst) && (h == *((int *)dst+1));
+    case AV_OPT_TYPE_VIDEO_RATE:
+        q = (AVRational){0, 0};
+        if (o->default_val.str)
+            av_parse_video_rate(&q, o->default_val.str);
+        return !av_cmp_q(*(AVRational*)dst, q);
+    case AV_OPT_TYPE_COLOR: {
+        uint8_t color[4] = {0, 0, 0, 0};
+        if (o->default_val.str)
+            av_parse_color(color, o->default_val.str, -1, NULL);
+        return !memcmp(color, dst, sizeof(color));
+    }
+    default:
+        av_log(obj, AV_LOG_WARNING, "Not supported option type: %d, option name: %s\n", o->type, o->name);
+        break;
+    }
+    return AVERROR_PATCHWELCOME;
+}
+
+int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags)
+{
+    const AVOption *o;
+    void *target;
+    if (!obj)
+        return AVERROR(EINVAL);
+    o = av_opt_find2(obj, name, NULL, 0, search_flags, &target);
+    if (!o)
+        return AVERROR_OPTION_NOT_FOUND;
+    return av_opt_is_set_to_default(target, o);
+}
+
+int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
+                     const char key_val_sep, const char pairs_sep)
+{
+    const AVOption *o = NULL;
+    uint8_t *buf;
+    AVBPrint bprint;
+    int ret, cnt = 0;
+    const char special_chars[] = {pairs_sep, key_val_sep, '\0'};
+
+    if (pairs_sep == '\0' || key_val_sep == '\0' || pairs_sep == key_val_sep ||
+        pairs_sep == '\\' || key_val_sep == '\\') {
+        av_log(obj, AV_LOG_ERROR, "Invalid separator(s) found.");
+        return AVERROR(EINVAL);
+    }
+
+    if (!obj || !buffer)
+        return AVERROR(EINVAL);
+
+    *buffer = NULL;
+    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
+
+    while (o = av_opt_next(obj, o)) {
+        if (o->type == AV_OPT_TYPE_CONST)
+            continue;
+        if ((flags & AV_OPT_SERIALIZE_OPT_FLAGS_EXACT) && o->flags != opt_flags)
+            continue;
+        else if (((o->flags & opt_flags) != opt_flags))
+            continue;
+        if (flags & AV_OPT_SERIALIZE_SKIP_DEFAULTS && av_opt_is_set_to_default(obj, o) > 0)
+            continue;
+        if ((ret = av_opt_get(obj, o->name, 0, &buf)) < 0) {
+            av_bprint_finalize(&bprint, NULL);
+            return ret;
+        }
+        if (buf) {
+            if (cnt++)
+                av_bprint_append_data(&bprint, &pairs_sep, 1);
+            av_bprint_escape(&bprint, o->name, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+            av_bprint_append_data(&bprint, &key_val_sep, 1);
+            av_bprint_escape(&bprint, buf, special_chars, AV_ESCAPE_MODE_BACKSLASH, 0);
+            av_freep(&buf);
+        }
+    }
+    av_bprint_finalize(&bprint, buffer);
+    return 0;
+}
+
 #ifdef TEST
 
 typedef struct TestContext
@@ -1729,6 +1903,16 @@
     int64_t duration;
     uint8_t color[4];
     int64_t channel_layout;
+    void *binary;
+    int binary_size;
+    void *binary1;
+    int binary_size1;
+    void *binary2;
+    int binary_size2;
+    int64_t num64;
+    float flt;
+    double dbl;
+    char *escape;
 } TestContext;
 
 #define OFFSET(x) offsetof(TestContext, x)
@@ -1739,20 +1923,27 @@
 
 static const AVOption test_options[]= {
 {"num",      "set num",        OFFSET(num),      AV_OPT_TYPE_INT,      {.i64 = 0},       0,        100                 },
-{"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {.i64 = 0},       0,        1                   },
-{"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 0},       0,        10                  },
+{"toggle",   "set toggle",     OFFSET(toggle),   AV_OPT_TYPE_INT,      {.i64 = 1},       0,        1                   },
+{"rational", "set rational",   OFFSET(rational), AV_OPT_TYPE_RATIONAL, {.dbl = 1},       0,        10                  },
 {"string",   "set string",     OFFSET(string),   AV_OPT_TYPE_STRING,   {.str = "default"}, CHAR_MIN, CHAR_MAX          },
-{"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {.i64 = 0},       0,        INT_MAX, 0, "flags" },
+{"escape",   "set escape str", OFFSET(escape),   AV_OPT_TYPE_STRING,   {.str = "\\=,"}, CHAR_MIN, CHAR_MAX             },
+{"flags",    "set flags",      OFFSET(flags),    AV_OPT_TYPE_FLAGS,    {.i64 = 1},       0,        INT_MAX, 0, "flags" },
 {"cool",     "set cool flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_COOL}, INT_MIN,  INT_MAX, 0, "flags" },
 {"lame",     "set lame flag ", 0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_LAME}, INT_MIN,  INT_MAX, 0, "flags" },
 {"mu",       "set mu flag ",   0,                AV_OPT_TYPE_CONST,    {.i64 = TEST_FLAG_MU},   INT_MIN,  INT_MAX, 0, "flags" },
-{"size",     "set size",       OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE,{0},             0,        0                   },
-{"pix_fmt",  "set pixfmt",     OFFSET(pix_fmt),  AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, INT_MAX},
-{"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_NONE}, -1, INT_MAX},
+{"size",     "set size",       OFFSET(w),        AV_OPT_TYPE_IMAGE_SIZE,{.str="200x300"},             0,        0                   },
+{"pix_fmt",  "set pixfmt",     OFFSET(pix_fmt),  AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_0BGR}, -1, INT_MAX},
+{"sample_fmt", "set samplefmt", OFFSET(sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64 = AV_SAMPLE_FMT_S16}, -1, INT_MAX},
 {"video_rate", "set videorate", OFFSET(video_rate), AV_OPT_TYPE_VIDEO_RATE,  {.str = "25"}, 0,     0                   },
-{"duration", "set duration",   OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX},
+{"duration", "set duration",   OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 1000}, 0, INT64_MAX},
 {"color", "set color",   OFFSET(color), AV_OPT_TYPE_COLOR, {.str = "pink"}, 0, 0},
 {"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = AV_CH_LAYOUT_HEXAGONAL}, 0, INT64_MAX},
+{"bin", "set binary value",    OFFSET(binary),   AV_OPT_TYPE_BINARY,   {.str="62696e00"}, 0,        0 },
+{"bin1", "set binary value",   OFFSET(binary1),  AV_OPT_TYPE_BINARY,   {.str=NULL},       0,        0 },
+{"bin2", "set binary value",   OFFSET(binary2),  AV_OPT_TYPE_BINARY,   {.str=""},         0,        0 },
+{"num64",    "set num 64bit",  OFFSET(num64),    AV_OPT_TYPE_INT64,    {.i64 = 1},        0,        100 },
+{"flt",      "set float",      OFFSET(flt),      AV_OPT_TYPE_FLOAT,    {.dbl = 1.0/3},    0,        100 },
+{"dbl",      "set double",     OFFSET(dbl),      AV_OPT_TYPE_DOUBLE,   {.dbl = 1.0/3},    0,        100 },
 {NULL},
 };
 
@@ -1771,6 +1962,79 @@
 {
     int i;
 
+    printf("Testing default values\n");
+    {
+        TestContext test_ctx = { 0 };
+        test_ctx.class = &test_class;
+        av_opt_set_defaults(&test_ctx);
+
+        printf("num=%d\n", test_ctx.num);
+        printf("toggle=%d\n", test_ctx.toggle);
+        printf("string=%s\n", test_ctx.string);
+        printf("escape=%s\n", test_ctx.escape);
+        printf("flags=%d\n", test_ctx.flags);
+        printf("rational=%d/%d\n", test_ctx.rational.num, test_ctx.rational.den);
+        printf("video_rate=%d/%d\n", test_ctx.video_rate.num, test_ctx.video_rate.den);
+        printf("width=%d height=%d\n", test_ctx.w, test_ctx.h);
+        printf("pix_fmt=%s\n", av_get_pix_fmt_name(test_ctx.pix_fmt));
+        printf("sample_fmt=%s\n", av_get_sample_fmt_name(test_ctx.sample_fmt));
+        printf("duration=%"PRId64"\n", test_ctx.duration);
+        printf("color=%d %d %d %d\n", test_ctx.color[0], test_ctx.color[1], test_ctx.color[2], test_ctx.color[3]);
+        printf("channel_layout=%"PRId64"=%"PRId64"\n", test_ctx.channel_layout, (int64_t)AV_CH_LAYOUT_HEXAGONAL);
+        if (test_ctx.binary)
+            printf("binary=%x %x %x %x\n", ((uint8_t*)test_ctx.binary)[0], ((uint8_t*)test_ctx.binary)[1], ((uint8_t*)test_ctx.binary)[2], ((uint8_t*)test_ctx.binary)[3]);
+        printf("binary_size=%d\n", test_ctx.binary_size);
+        printf("num64=%"PRId64"\n", test_ctx.num64);
+        printf("flt=%.6f\n", test_ctx.flt);
+        printf("dbl=%.6f\n", test_ctx.dbl);
+        av_opt_free(&test_ctx);
+    }
+
+    printf("\nTesting av_opt_is_set_to_default()\n");
+    {
+        int ret;
+        TestContext test_ctx = { 0 };
+        const AVOption *o = NULL;
+        test_ctx.class = &test_class;
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        while (o = av_opt_next(&test_ctx, o)) {
+            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
+            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
+        }
+        av_opt_set_defaults(&test_ctx);
+        while (o = av_opt_next(&test_ctx, o)) {
+            ret = av_opt_is_set_to_default_by_name(&test_ctx, o->name, 0);
+            printf("name:%10s default:%d error:%s\n", o->name, !!ret, ret < 0 ? av_err2str(ret) : "");
+        }
+        av_opt_free(&test_ctx);
+    }
+
+    printf("\nTest av_opt_serialize()\n");
+    {
+        TestContext test_ctx = { 0 };
+        char *buf;
+        test_ctx.class = &test_class;
+
+        av_log_set_level(AV_LOG_QUIET);
+
+        av_opt_set_defaults(&test_ctx);
+        if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
+            printf("%s\n", buf);
+            av_opt_free(&test_ctx);
+            memset(&test_ctx, 0, sizeof(test_ctx));
+            test_ctx.class = &test_class;
+            av_set_options_string(&test_ctx, buf, "=", ",");
+            av_free(buf);
+            if (av_opt_serialize(&test_ctx, 0, 0, &buf, '=', ',') >= 0) {
+                printf("%s\n", buf);
+                av_free(buf);
+            }
+        }
+        av_opt_free(&test_ctx);
+    }
+
     printf("\nTesting av_set_options_string()\n");
     {
         TestContext test_ctx = { 0 };
@@ -1816,18 +2080,37 @@
             "color=0x42FF07AA",
             "cl=stereo+downmix",
             "cl=foo",
+            "bin=boguss",
+            "bin=111",
+            "bin=ffff",
+            "num64=bogus",
+            "num64=44",
+            "num64=44.4",
+            "num64=-1",
+            "num64=101",
+            "flt=bogus",
+            "flt=2",
+            "flt=2.2",
+            "flt=-1",
+            "flt=101",
+            "dbl=bogus",
+            "dbl=2",
+            "dbl=2.2",
+            "dbl=-1",
+            "dbl=101",
         };
 
         test_ctx.class = &test_class;
         av_opt_set_defaults(&test_ctx);
 
-        av_log_set_level(AV_LOG_DEBUG);
+        av_log_set_level(AV_LOG_QUIET);
 
         for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
             av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
             if (av_set_options_string(&test_ctx, options[i], "=", ":") < 0)
-                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
-            printf("\n");
+                printf("Error '%s'\n", options[i]);
+            else
+                printf("OK    '%s'\n", options[i]);
         }
         av_opt_free(&test_ctx);
     }
@@ -1851,13 +2134,14 @@
         test_ctx.class = &test_class;
         av_opt_set_defaults(&test_ctx);
 
-        av_log_set_level(AV_LOG_DEBUG);
+        av_log_set_level(AV_LOG_QUIET);
 
         for (i=0; i < FF_ARRAY_ELEMS(options); i++) {
             av_log(&test_ctx, AV_LOG_DEBUG, "Setting options string '%s'\n", options[i]);
             if (av_opt_set_from_string(&test_ctx, options[i], shorthand, "=", ":") < 0)
-                av_log(&test_ctx, AV_LOG_ERROR, "Error setting options string: '%s'\n", options[i]);
-            printf("\n");
+                printf("Error '%s'\n", options[i]);
+            else
+                printf("OK    '%s'\n", options[i]);
         }
         av_opt_free(&test_ctx);
     }
diff --git a/libavutil/opt.h b/libavutil/opt.h
index 1b72a10..5fc8a9b 100644
--- a/libavutil/opt.h
+++ b/libavutil/opt.h
@@ -33,6 +33,7 @@
 #include "log.h"
 #include "pixfmt.h"
 #include "samplefmt.h"
+#include "version.h"
 
 /**
  * @defgroup avoptions AVOptions
@@ -416,7 +417,7 @@
 AVRational av_get_q(void *obj, const char *name, const AVOption **o_out);
 int64_t av_get_int(void *obj, const char *name, const AVOption **o_out);
 attribute_deprecated const char *av_get_string(void *obj, const char *name, const AVOption **o_out, char *buf, int buf_len);
-attribute_deprecated const AVOption *av_next_option(void *obj, const AVOption *last);
+attribute_deprecated const AVOption *av_next_option(FF_CONST_AVUTIL55 void *obj, const AVOption *last);
 #endif
 
 /**
@@ -456,7 +457,7 @@
  * @return the number of successfully set key/value pairs, or a negative
  * value corresponding to an AVERROR code in case of error:
  * AVERROR(EINVAL) if opts cannot be parsed,
- * the error code issued by av_set_string3() if a key/value pair
+ * the error code issued by av_opt_set() if a key/value pair
  * cannot be set
  */
 int av_set_options_string(void *ctx, const char *opts,
@@ -633,7 +634,7 @@
  *         was found.
  *
  * @note Options found with AV_OPT_SEARCH_CHILDREN flag may not be settable
- * directly with av_set_string3(). Use special calls which take an options
+ * directly with av_opt_set(). Use special calls which take an options
  * AVDictionary (e.g. avformat_open_input()) to set options found with this
  * flag.
  */
@@ -673,7 +674,7 @@
  *             or NULL
  * @return next AVOption or NULL
  */
-const AVOption *av_opt_next(void *obj, const AVOption *prev);
+const AVOption *av_opt_next(FF_CONST_AVUTIL55 void *obj, const AVOption *prev);
 
 /**
  * Iterate over AVOptions-enabled children of obj.
@@ -815,7 +816,17 @@
  */
 int av_opt_query_ranges(AVOptionRanges **, void *obj, const char *key, int flags);
 
-int av_opt_copy(void *dest, void *src);
+/**
+ * Copy options from src object into dest object.
+ *
+ * Options that require memory allocation (e.g. string or binary) are malloc'ed in dest object.
+ * Original memory allocated for such options is freed unless both src and dest options points to the same memory.
+ *
+ * @param dest Object to copy from
+ * @param src  Object to copy into
+ * @return 0 on success, negative on error
+ */
+int av_opt_copy(void *dest, FF_CONST_AVUTIL55 void *src);
 
 /**
  * Get a default list of allowed ranges for the given option.
@@ -834,6 +845,56 @@
 int av_opt_query_ranges_default(AVOptionRanges **, void *obj, const char *key, int flags);
 
 /**
+ * Check if given option is set to its default value.
+ *
+ * Options o must belong to the obj. This function must not be called to check child's options state.
+ * @see av_opt_is_set_to_default_by_name().
+ *
+ * @param obj  AVClass object to check option on
+ * @param o    option to be checked
+ * @return     >0 when option is set to its default,
+ *              0 when option is not set its default,
+ *             <0 on error
+ */
+int av_opt_is_set_to_default(void *obj, const AVOption *o);
+
+/**
+ * Check if given option is set to its default value.
+ *
+ * @param obj          AVClass object to check option on
+ * @param name         option name
+ * @param search_flags combination of AV_OPT_SEARCH_*
+ * @return             >0 when option is set to its default,
+ *                     0 when option is not set its default,
+ *                     <0 on error
+ */
+int av_opt_is_set_to_default_by_name(void *obj, const char *name, int search_flags);
+
+
+#define AV_OPT_SERIALIZE_SKIP_DEFAULTS              0x00000001  ///< Serialize options that are not set to default values only.
+#define AV_OPT_SERIALIZE_OPT_FLAGS_EXACT            0x00000002  ///< Serialize options that exactly match opt_flags only.
+
+/**
+ * Serialize object's options.
+ *
+ * Create a string containing object's serialized options.
+ * Such string may be passed back to av_opt_set_from_string() in order to restore option values.
+ * A key/value or pairs separator occurring in the serialized value or
+ * name string are escaped through the av_escape() function.
+ *
+ * @param[in]  obj           AVClass object to serialize
+ * @param[in]  opt_flags     serialize options with all the specified flags set (AV_OPT_FLAG)
+ * @param[in]  flags         combination of AV_OPT_SERIALIZE_* flags
+ * @param[out] buffer        Pointer to buffer that will be allocated with string containg serialized options.
+ *                           Buffer must be freed by the caller when is no longer needed.
+ * @param[in]  key_val_sep   character used to separate key from value
+ * @param[in]  pairs_sep     character used to separate two pairs from each other
+ * @return                   >= 0 on success, negative on error
+ * @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same.
+ */
+int av_opt_serialize(void *obj, int opt_flags, int flags, char **buffer,
+                     const char key_val_sep, const char pairs_sep);
+/**
  * @}
  */
 
diff --git a/libavutil/ppc/util_altivec.h b/libavutil/ppc/util_altivec.h
index 2c0ad5f..51a4e8c 100644
--- a/libavutil/ppc/util_altivec.h
+++ b/libavutil/ppc/util_altivec.h
@@ -46,9 +46,21 @@
 #define WORD_s1 0x14,0x15,0x16,0x17
 #define WORD_s2 0x18,0x19,0x1a,0x1b
 #define WORD_s3 0x1c,0x1d,0x1e,0x1f
-
 #define vcprm(a,b,c,d) (const vector unsigned char){WORD_ ## a, WORD_ ## b, WORD_ ## c, WORD_ ## d}
 
+#define SWP_W2S0 0x02,0x03,0x00,0x01
+#define SWP_W2S1 0x06,0x07,0x04,0x05
+#define SWP_W2S2 0x0a,0x0b,0x08,0x09
+#define SWP_W2S3 0x0e,0x0f,0x0c,0x0d
+#define SWP_W2Ss0 0x12,0x13,0x10,0x11
+#define SWP_W2Ss1 0x16,0x17,0x14,0x15
+#define SWP_W2Ss2 0x1a,0x1b,0x18,0x19
+#define SWP_W2Ss3 0x1e,0x1f,0x1c,0x1d
+#define vcswapi2s(a,b,c,d) (const vector unsigned char){SWP_W2S ## a, SWP_W2S ## b, SWP_W2S ## c, SWP_W2S ## d}
+
+#define vcswapc() \
+  (const vector unsigned char){0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00}
+
 
 // Transpose 8x8 matrix of 16-bit elements (in-place)
 #define TRANSPOSE8(a,b,c,d,e,f,g,h) \
@@ -85,29 +97,68 @@
 } while (0)
 
 
+#if HAVE_BIGENDIAN
+#define VEC_LD(offset,b)                                   \
+    vec_perm(vec_ld(offset, b), vec_ld((offset)+15, b), vec_lvsl(offset, b))
+#else
+#define VEC_LD(offset,b)                                   \
+    vec_vsx_ld(offset, b)
+#endif
+
 /** @brief loads unaligned vector @a *src with offset @a offset
     and returns it */
-static inline vector unsigned char unaligned_load(int offset, uint8_t *src)
+#if HAVE_BIGENDIAN
+static inline vector unsigned char unaligned_load(int offset, const uint8_t *src)
 {
     register vector unsigned char first = vec_ld(offset, src);
     register vector unsigned char second = vec_ld(offset+15, src);
     register vector unsigned char mask = vec_lvsl(offset, src);
     return vec_perm(first, second, mask);
 }
-
-/**
- * loads vector known misalignment
- * @param perm_vec the align permute vector to combine the two loads from lvsl
- */
-static inline vec_u8 load_with_perm_vec(int offset, uint8_t *src, vec_u8 perm_vec)
+static inline vec_u8 load_with_perm_vec(int offset, const uint8_t *src, vec_u8 perm_vec)
 {
     vec_u8 a = vec_ld(offset, src);
     vec_u8 b = vec_ld(offset+15, src);
     return vec_perm(a, b, perm_vec);
 }
+#else
+#define unaligned_load(a,b) VEC_LD(a,b)
+#define load_with_perm_vec(a,b,c) VEC_LD(a,b)
+#endif
 
-#define vec_unaligned_load(b)                                   \
-    vec_perm(vec_ld(0, b), vec_ld(15, b), vec_lvsl(0, b));
+
+/**
+ * loads vector known misalignment
+ * @param perm_vec the align permute vector to combine the two loads from lvsl
+ */
+
+#define vec_unaligned_load(b)  VEC_LD(0, b)
+
+#if HAVE_BIGENDIAN
+#define VEC_MERGEH(a, b) vec_mergeh(a, b)
+#define VEC_MERGEL(a, b) vec_mergel(a, b)
+#else
+#define VEC_MERGEH(a, b) vec_mergeh(b, a)
+#define VEC_MERGEL(a, b) vec_mergel(b, a)
+#endif
+
+#if HAVE_BIGENDIAN
+#define VEC_ST(a,b,c) vec_st(a,b,c)
+#else
+#define VEC_ST(a,b,c) vec_vsx_st(a,b,c)
+#endif
+
+#if HAVE_BIGENDIAN
+#define VEC_SPLAT16(a,b) vec_splat((vec_s16)(a), b)
+#else
+#define VEC_SPLAT16(a,b) vec_splat((vec_s16)(vec_perm(a, a, vcswapi2s(0,1,2,3))), b)
+#endif
+
+#if HAVE_BIGENDIAN
+#define VEC_SLD16(a,b,c) vec_sld(a, b, c)
+#else
+#define VEC_SLD16(a,b,c) vec_sld(b, a, c)
+#endif
 
 #endif /* HAVE_ALTIVEC */
 
diff --git a/libavutil/thread.h b/libavutil/thread.h
new file mode 100644
index 0000000..297b5b9
--- /dev/null
+++ b/libavutil/thread.h
@@ -0,0 +1,59 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+// This header should only be used to simplify code where
+// threading is optional, not as a generic threading abstraction.
+
+#ifndef AVUTIL_THREAD_H
+#define AVUTIL_THREAD_H
+
+#include "config.h"
+
+#if HAVE_PTHREADS || HAVE_W32THREADS || HAVE_OS2THREADS
+
+#define USE_ATOMICS 0
+
+#if HAVE_PTHREADS
+#include <pthread.h>
+#elif HAVE_OS2THREADS
+#include "compat/os2threads.h"
+#else
+#include "compat/w32pthreads.h"
+#endif
+
+#define AVMutex pthread_mutex_t
+
+#define ff_mutex_init    pthread_mutex_init
+#define ff_mutex_lock    pthread_mutex_lock
+#define ff_mutex_unlock  pthread_mutex_unlock
+#define ff_mutex_destroy pthread_mutex_destroy
+
+#else
+
+#define USE_ATOMICS 1
+
+#define AVMutex char
+
+#define ff_mutex_init(mutex, attr) (0)
+#define ff_mutex_lock(mutex) (0)
+#define ff_mutex_unlock(mutex) (0)
+#define ff_mutex_destroy(mutex) (0)
+
+#endif
+
+#endif /* AVUTIL_THREAD_H */
diff --git a/libavutil/time_internal.h b/libavutil/time_internal.h
index c19cc5f..612a75a 100644
--- a/libavutil/time_internal.h
+++ b/libavutil/time_internal.h
@@ -22,7 +22,7 @@
 #include <time.h>
 #include "config.h"
 
-#if !HAVE_GMTIME_R
+#if !HAVE_GMTIME_R && !defined(gmtime_r)
 static inline struct tm *gmtime_r(const time_t* clock, struct tm *result)
 {
     struct tm *ptr = gmtime(clock);
@@ -33,7 +33,7 @@
 }
 #endif
 
-#if !HAVE_LOCALTIME_R
+#if !HAVE_LOCALTIME_R && !defined(localtime_r)
 static inline struct tm *localtime_r(const time_t* clock, struct tm *result)
 {
     struct tm *ptr = localtime(clock);
diff --git a/libavutil/version.h b/libavutil/version.h
index a682c80..c19e943 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -56,7 +56,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  54
-#define LIBAVUTIL_VERSION_MINOR  11
+#define LIBAVUTIL_VERSION_MINOR  15
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
@@ -120,12 +120,11 @@
 #define FF_API_OPT_TYPE_METADATA        (LIBAVUTIL_VERSION_MAJOR < 55)
 #endif
 
-
-#ifndef FF_CONST_AVUTIL53
-#if LIBAVUTIL_VERSION_MAJOR >= 53
-#define FF_CONST_AVUTIL53 const
+#ifndef FF_CONST_AVUTIL55
+#if LIBAVUTIL_VERSION_MAJOR >= 55
+#define FF_CONST_AVUTIL55 const
 #else
-#define FF_CONST_AVUTIL53
+#define FF_CONST_AVUTIL55
 #endif
 #endif
 
diff --git a/libavutil/wchar_filename.h b/libavutil/wchar_filename.h
new file mode 100644
index 0000000..c553c46
--- /dev/null
+++ b/libavutil/wchar_filename.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_WCHAR_FILENAME_H
+#define AVUTIL_WCHAR_FILENAME_H
+
+#if defined(_WIN32) && !defined(__MINGW32CE__)
+#include <windows.h>
+#include "mem.h"
+
+static inline int utf8towchar(const char *filename_utf8, wchar_t **filename_w)
+{
+    int num_chars;
+    num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0);
+    if (num_chars <= 0) {
+        *filename_w = NULL;
+        return 0;
+    }
+    *filename_w = (wchar_t *)av_mallocz_array(num_chars, sizeof(wchar_t));
+    if (!*filename_w) {
+        errno = ENOMEM;
+        return -1;
+    }
+    MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars);
+    return 0;
+}
+#endif
+
+#endif /* AVUTIL_WCHAR_FILENAME_H */
diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm
index 0d0ef07..2d02f75 100644
--- a/libavutil/x86/x86util.asm
+++ b/libavutil/x86/x86util.asm
@@ -641,6 +641,11 @@
 %endif
 %endmacro
 
+%macro CLIPUB 3 ;(dst, min, max)
+    pmaxub %1, %2
+    pminub %1, %3
+%endmacro
+
 %macro CLIPW 3 ;(dst, min, max)
     pmaxsw %1, %2
     pminsw %1, %3
diff --git a/libswresample/swresample.c b/libswresample/swresample.c
index b4d8f32..b0bd697 100644
--- a/libswresample/swresample.c
+++ b/libswresample/swresample.c
@@ -752,13 +752,14 @@
 }
 
 int swr_drop_output(struct SwrContext *s, int count){
+    const uint8_t *tmp_arg[SWR_CH_MAX];
     s->drop_output += count;
 
     if(s->drop_output <= 0)
         return 0;
 
     av_log(s, AV_LOG_VERBOSE, "discarding %d audio samples\n", count);
-    return swr_convert(s, NULL, s->drop_output, NULL, 0);
+    return swr_convert(s, NULL, s->drop_output, tmp_arg, 0);
 }
 
 int swr_inject_silence(struct SwrContext *s, int count){
diff --git a/libswresample/x86/audio_convert.asm b/libswresample/x86/audio_convert.asm
index b6e9e5d..57d3a89 100644
--- a/libswresample/x86/audio_convert.asm
+++ b/libswresample/x86/audio_convert.asm
@@ -245,15 +245,27 @@
     mov%3     m4, [srcq+src4q]
     mov%3     m5, [srcq+src5q]
     %7 x,x,x,x,m7,x
-%if cpuflag(sse4)
+%if cpuflag(sse)
     SBUTTERFLYPS 0, 1, 6
     SBUTTERFLYPS 2, 3, 6
     SBUTTERFLYPS 4, 5, 6
 
+%if cpuflag(avx)
     blendps   m6, m4, m0, 1100b
+%else
+    movaps    m6, m4
+    shufps    m4, m0, q3210
+    SWAP 4,6
+%endif
     movlhps   m0, m2
     movhlps   m4, m2
+%if cpuflag(avx)
     blendps   m2, m5, m1, 1100b
+%else
+    movaps    m2, m5
+    shufps    m5, m1, q3210
+    SWAP 2,5
+%endif
     movlhps   m1, m3
     movhlps   m5, m3
 
@@ -330,10 +342,10 @@
     mulps %1, %5
     mulps %2, %5
     cvtps2dq  %6, %1
-    cmpnltps %1, %5
+    cmpps %1, %1, %5, 5
     paddd %1, %6
     cvtps2dq  %6, %2
-    cmpnltps %2, %5
+    cmpps %2, %2, %5, 5
     paddd %2, %6
 %endmacro
 
@@ -380,6 +392,10 @@
 PACK_6CH float, float, u, 2, 2, NOP_N, NOP_N
 PACK_6CH float, float, a, 2, 2, NOP_N, NOP_N
 
+INIT_XMM sse
+PACK_6CH float, float, u, 2, 2, NOP_N, NOP_N
+PACK_6CH float, float, a, 2, 2, NOP_N, NOP_N
+
 INIT_XMM sse2
 CONV int32, int16, u, 2, 1, INT16_TO_INT32_N, NOP_N
 CONV int32, int16, a, 2, 1, INT16_TO_INT32_N, NOP_N
@@ -431,6 +447,10 @@
 UNPACK_2CH int16, float, u, 1, 2, FLOAT_TO_INT16_N, FLOAT_TO_INT16_INIT
 UNPACK_2CH int16, float, a, 1, 2, FLOAT_TO_INT16_N, FLOAT_TO_INT16_INIT
 
+PACK_6CH float, int32, u, 2, 2, INT32_TO_FLOAT_N, INT32_TO_FLOAT_INIT
+PACK_6CH float, int32, a, 2, 2, INT32_TO_FLOAT_N, INT32_TO_FLOAT_INIT
+PACK_6CH int32, float, u, 2, 2, FLOAT_TO_INT32_N, FLOAT_TO_INT32_INIT
+PACK_6CH int32, float, a, 2, 2, FLOAT_TO_INT32_N, FLOAT_TO_INT32_INIT
 
 INIT_XMM ssse3
 UNPACK_2CH int16, int16, u, 1, 1, NOP_N, NOP_N
@@ -440,15 +460,6 @@
 UNPACK_2CH float, int16, u, 2, 1, INT16_TO_FLOAT_N, INT16_TO_FLOAT_INIT
 UNPACK_2CH float, int16, a, 2, 1, INT16_TO_FLOAT_N, INT16_TO_FLOAT_INIT
 
-INIT_XMM sse4
-PACK_6CH float, float, u, 2, 2, NOP_N, NOP_N
-PACK_6CH float, float, a, 2, 2, NOP_N, NOP_N
-
-PACK_6CH float, int32, u, 2, 2, INT32_TO_FLOAT_N, INT32_TO_FLOAT_INIT
-PACK_6CH float, int32, a, 2, 2, INT32_TO_FLOAT_N, INT32_TO_FLOAT_INIT
-PACK_6CH int32, float, u, 2, 2, FLOAT_TO_INT32_N, FLOAT_TO_INT32_INIT
-PACK_6CH int32, float, a, 2, 2, FLOAT_TO_INT32_N, FLOAT_TO_INT32_INIT
-
 %if HAVE_AVX_EXTERNAL
 INIT_XMM avx
 PACK_6CH float, float, u, 2, 2, NOP_N, NOP_N
@@ -463,3 +474,9 @@
 CONV float, int32, u, 2, 2, INT32_TO_FLOAT_N, INT32_TO_FLOAT_INIT
 CONV float, int32, a, 2, 2, INT32_TO_FLOAT_N, INT32_TO_FLOAT_INIT
 %endif
+
+%if HAVE_AVX2_EXTERNAL
+INIT_YMM avx2
+CONV int32, float, u, 2, 2, FLOAT_TO_INT32_N, FLOAT_TO_INT32_INIT
+CONV int32, float, a, 2, 2, FLOAT_TO_INT32_N, FLOAT_TO_INT32_INIT
+%endif
diff --git a/libswresample/x86/audio_convert_init.c b/libswresample/x86/audio_convert_init.c
index a26cdf6..90bed51 100644
--- a/libswresample/x86/audio_convert_init.c
+++ b/libswresample/x86/audio_convert_init.c
@@ -25,7 +25,7 @@
 #define PROTO(pre, in, out, cap) void ff ## pre ## in## _to_ ##out## _a_ ##cap(uint8_t **dst, const uint8_t **src, int len);
 #define PROTO2(pre, out, cap) PROTO(pre, int16, out, cap) PROTO(pre, int32, out, cap) PROTO(pre, float, out, cap)
 #define PROTO3(pre, cap) PROTO2(pre, int16, cap) PROTO2(pre, int32, cap) PROTO2(pre, float, cap)
-#define PROTO4(pre) PROTO3(pre, mmx) PROTO3(pre, sse) PROTO3(pre, sse2) PROTO3(pre, ssse3) PROTO3(pre, sse4) PROTO3(pre, avx)
+#define PROTO4(pre) PROTO3(pre, mmx) PROTO3(pre, sse) PROTO3(pre, sse2) PROTO3(pre, ssse3) PROTO3(pre, sse4) PROTO3(pre, avx) PROTO3(pre, avx2)
 PROTO4(_)
 PROTO4(_pack_2ch_)
 PROTO4(_pack_6ch_)
@@ -58,7 +58,12 @@
                 ac->simd_f =  ff_pack_6ch_float_to_float_a_mmx;
         }
     }
-
+    if(EXTERNAL_SSE(mm_flags)) {
+        if(channels == 6) {
+            if(   out_fmt == AV_SAMPLE_FMT_FLT  && in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S32P)
+                ac->simd_f =  ff_pack_6ch_float_to_float_a_sse;
+        }
+    }
     if(EXTERNAL_SSE2(mm_flags)) {
         if(   out_fmt == AV_SAMPLE_FMT_FLT  && in_fmt == AV_SAMPLE_FMT_S32 || out_fmt == AV_SAMPLE_FMT_FLTP && in_fmt == AV_SAMPLE_FMT_S32P)
             ac->simd_f =  ff_int32_to_float_a_sse2;
@@ -105,6 +110,12 @@
             if(   out_fmt == AV_SAMPLE_FMT_S16P  && in_fmt == AV_SAMPLE_FMT_FLT)
                 ac->simd_f =  ff_unpack_2ch_float_to_int16_a_sse2;
         }
+        if(channels == 6) {
+            if(   out_fmt == AV_SAMPLE_FMT_FLT  && in_fmt == AV_SAMPLE_FMT_S32P)
+                ac->simd_f =  ff_pack_6ch_int32_to_float_a_sse2;
+            if(   out_fmt == AV_SAMPLE_FMT_S32  && in_fmt == AV_SAMPLE_FMT_FLTP)
+                ac->simd_f =  ff_pack_6ch_float_to_int32_a_sse2;
+        }
     }
     if(EXTERNAL_SSSE3(mm_flags)) {
         if(channels == 2) {
@@ -116,16 +127,6 @@
                 ac->simd_f =  ff_unpack_2ch_int16_to_float_a_ssse3;
         }
     }
-    if(EXTERNAL_SSE4(mm_flags)) {
-        if(channels == 6) {
-            if(   out_fmt == AV_SAMPLE_FMT_FLT  && in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S32P)
-                ac->simd_f =  ff_pack_6ch_float_to_float_a_sse4;
-            if(   out_fmt == AV_SAMPLE_FMT_FLT  && in_fmt == AV_SAMPLE_FMT_S32P)
-                ac->simd_f =  ff_pack_6ch_int32_to_float_a_sse4;
-            if(   out_fmt == AV_SAMPLE_FMT_S32  && in_fmt == AV_SAMPLE_FMT_FLTP)
-                ac->simd_f =  ff_pack_6ch_float_to_int32_a_sse4;
-        }
-    }
     if(EXTERNAL_AVX(mm_flags)) {
         if(   out_fmt == AV_SAMPLE_FMT_FLT  && in_fmt == AV_SAMPLE_FMT_S32 || out_fmt == AV_SAMPLE_FMT_FLTP && in_fmt == AV_SAMPLE_FMT_S32P)
             ac->simd_f =  ff_int32_to_float_a_avx;
@@ -138,4 +139,8 @@
                 ac->simd_f =  ff_pack_6ch_float_to_int32_a_avx;
         }
     }
+    if(EXTERNAL_AVX2(mm_flags)) {
+        if(   out_fmt == AV_SAMPLE_FMT_S32  && in_fmt == AV_SAMPLE_FMT_FLT || out_fmt == AV_SAMPLE_FMT_S32P && in_fmt == AV_SAMPLE_FMT_FLTP)
+            ac->simd_f =  ff_float_to_int32_a_avx2;
+    }
 }
diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c
index 86f40ab..a1548a7 100644
--- a/libswscale/ppc/swscale_altivec.c
+++ b/libswscale/ppc/swscale_altivec.c
@@ -29,22 +29,62 @@
 #include "libavutil/attributes.h"
 #include "libavutil/cpu.h"
 #include "yuv2rgb_altivec.h"
+#include "libavutil/ppc/util_altivec.h"
 
 #if HAVE_ALTIVEC
 #define vzero vec_splat_s32(0)
 
-#define yuv2planeX_8(d1, d2, l1, src, x, perm, filter) do {     \
-        vector signed short l2  = vec_ld(((x) << 1) + 16, src); \
-        vector signed short ls  = vec_perm(l1, l2, perm);       \
-        vector signed int   i1  = vec_mule(filter, ls);         \
-        vector signed int   i2  = vec_mulo(filter, ls);         \
-        vector signed int   vf1 = vec_mergeh(i1, i2);           \
-        vector signed int   vf2 = vec_mergel(i1, i2);           \
-        d1 = vec_add(d1, vf1);                                  \
-        d2 = vec_add(d2, vf2);                                  \
-        l1 = l2;                                                \
+#if HAVE_BIGENDIAN
+#define  GET_LS(a,b,c,s) {\
+        vector signed short l2  = vec_ld(((b) << 1) + 16, s);\
+        ls  = vec_perm(a, l2, c);\
+        a = l2;\
+    }
+#define  GET_VF(a, b, c,d) {\
+        a = vec_mergeh(c, d);\
+        b = vec_mergel(c, d);\
+    }
+#else
+#define  GET_LS(a,b,c,s) {\
+        ls  = a;\
+        a = vec_vsx_ld(((b) << 1)  + 16, s);\
+    }
+#define  GET_VF(a, b, c, d) {\
+        a = vec_mergel(d, c);\
+        b = vec_mergeh(d, c);\
+    }
+#endif
+
+#define yuv2planeX_8(d1, d2, l1, src, x, perm, filter) do {\
+        vector signed short ls;\
+        GET_LS(l1, x, perm, src);\
+        vector signed int   i1  = vec_mule(filter, ls);\
+        vector signed int   i2  = vec_mulo(filter, ls);\
+        vector signed int   vf1, vf2;\
+        GET_VF(vf1, vf2, i1, i2);\
+        d1 = vec_add(d1, vf1);\
+        d2 = vec_add(d2, vf2);\
     } while (0)
 
+#if HAVE_BIGENDIAN
+#define LOAD_FILTER(vf,f) {\
+        vector unsigned char perm0 = vec_lvsl(joffset, f);\
+        vf = vec_ld(joffset, f);\
+        vf = vec_perm(vf, vf, perm0);\
+}
+#define LOAD_L1(ll1,s,p){\
+        p = vec_lvsl(xoffset, s);\
+        ll1   = vec_ld(xoffset, s);\
+}
+#else
+#define LOAD_FILTER(vf,f) {\
+        vf = vec_vsx_ld(joffset, f);\
+}
+#define LOAD_L1(ll1,s,p){\
+        ll1  = vec_vsx_ld(xoffset, s);\
+}
+#endif
+
 static void yuv2planeX_16_altivec(const int16_t *filter, int filterSize,
                                   const int16_t **src, uint8_t *dest,
                                   const uint8_t *dither, int offset, int x)
@@ -66,14 +106,13 @@
     vo4 = vec_ld(48, val);
 
     for (j = 0; j < filterSize; j++) {
-        vector signed short l1, vLumFilter = vec_ld(j << 1, filter);
-        vector unsigned char perm, perm0 = vec_lvsl(j << 1, filter);
-        vLumFilter = vec_perm(vLumFilter, vLumFilter, perm0);
-        vLumFilter = vec_splat(vLumFilter, 0); // lumFilter[j] is loaded 8 times in vLumFilter
-
-        perm = vec_lvsl(x << 1, src[j]);
-        l1   = vec_ld(x << 1, src[j]);
-
+        unsigned int joffset=j<<1;
+        unsigned int xoffset=x<<1;
+        vector unsigned char perm;
+        vector signed short l1,vLumFilter;
+        LOAD_FILTER(vLumFilter,filter);
+        vLumFilter = vec_splat(vLumFilter, 0);
+        LOAD_L1(l1,src[j],perm);
         yuv2planeX_8(vo1, vo2, l1, src[j], x,     perm, vLumFilter);
         yuv2planeX_8(vo3, vo4, l1, src[j], x + 8, perm, vLumFilter);
     }
@@ -85,9 +124,10 @@
     vs1 = vec_packsu(vo1, vo2);
     vs2 = vec_packsu(vo3, vo4);
     vf  = vec_packsu(vs1, vs2);
-    vec_st(vf, 0, dest);
+    VEC_ST(vf, 0, dest);
 }
 
+
 static inline void yuv2planeX_u(const int16_t *filter, int filterSize,
                                 const int16_t **src, uint8_t *dest, int dstW,
                                 const uint8_t *dither, int offset, int x)
@@ -118,6 +158,58 @@
     yuv2planeX_u(filter, filterSize, src, dest, dstW, dither, offset, i);
 }
 
+#if HAVE_BIGENDIAN
+// The 3 above is 2 (filterSize == 4) + 1 (sizeof(short) == 2).
+
+// The neat trick: We only care for half the elements,
+// high or low depending on (i<<3)%16 (it's 0 or 8 here),
+// and we're going to use vec_mule, so we choose
+// carefully how to "unpack" the elements into the even slots.
+#define GET_VF4(a, vf, f) {\
+    vf = vec_ld(a<< 3, f);\
+    if ((a << 3) % 16)\
+        vf = vec_mergel(vf, (vector signed short)vzero);\
+    else\
+        vf = vec_mergeh(vf, (vector signed short)vzero);\
+}
+#define FIRST_LOAD(sv, pos, s, per) {\
+    sv = vec_ld(pos, s);\
+    per = vec_lvsl(pos, s);\
+}
+#define UPDATE_PTR(s0, d0, s1, d1) {\
+    d0 = s0;\
+    d1 = s1;\
+}
+#define LOAD_SRCV(pos, a, s, per, v0, v1, vf) {\
+    v1 = vec_ld(pos + a + 16, s);\
+    vf = vec_perm(v0, v1, per);\
+}
+#define LOAD_SRCV8(pos, a, s, per, v0, v1, vf) {\
+    if ((((uintptr_t)s + pos) % 16) > 8) {\
+        v1 = vec_ld(pos + a + 16, s);\
+    }\
+    vf = vec_perm(v0, src_v1, per);\
+}
+#define GET_VFD(a, b, f, vf0, vf1, per, vf, off) {\
+    vf1 = vec_ld((a * 2 * filterSize) + (b * 2) + 16 + off, f);\
+    vf  = vec_perm(vf0, vf1, per);\
+}
+#else /* else of #if HAVE_BIGENDIAN */
+#define GET_VF4(a, vf, f) {\
+    vf = (vector signed short)vec_vsx_ld(a << 3, f);\
+    vf = vec_mergeh(vf, (vector signed short)vzero);\
+}
+#define FIRST_LOAD(sv, pos, s, per) {}
+#define UPDATE_PTR(s0, d0, s1, d1) {}
+#define LOAD_SRCV(pos, a, s, per, v0, v1, vf) {\
+    vf = vec_vsx_ld(pos + a, s);\
+}
+#define LOAD_SRCV8(pos, a, s, per, v0, v1, vf) LOAD_SRCV(pos, a, s, per, v0, v1, vf)
+#define GET_VFD(a, b, f, vf0, vf1, per, vf, off) {\
+    vf  = vec_vsx_ld((a * 2 * filterSize) + (b * 2) + off, f);\
+}
+#endif /* end of #if HAVE_BIGENDIAN */
+
 static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW,
                                 const uint8_t *src, const int16_t *filter,
                                 const int32_t *filterPos, int filterSize)
@@ -140,57 +232,32 @@
             for (i = 0; i < dstW; i++) {
                 register int srcPos = filterPos[i];
 
-                vector unsigned char src_v0 = vec_ld(srcPos, src);
-                vector unsigned char src_v1, src_vF;
+                vector unsigned char src_vF = unaligned_load(srcPos, src);
                 vector signed short src_v, filter_v;
                 vector signed int val_vEven, val_s;
-                if ((((uintptr_t)src + srcPos) % 16) > 12) {
-                    src_v1 = vec_ld(srcPos + 16, src);
-                }
-                src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));
-
                 src_v = // vec_unpackh sign-extends...
-                        (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+                        (vector signed short)(VEC_MERGEH((vector unsigned char)vzero, src_vF));
                 // now put our elements in the even slots
                 src_v = vec_mergeh(src_v, (vector signed short)vzero);
-
-                filter_v = vec_ld(i << 3, filter);
-                // The 3 above is 2 (filterSize == 4) + 1 (sizeof(short) == 2).
-
-                // The neat trick: We only care for half the elements,
-                // high or low depending on (i<<3)%16 (it's 0 or 8 here),
-                // and we're going to use vec_mule, so we choose
-                // carefully how to "unpack" the elements into the even slots.
-                if ((i << 3) % 16)
-                    filter_v = vec_mergel(filter_v, (vector signed short)vzero);
-                else
-                    filter_v = vec_mergeh(filter_v, (vector signed short)vzero);
-
+                GET_VF4(i, filter_v, filter);
                 val_vEven = vec_mule(src_v, filter_v);
                 val_s     = vec_sums(val_vEven, vzero);
                 vec_st(val_s, 0, tempo);
                 dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);
             }
         break;
-
         case 8:
             for (i = 0; i < dstW; i++) {
                 register int srcPos = filterPos[i];
-
-                vector unsigned char src_v0 = vec_ld(srcPos, src);
-                vector unsigned char src_v1, src_vF;
+                vector unsigned char src_vF, src_v0, src_v1;
+                vector unsigned char permS;
                 vector signed short src_v, filter_v;
                 vector signed int val_v, val_s;
-                if ((((uintptr_t)src + srcPos) % 16) > 8) {
-                    src_v1 = vec_ld(srcPos + 16, src);
-                }
-                src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));
-
+                FIRST_LOAD(src_v0, srcPos, src, permS);
+                LOAD_SRCV8(srcPos, 0, src, permS, src_v0, src_v1, src_vF);
                 src_v = // vec_unpackh sign-extends...
-                        (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+                        (vector signed short)(VEC_MERGEH((vector unsigned char)vzero, src_vF));
                 filter_v = vec_ld(i << 4, filter);
-                // the 4 above is 3 (filterSize == 8) + 1 (sizeof(short) == 2)
-
                 val_v = vec_msums(src_v, filter_v, (vector signed int)vzero);
                 val_s = vec_sums(val_v, vzero);
                 vec_st(val_s, 0, tempo);
@@ -202,85 +269,64 @@
             for (i = 0; i < dstW; i++) {
                 register int srcPos = filterPos[i];
 
-                vector unsigned char src_v0 = vec_ld(srcPos, src);
-                vector unsigned char src_v1 = vec_ld(srcPos + 16, src);
-                vector unsigned char src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src));
-
+                vector unsigned char src_vF = unaligned_load(srcPos, src);
                 vector signed short src_vA = // vec_unpackh sign-extends...
-                                             (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+                                             (vector signed short)(VEC_MERGEH((vector unsigned char)vzero, src_vF));
                 vector signed short src_vB = // vec_unpackh sign-extends...
-                                             (vector signed short)(vec_mergel((vector unsigned char)vzero, src_vF));
-
+                                             (vector signed short)(VEC_MERGEL((vector unsigned char)vzero, src_vF));
                 vector signed short filter_v0 = vec_ld(i << 5, filter);
                 vector signed short filter_v1 = vec_ld((i << 5) + 16, filter);
-                // the 5 above are 4 (filterSize == 16) + 1 (sizeof(short) == 2)
 
                 vector signed int val_acc = vec_msums(src_vA, filter_v0, (vector signed int)vzero);
                 vector signed int val_v   = vec_msums(src_vB, filter_v1, val_acc);
 
                 vector signed int val_s = vec_sums(val_v, vzero);
 
-                vec_st(val_s, 0, tempo);
+                VEC_ST(val_s, 0, tempo);
                 dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);
             }
         break;
 
         default:
             for (i = 0; i < dstW; i++) {
-                register int j;
+                register int j, offset = i * 2 * filterSize;
                 register int srcPos = filterPos[i];
 
                 vector signed int val_s, val_v = (vector signed int)vzero;
-                vector signed short filter_v0R = vec_ld(i * 2 * filterSize, filter);
-                vector unsigned char permF     = vec_lvsl((i * 2 * filterSize), filter);
-
-                vector unsigned char src_v0 = vec_ld(srcPos, src);
-                vector unsigned char permS  = vec_lvsl(srcPos, src);
+                vector signed short filter_v0R;
+                vector unsigned char permF, src_v0, permS;
+                FIRST_LOAD(filter_v0R, offset, filter, permF);
+                FIRST_LOAD(src_v0, srcPos, src, permS);
 
                 for (j = 0; j < filterSize - 15; j += 16) {
-                    vector unsigned char src_v1 = vec_ld(srcPos + j + 16, src);
-                    vector unsigned char src_vF = vec_perm(src_v0, src_v1, permS);
-
+                    vector unsigned char src_v1, src_vF;
+                    vector signed short filter_v1R, filter_v2R, filter_v0, filter_v1;
+                    LOAD_SRCV(srcPos, j, src, permS, src_v0, src_v1, src_vF);
                     vector signed short src_vA = // vec_unpackh sign-extends...
-                                                 (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
+                                                 (vector signed short)(VEC_MERGEH((vector unsigned char)vzero, src_vF));
                     vector signed short src_vB = // vec_unpackh sign-extends...
-                                                 (vector signed short)(vec_mergel((vector unsigned char)vzero, src_vF));
-
-                    vector signed short filter_v1R = vec_ld((i * 2 * filterSize) + (j * 2) + 16, filter);
-                    vector signed short filter_v2R = vec_ld((i * 2 * filterSize) + (j * 2) + 32, filter);
-                    vector signed short filter_v0  = vec_perm(filter_v0R, filter_v1R, permF);
-                    vector signed short filter_v1  = vec_perm(filter_v1R, filter_v2R, permF);
+                                                 (vector signed short)(VEC_MERGEL((vector unsigned char)vzero, src_vF));
+                    GET_VFD(i, j, filter, filter_v0R, filter_v1R, permF, filter_v0, 0);
+                    GET_VFD(i, j, filter, filter_v1R, filter_v2R, permF, filter_v1, 16);
 
                     vector signed int val_acc = vec_msums(src_vA, filter_v0, val_v);
                     val_v = vec_msums(src_vB, filter_v1, val_acc);
-
-                    filter_v0R = filter_v2R;
-                    src_v0     = src_v1;
+                    UPDATE_PTR(filter_v2R, filter_v0R, src_v1, src_v0);
                 }
 
                 if (j < filterSize - 7) {
                     // loading src_v0 is useless, it's already done above
-                    // vector unsigned char src_v0 = vec_ld(srcPos + j, src);
                     vector unsigned char src_v1, src_vF;
                     vector signed short src_v, filter_v1R, filter_v;
-                    if ((((uintptr_t)src + srcPos) % 16) > 8) {
-                        src_v1 = vec_ld(srcPos + j + 16, src);
-                    }
-                    src_vF = vec_perm(src_v0, src_v1, permS);
-
+                    LOAD_SRCV8(srcPos, j, src, permS, src_v0, src_v1, src_vF);
                     src_v = // vec_unpackh sign-extends...
-                            (vector signed short)(vec_mergeh((vector unsigned char)vzero, src_vF));
-                    // loading filter_v0R is useless, it's already done above
-                    // vector signed short filter_v0R = vec_ld((i * 2 * filterSize) + j, filter);
-                    filter_v1R = vec_ld((i * 2 * filterSize) + (j * 2) + 16, filter);
-                    filter_v   = vec_perm(filter_v0R, filter_v1R, permF);
-
+                            (vector signed short)(VEC_MERGEH((vector unsigned char)vzero, src_vF));
+                    GET_VFD(i, j, filter, filter_v0R, filter_v1R, permF, filter_v, 0);
                     val_v = vec_msums(src_v, filter_v, val_v);
                 }
-
                 val_s = vec_sums(val_v, vzero);
 
-                vec_st(val_s, 0, tempo);
+                VEC_ST(val_s, 0, tempo);
                 dst[i] = FFMIN(tempo[3] >> 7, (1 << 15) - 1);
             }
         }
diff --git a/libswscale/utils.c b/libswscale/utils.c
index 5904ef8..ab494ed 100644
--- a/libswscale/utils.c
+++ b/libswscale/utils.c
@@ -1217,6 +1217,31 @@
         }
     }
 
+    if (isBayer(srcFormat)) {
+        if (!unscaled ||
+            (dstFormat != AV_PIX_FMT_RGB24 && dstFormat != AV_PIX_FMT_YUV420P)) {
+            enum AVPixelFormat tmpFormat = AV_PIX_FMT_RGB24;
+
+            ret = av_image_alloc(c->cascaded_tmp, c->cascaded_tmpStride,
+                                srcW, srcH, tmpFormat, 64);
+            if (ret < 0)
+                return ret;
+
+            c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat,
+                                                    srcW, srcH, tmpFormat,
+                                                    flags, srcFilter, NULL, c->param);
+            if (!c->cascaded_context[0])
+                return -1;
+
+            c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFormat,
+                                                    dstW, dstH, dstFormat,
+                                                    flags, NULL, dstFilter, c->param);
+            if (!c->cascaded_context[1])
+                return -1;
+            return 0;
+        }
+    }
+
 #define USE_MMAP (HAVE_MMAP && HAVE_MPROTECT && defined MAP_ANONYMOUS)
 
     /* precalculate horizontal scaler filter coefficients */
diff --git a/libswscale/x86/rgb2rgb_template.c b/libswscale/x86/rgb2rgb_template.c
index 3899d0a..7796d38 100644
--- a/libswscale/x86/rgb2rgb_template.c
+++ b/libswscale/x86/rgb2rgb_template.c
@@ -1634,6 +1634,16 @@
 #define BGR2V_IDX "16*4+16*34"
     int y;
     const x86_reg chromWidth= width>>1;
+
+    if (height > 2) {
+        ff_rgb24toyv12_c(src, ydst, udst, vdst, width, 2, lumStride, chromStride, srcStride, rgb2yuv);
+        src  += 2*srcStride;
+        ydst += 2*lumStride;
+        udst += chromStride;
+        vdst += chromStride;
+        height -= 2;
+    }
+
     for (y=0; y<height-2; y+=2) {
         int i;
         for (i=0; i<2; i++) {
diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c
index 8ce87b3..fe5c4ea 100644
--- a/libswscale/x86/swscale.c
+++ b/libswscale/x86/swscale.c
@@ -430,7 +430,7 @@
     case 16:                          do_16_case;                          break; \
     case 10: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \
     case 9:  if (!isBE(c->dstFormat)) vscalefn = ff_yuv2planeX_9_  ## opt; break; \
-    default: if (condition_8bit)    /*vscalefn = ff_yuv2planeX_8_  ## opt;*/ break; \
+    case 8: if ((condition_8bit) && !c->use_mmx_vfilter) vscalefn = ff_yuv2planeX_8_  ## opt; break; \
     }
 #define ASSIGN_VSCALE_FUNC(vscalefn, opt1, opt2, opt2chk) \
     switch(c->dstBpc){ \
diff --git a/tests/Makefile b/tests/Makefile
index f08f924..7ef8132 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -38,7 +38,7 @@
 
 tests/test_copy.ffmeta: TAG = COPY
 tests/test_copy.ffmeta: tests/data
-	$(M)cp -f $(SRC_PATH)/tests/test.ffmeta $(TARGET_PATH)/tests/test_copy.ffmeta
+	$(M)cp -f $(SRC_PATH)/tests/test.ffmeta tests/test_copy.ffmeta
 
 tests/data/ffprobe-test.nut: ffmpeg$(EXESUF) tests/test_copy.ffmeta
 	$(M)$(TARGET_EXEC) ./$< \
@@ -47,7 +47,7 @@
         -flags +bitexact -map 0:0 -map 0:1 -map 0:2 -map_metadata 1 \
         -map_metadata:s:0 1:s:0 -map_metadata:s:1 1:s:1 \
         -vcodec rawvideo -acodec pcm_s16le \
-        -y $@ 2>/dev/null
+        -y $(TARGET_PATH)/$@ 2>/dev/null
 
 tests/data/%.sw tests/data/asynth% tests/data/vsynth%.yuv tests/vsynth%/00.pgm tests/data/%.nut: TAG = GEN
 
diff --git a/tests/fate-run.sh b/tests/fate-run.sh
index f00a0be..f78e4fc 100755
--- a/tests/fate-run.sh
+++ b/tests/fate-run.sh
@@ -203,12 +203,14 @@
     $showfiltfmts $filter | awk -F '[ \r]' '/^INPUT/{ fmt=substr($3, 5); print fmt }' | sort >$in_fmts
     pix_fmts=$(comm -12 $scale_exclude_fmts $in_fmts)
 
+    outertest=$test
     for pix_fmt in $pix_fmts; do
         test=$pix_fmt
         video_filter "${prefilter_chain}format=$pix_fmt,$filter=$filter_args" -pix_fmt $pix_fmt
     done
 
     rm $in_fmts $scale_in_fmts $scale_out_fmts $scale_exclude_fmts
+    test=$outertest
 }
 
 mkdir -p "$outdir"
diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak
index aa58dfc..b7e5362 100644
--- a/tests/fate/audio.mak
+++ b/tests/fate/audio.mak
@@ -44,8 +44,8 @@
 fate-nellymoser-aref-encode: CMD = enc_dec_pcm flv wav s16le $(REF) -c:a nellymoser
 fate-nellymoser-aref-encode: CMP = stddev
 fate-nellymoser-aref-encode: REF = ./tests/data/asynth-16000-1.wav
-fate-nellymoser-aref-encode: CMP_SHIFT = -244
-fate-nellymoser-aref-encode: CMP_TARGET = 9612
+fate-nellymoser-aref-encode: CMP_SHIFT = -256
+fate-nellymoser-aref-encode: CMP_TARGET = 3863
 fate-nellymoser-aref-encode: SIZE_TOLERANCE = 268
 
 FATE_SAMPLES_AUDIO-$(call DEMDEC, AVI, ON2AVC) += fate-on2avc
diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak
index c49cf00..601a0d8 100644
--- a/tests/fate/filter-video.mak
+++ b/tests/fate/filter-video.mak
@@ -156,6 +156,13 @@
 fate-filter-hq4x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf hqx=4 -pix_fmt bgra
 fate-filter-hqx: $(FATE_FILTER_HQX-yes)
 
+FATE_FILTER_XBR-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER XBR_FILTER) = fate-filter-2xbr fate-filter-3xbr fate-filter-4xbr
+FATE_FILTER-yes += $(FATE_FILTER_XBR-yes)
+fate-filter-2xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=2 -pix_fmt bgra
+fate-filter-3xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=3 -pix_fmt bgra
+fate-filter-4xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf xbr=4 -pix_fmt bgra
+fate-filter-xbr: $(FATE_FILTER_XBR-yes)
+
 FATE_FILTER-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves
 fate-filter-curves: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgb_median.avi -vf perms=random,curves=vintage
 
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 63a4dd6..eadebdb 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -107,6 +107,10 @@
 fate-xtea: libavutil/xtea-test$(EXESUF)
 fate-xtea: CMD = run libavutil/xtea-test
 
+FATE_LIBAVUTIL += fate-opt
+fate-opt: libavutil/opt-test$(EXESUF)
+fate-opt: CMD = run libavutil/opt-test
+
 FATE_LIBAVUTIL += $(FATE_LIBAVUTIL-yes)
 FATE-$(CONFIG_AVUTIL) += $(FATE_LIBAVUTIL)
 fate-libavutil: $(FATE_LIBAVUTIL)
diff --git a/tests/fate/libswresample.mak b/tests/fate/libswresample.mak
index 3b479a9..24b7d66 100644
--- a/tests/fate/libswresample.mak
+++ b/tests/fate/libswresample.mak
@@ -365,17 +365,17 @@
 fate-swr-resample_async-$(3)-$(1)-$(2): REF = tests/data/asynth-$(1)-1.wav
 endef
 
-fate-swr-resample_async-fltp-44100-8000: CMP_TARGET = 4047.25
-fate-swr-resample_async-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20132
+fate-swr-resample_async-fltp-44100-8000: CMP_TARGET = 4031.60
+fate-swr-resample_async-fltp-44100-8000: SIZE_TOLERANCE = 529200 - 20310
 
-fate-swr-resample_async-fltp-8000-44100: CMP_TARGET = 11193.77
-fate-swr-resample_async-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20312
+fate-swr-resample_async-fltp-8000-44100: CMP_TARGET = 11185.34
+fate-swr-resample_async-fltp-8000-44100: SIZE_TOLERANCE = 96000 - 20344
 
-fate-swr-resample_async-s16p-44100-8000: CMP_TARGET = 4047.24
-fate-swr-resample_async-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20132
+fate-swr-resample_async-s16p-44100-8000: CMP_TARGET = 4031.59
+fate-swr-resample_async-s16p-44100-8000: SIZE_TOLERANCE = 529200 - 20310
 
-fate-swr-resample_async-s16p-8000-44100: CMP_TARGET = 11194.08
-fate-swr-resample_async-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20312
+fate-swr-resample_async-s16p-8000-44100: CMP_TARGET = 11185.65
+fate-swr-resample_async-s16p-8000-44100: SIZE_TOLERANCE = 96000 - 20344
 
 $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,s16p,s16le,s16)
 $(call CROSS_TEST,$(SAMPLERATES),ARESAMPLE,s32p,s32le,s16)
diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak
index c715071..803edec 100644
--- a/tests/fate/vcodec.mak
+++ b/tests/fate/vcodec.mak
@@ -294,6 +294,11 @@
 FATE_VCODEC-$(call ENCDEC, RAWVIDEO, AVI) += yuv
 fate-vsynth%-yuv:                CODEC = rawvideo
 
+FATE_VCODEC-$(call ENCDEC, XFACE, NUT) += xface
+fate-vsynth%-xface:              ENCOPTS = -s 48x48 -sws_flags neighbor+bitexact
+fate-vsynth%-xface:              DECOPTS = -sws_flags neighbor+bitexact
+fate-vsynth%-xface:              FMT = nut
+
 FATE_VCODEC-$(call ENCDEC, YUV4, AVI) += yuv4
 
 FATE_VCODEC-$(call ENCDEC, Y41P, AVI) += y41p
diff --git a/tests/ref/acodec/adpcm-adx b/tests/ref/acodec/adpcm-adx
index b96d99a..34dd9b6 100644
--- a/tests/ref/acodec/adpcm-adx
+++ b/tests/ref/acodec/adpcm-adx
@@ -1,4 +1,4 @@
-0a30509d9296b857e134b762b76dbc31 *tests/data/fate/acodec-adpcm-adx.adx
+d7ec7d52a2f5c91464812d031b07cc1d *tests/data/fate/acodec-adpcm-adx.adx
 297720 tests/data/fate/acodec-adpcm-adx.adx
-7260139001fcac62384dad50a1023e75 *tests/data/fate/acodec-adpcm-adx.out.wav
-stddev: 6989.46 PSNR: 19.44 MAXDIFF:65398 bytes:  1058400/  1058432
+5b5a436ec9d528d6eb0bebaf667521b0 *tests/data/fate/acodec-adpcm-adx.out.wav
+stddev: 2549.93 PSNR: 28.20 MAXDIFF:57514 bytes:  1058400/  1058432
diff --git a/tests/ref/acodec/adpcm-adx-trellis b/tests/ref/acodec/adpcm-adx-trellis
index fff0291..d620d4a 100644
--- a/tests/ref/acodec/adpcm-adx-trellis
+++ b/tests/ref/acodec/adpcm-adx-trellis
@@ -1,4 +1,4 @@
-0a30509d9296b857e134b762b76dbc31 *tests/data/fate/acodec-adpcm-adx-trellis.adx
+d7ec7d52a2f5c91464812d031b07cc1d *tests/data/fate/acodec-adpcm-adx-trellis.adx
 297720 tests/data/fate/acodec-adpcm-adx-trellis.adx
-7260139001fcac62384dad50a1023e75 *tests/data/fate/acodec-adpcm-adx-trellis.out.wav
-stddev: 6989.46 PSNR: 19.44 MAXDIFF:65398 bytes:  1058400/  1058432
+5b5a436ec9d528d6eb0bebaf667521b0 *tests/data/fate/acodec-adpcm-adx-trellis.out.wav
+stddev: 2549.93 PSNR: 28.20 MAXDIFF:57514 bytes:  1058400/  1058432
diff --git a/tests/ref/fate/cdxl-bitline-ham6 b/tests/ref/fate/cdxl-bitline-ham6
index 8060f06..9ba7404 100644
--- a/tests/ref/fate/cdxl-bitline-ham6
+++ b/tests/ref/fate/cdxl-bitline-ham6
@@ -1,4 +1,4 @@
-#tb 0: 12/601
+#tb 0: 1/50
 0,          0,          0,        1,    63180, 0xcda82c16
 0,          1,          1,        1,    63180, 0xa6097bf9
 0,          2,          2,        1,    63180, 0x4c2fb091
diff --git a/tests/ref/fate/cdxl-ham8 b/tests/ref/fate/cdxl-ham8
index 269f1f3..1eebea3 100644
--- a/tests/ref/fate/cdxl-ham8
+++ b/tests/ref/fate/cdxl-ham8
@@ -1,2 +1,2 @@
-#tb 0: 3/158
+#tb 0: 12/281
 0,          0,          0,        1,    67584, 0xce0cade5
diff --git a/tests/ref/fate/cdxl-pal8 b/tests/ref/fate/cdxl-pal8
index 82d4d63..b2fb045 100644
--- a/tests/ref/fate/cdxl-pal8
+++ b/tests/ref/fate/cdxl-pal8
@@ -1,4 +1,4 @@
-#tb 0: 12/601
+#tb 0: 1/50
 0,          0,          0,        1,    67584, 0x5eae629b
 0,          1,          1,        1,    67584, 0x32591227
 0,          2,          2,        1,    67584, 0x4e4424c7
diff --git a/tests/ref/fate/filter-2xbr b/tests/ref/fate/filter-2xbr
new file mode 100644
index 0000000..91e1d4c
--- /dev/null
+++ b/tests/ref/fate/filter-2xbr
@@ -0,0 +1,3 @@
+#tb 0: 1/25
+0,          0,          0,        1,   877072, 0x5142c6cd
+0,          1,          1,        1,   877072, 0xa01a3f47
diff --git a/tests/ref/fate/filter-3xbr b/tests/ref/fate/filter-3xbr
new file mode 100644
index 0000000..013f6a3
--- /dev/null
+++ b/tests/ref/fate/filter-3xbr
@@ -0,0 +1,3 @@
+#tb 0: 1/25
+0,          0,          0,        1,  1973412, 0xd4cf257b
+0,          1,          1,        1,  1973412, 0x63fcd614
diff --git a/tests/ref/fate/filter-4xbr b/tests/ref/fate/filter-4xbr
new file mode 100644
index 0000000..92b70d9
--- /dev/null
+++ b/tests/ref/fate/filter-4xbr
@@ -0,0 +1,3 @@
+#tb 0: 1/25
+0,          0,          0,        1,  3508288, 0xc7b1d170
+0,          1,          1,        1,  3508288, 0x3fd0c3fb
diff --git a/tests/ref/fate/filter-pixfmts-kerndeint b/tests/ref/fate/filter-pixfmts-kerndeint
index 6fefda3..376d8f4 100644
--- a/tests/ref/fate/filter-pixfmts-kerndeint
+++ b/tests/ref/fate/filter-pixfmts-kerndeint
@@ -1,10 +1,10 @@
-0bgr                e179e118e6dc0a5b6f9e80955fedc776
-0rgb                95fa448040fa3f86d23418b857123259
-abgr                1a24de822f91557546c8e9c8236f7814
-argb                adc0120d95192942f5c39de1b602b883
-bgr0                33ee8c3df7c05bff51c742fe6beacad1
-bgra                6e8b840001a5f50c0b277fe3d7cafd26
-rgb0                8d63004296dc6db7868aa7163780f5b5
-rgba                ebf7aaa65634dcee4289e80d4fb31e50
-yuv420p             8edaf2d52dc7fba910784076b2dbdcfc
-yuyv422             07198d8a9f7989bd75d1da94800c69d5
+0bgr                bdff73f3a0b22f29d2fcae461db92efc
+0rgb                6d19d706cc405fc7e0d0e941d34ddc5f
+abgr                6eb205786c9eb1419334f7725fc799ee
+argb                180b920be1f3b03234e327725a00abed
+bgr0                661a99840c4cb6d9bb755ab6fec9548b
+bgra                c5e9622e15ad7ad276f50d8ebb7e994f
+rgb0                58d8a93cf254c8a7affef326a2e88367
+rgba                403329386173553df13d94c7230ec734
+yuv420p             c1d71b5c7f1f65d7e27070355fc7c74a
+yuyv422             ce701473de3deefd9a8a1184e505ffe5
diff --git a/tests/ref/fate/filter-pixfmts-tinterlace_merge b/tests/ref/fate/filter-pixfmts-tinterlace_merge
index 526b77f..4f1f75e 100644
--- a/tests/ref/fate/filter-pixfmts-tinterlace_merge
+++ b/tests/ref/fate/filter-pixfmts-tinterlace_merge
@@ -1,14 +1,14 @@
-gray                330feb7cbe8ede999b93ac802012058a
-yuv410p             c5dac1d3f5a7a51310795daf1ac57992
-yuv411p             2fe635d25d77d7d107ddd9ad2ae1a863
-yuv420p             aea7ee5c4dc21d17c833c5390d9f22ba
-yuv422p             5820321e6a49c72677003163a8fd5ebb
-yuv440p             1011e599e6f2c8095d46ed28d74ae74d
-yuv444p             4602f8acdea686aee4c281d7305831c9
-yuva420p            b7258aaa6de3492642008fff075ecb2c
-yuva422p            b4691c4c3b1bfc9adb5b1d855aadec81
-yuva444p            a83646df12b4674d732e17b93b538be2
-yuvj420p            40b23e9f290aa5fc536337bda1e55118
-yuvj422p            036400f7fdafc1964582811b11677330
-yuvj440p            572bd7e96fe7fc6df118bb213e168f80
-yuvj444p            867f5851eb22ad7d3032333219e8133b
+gray                5bfdd4a77ce5bef266f2e0ce9f4f971b
+yuv410p             2327b4c01e6a16acf18229f3faa4f29f
+yuv411p             486a0448fd543b54eefd599eee613ba4
+yuv420p             36c640c73bdbc62d047a923d2abbc559
+yuv422p             2434b401a62eb3799e441d8b1c2e18f2
+yuv440p             6951eb4455ea2979f65ece3b1132eb5c
+yuv444p             d36e193a9bfc1b21ca16b563d3802d9c
+yuva420p            54139ae3544a9c2695ade817342bd1d6
+yuva422p            0ec7ea9e289365c357ba0a0926d684f3
+yuva444p            bb9cfc136d4a5a2e8c25b5885ff51a38
+yuvj420p            ead0073708f677df3ea594d326954415
+yuvj422p            b76079bba6818dac80d71795403585d8
+yuvj440p            e3d34f02bf946af9d7973701097b3391
+yuvj444p            c1757fcbb3f04d78cf082afe6537a540
diff --git a/tests/ref/fate/gif-disposal-restore b/tests/ref/fate/gif-disposal-restore
index c5ebfcb..0ff1715 100644
--- a/tests/ref/fate/gif-disposal-restore
+++ b/tests/ref/fate/gif-disposal-restore
@@ -1,3 +1,4 @@
 #tb 0: 1/1
 0,          0,          0,        1,   112320, 0xb8afe429
+0,          1,          1,        1,   112320, 0xae588a4b
 0,          3,          3,        1,   112320, 0xccdd27b7
diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt
new file mode 100644
index 0000000..084a222
--- /dev/null
+++ b/tests/ref/fate/opt
@@ -0,0 +1,141 @@
+Testing default values
+num=0
+toggle=1
+string=default
+escape=\=,
+flags=1
+rational=1/1
+video_rate=25/1
+width=200 height=300
+pix_fmt=0bgr
+sample_fmt=s16
+duration=1000
+color=255 192 203 255
+channel_layout=311=311
+binary=62 69 6e 0
+binary_size=4
+num64=1
+flt=0.333333
+dbl=0.333333
+
+Testing av_opt_is_set_to_default()
+name:       num default:1 error:
+name:    toggle default:0 error:
+name:  rational default:0 error:
+name:    string default:0 error:
+name:    escape default:0 error:
+name:     flags default:0 error:
+name:      cool default:1 error:Option not found
+name:      lame default:1 error:Option not found
+name:        mu default:1 error:Option not found
+name:      size default:0 error:
+name:   pix_fmt default:0 error:
+name:sample_fmt default:0 error:
+name:video_rate default:0 error:
+name:  duration default:0 error:
+name:     color default:0 error:
+name:        cl default:0 error:
+name:       bin default:0 error:
+name:      bin1 default:1 error:
+name:      bin2 default:1 error:
+name:     num64 default:0 error:
+name:       flt default:0 error:
+name:       dbl default:0 error:
+name:       num default:1 error:
+name:    toggle default:1 error:
+name:  rational default:1 error:
+name:    string default:1 error:
+name:    escape default:1 error:
+name:     flags default:1 error:
+name:      cool default:1 error:Option not found
+name:      lame default:1 error:Option not found
+name:        mu default:1 error:Option not found
+name:      size default:1 error:
+name:   pix_fmt default:1 error:
+name:sample_fmt default:1 error:
+name:video_rate default:1 error:
+name:  duration default:1 error:
+name:     color default:1 error:
+name:        cl default:1 error:
+name:       bin default:1 error:
+name:      bin1 default:1 error:
+name:      bin2 default:1 error:
+name:     num64 default:1 error:
+name:       flt default:1 error:
+name:       dbl default:1 error:
+
+Test av_opt_serialize()
+num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
+num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0:00:00.001000,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333
+
+Testing av_set_options_string()
+OK    ''
+Error ':'
+Error '='
+Error 'foo=:'
+Error ':=foo'
+Error '=foo'
+Error 'foo='
+Error 'foo'
+Error 'foo=val'
+Error 'foo==val'
+Error 'toggle=:'
+OK    'string=:'
+Error 'toggle=1 : foo'
+Error 'toggle=100'
+Error 'toggle==1'
+OK    'flags=+mu-lame : num=42: toggle=0'
+OK    'num=42 : string=blahblah'
+Error 'rational=0 : rational=1/2 : rational=1/-1'
+Error 'rational=-1/0'
+OK    'size=1024x768'
+OK    'size=pal'
+Error 'size=bogus'
+OK    'pix_fmt=yuv420p'
+OK    'pix_fmt=2'
+Error 'pix_fmt=bogus'
+OK    'sample_fmt=s16'
+OK    'sample_fmt=2'
+Error 'sample_fmt=bogus'
+OK    'video_rate=pal'
+OK    'video_rate=25'
+OK    'video_rate=30000/1001'
+OK    'video_rate=30/1.001'
+Error 'video_rate=bogus'
+Error 'duration=bogus'
+OK    'duration=123.45'
+OK    'duration=1\:23\:45.67'
+OK    'color=blue'
+OK    'color=0x223300'
+OK    'color=0x42FF07AA'
+OK    'cl=stereo+downmix'
+Error 'cl=foo'
+Error 'bin=boguss'
+Error 'bin=111'
+OK    'bin=ffff'
+Error 'num64=bogus'
+OK    'num64=44'
+OK    'num64=44.4'
+Error 'num64=-1'
+Error 'num64=101'
+Error 'flt=bogus'
+OK    'flt=2'
+OK    'flt=2.2'
+Error 'flt=-1'
+Error 'flt=101'
+Error 'dbl=bogus'
+OK    'dbl=2'
+OK    'dbl=2.2'
+Error 'dbl=-1'
+Error 'dbl=101'
+
+Testing av_opt_set_from_string()
+OK    ''
+OK    '5'
+OK    '5:hello'
+OK    '5:hello:size=pal'
+Error '5:size=pal:hello'
+Error ':'
+Error '='
+OK    ' 5 : hello : size = pal '
+Error 'a_very_long_option_name_that_will_need_to_be_ellipsized_around_here=42'
diff --git a/tests/ref/fate/sub-movtextenc b/tests/ref/fate/sub-movtextenc
index e79df0f..e74b8f2 100644
--- a/tests/ref/fate/sub-movtextenc
+++ b/tests/ref/fate/sub-movtextenc
@@ -1 +1 @@
-f632afed498634a01b9c5ae5a2228012
+bb762c178bd8c437a9101c748c1ccb4d
diff --git a/tests/ref/fate/vcr2 b/tests/ref/fate/vcr2
index 521e55f..f7e1540 100644
--- a/tests/ref/fate/vcr2
+++ b/tests/ref/fate/vcr2
@@ -1,4 +1,4 @@
-#tb 0: 16701/250000
+#tb 0: 1001/15000
 0,          0,          0,        1,    38016, 0x50e93e0d
 0,          1,          1,        1,    38016, 0x6ac8627d
 0,          2,          2,        1,    38016, 0x6f38661e
diff --git a/tests/ref/fate/webm-dash-manifest b/tests/ref/fate/webm-dash-manifest
index 4b88040..f5fc912 100644
--- a/tests/ref/fate/webm-dash-manifest
+++ b/tests/ref/fate/webm-dash-manifest
@@ -27,7 +27,7 @@
 </Representation>
 </AdaptationSet>
 <AdaptationSet id="1" mimeType="audio/webm" codecs="vorbis" lang="eng" audioSamplingRate="44100" bitstreamSwitching="true" subsegmentAlignment="false" subsegmentStartsWithSAP="1">
-<Representation id="0" bandwidth="82867">
+<Representation id="2" bandwidth="82867">
 <BaseURL>dash_audio1.webm</BaseURL>
 <SegmentBase
   indexRange="335488-335612">
@@ -35,7 +35,7 @@
   range="0-4103" />
 </SegmentBase>
 </Representation>
-<Representation id="1" bandwidth="82814">
+<Representation id="3" bandwidth="82814">
 <BaseURL>dash_audio2.webm</BaseURL>
 <SegmentBase
   indexRange="335312-335425">
diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm
index c11350a..5de2f39 100644
--- a/tests/ref/lavf/ffm
+++ b/tests/ref/lavf/ffm
@@ -1,3 +1,3 @@
-16cc0ee04b036c210b2fc85182d748e1 *./tests/data/lavf/lavf.ffm
+d5d4e5e3eec336ae6680dde035870564 *./tests/data/lavf/lavf.ffm
 376832 ./tests/data/lavf/lavf.ffm
 ./tests/data/lavf/lavf.ffm CRC=0x000e23ae
diff --git a/tests/ref/lavf/ismv b/tests/ref/lavf/ismv
index c54b857..f29b5ff 100644
--- a/tests/ref/lavf/ismv
+++ b/tests/ref/lavf/ismv
@@ -1,9 +1,9 @@
-564eaa3553ce02cf0921cd647fa4e6d2 *./tests/data/lavf/lavf.ismv
-312606 ./tests/data/lavf/lavf.ismv
-./tests/data/lavf/lavf.ismv CRC=0xb7d29d29
-53f0506abc827a6540a9faf5e3b761c0 *./tests/data/lavf/lavf.ismv
-321512 ./tests/data/lavf/lavf.ismv
-./tests/data/lavf/lavf.ismv CRC=0x33834815
-564eaa3553ce02cf0921cd647fa4e6d2 *./tests/data/lavf/lavf.ismv
-312606 ./tests/data/lavf/lavf.ismv
-./tests/data/lavf/lavf.ismv CRC=0xb7d29d29
+a9ccbb4cd1436d222ef4425567b4e03d *./tests/data/lavf/lavf.ismv
+312542 ./tests/data/lavf/lavf.ismv
+./tests/data/lavf/lavf.ismv CRC=0x9d9a638a
+440d85f9fd5b9f63c2676638782b5c15 *./tests/data/lavf/lavf.ismv
+321448 ./tests/data/lavf/lavf.ismv
+./tests/data/lavf/lavf.ismv CRC=0xe8130120
+a9ccbb4cd1436d222ef4425567b4e03d *./tests/data/lavf/lavf.ismv
+312542 ./tests/data/lavf/lavf.ismv
+./tests/data/lavf/lavf.ismv CRC=0x9d9a638a
diff --git a/tests/ref/vsynth/vsynth1-v210 b/tests/ref/vsynth/vsynth1-v210
index dbafe42..0d12afa 100644
--- a/tests/ref/vsynth/vsynth1-v210
+++ b/tests/ref/vsynth/vsynth1-v210
@@ -1,4 +1,4 @@
-895d30660eb4da017568141a8d1df4e8 *tests/data/fate/vsynth1-v210.avi
+b066679e08cd90c342da21c88bec2a20 *tests/data/fate/vsynth1-v210.avi
 14752448 tests/data/fate/vsynth1-v210.avi
-50973792d3f1abe04a51ee0121f077f2 *tests/data/fate/vsynth1-v210.out.rawvideo
-stddev:    1.85 PSNR: 42.78 MAXDIFF:   29 bytes:  7603200/  7603200
+2ba7f4ca302f3c4147860b9dfb12b6e4 *tests/data/fate/vsynth1-v210.out.rawvideo
+stddev:    1.84 PSNR: 42.81 MAXDIFF:   29 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth1-xface b/tests/ref/vsynth/vsynth1-xface
new file mode 100644
index 0000000..3b916c6
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-xface
@@ -0,0 +1,4 @@
+487c3e53249f7b9f16e04257295998de *tests/data/fate/vsynth1-xface.nut
+19746 tests/data/fate/vsynth1-xface.nut
+42d8261bb538b8789840ac085f7fc4d2 *tests/data/fate/vsynth1-xface.out.rawvideo
+stddev:  103.88 PSNR:  7.80 MAXDIFF:  254 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth2-v210 b/tests/ref/vsynth/vsynth2-v210
index 1320c38..abb425e 100644
--- a/tests/ref/vsynth/vsynth2-v210
+++ b/tests/ref/vsynth/vsynth2-v210
@@ -1,4 +1,4 @@
-6fbbcfee1832fe4c62aacb70454cff62 *tests/data/fate/vsynth2-v210.avi
+fa1c4b1b8d0e9454b4bc2269c7fe634b *tests/data/fate/vsynth2-v210.avi
 14752448 tests/data/fate/vsynth2-v210.avi
-a627fb50c8276200fd71383977d87ca3 *tests/data/fate/vsynth2-v210.out.rawvideo
-stddev:    0.34 PSNR: 57.43 MAXDIFF:    6 bytes:  7603200/  7603200
+7ba6e411e43c6b57c95c49d6848f41e6 *tests/data/fate/vsynth2-v210.out.rawvideo
+stddev:    0.34 PSNR: 57.41 MAXDIFF:    6 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth2-xface b/tests/ref/vsynth/vsynth2-xface
new file mode 100644
index 0000000..5f60d66
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-xface
@@ -0,0 +1,4 @@
+6a1a7b467eeab2795510e7dd1ca528ff *tests/data/fate/vsynth2-xface.nut
+17504 tests/data/fate/vsynth2-xface.nut
+6d87881d630439d02c7a97f468d67a1c *tests/data/fate/vsynth2-xface.out.rawvideo
+stddev:   99.01 PSNR:  8.22 MAXDIFF:  238 bytes:  7603200/  7603200
diff --git a/tests/ref/vsynth/vsynth3-v210 b/tests/ref/vsynth/vsynth3-v210
index d3275f0..0eaf041 100644
--- a/tests/ref/vsynth/vsynth3-v210
+++ b/tests/ref/vsynth/vsynth3-v210
@@ -1,4 +1,4 @@
-d2f5e07f0c0e917d80d63f39d683919e *tests/data/fate/vsynth3-v210.avi
+6618ab86d047f4fb8fdd2d633888b20b *tests/data/fate/vsynth3-v210.avi
 224448 tests/data/fate/vsynth3-v210.avi
-0cf7cf68724fa5146b1667e4fa08b0e1 *tests/data/fate/vsynth3-v210.out.rawvideo
-stddev:    2.12 PSNR: 41.58 MAXDIFF:   26 bytes:    86700/    86700
+198ffb24c06927d8aaac5e59d81a0934 *tests/data/fate/vsynth3-v210.out.rawvideo
+stddev:    2.11 PSNR: 41.61 MAXDIFF:   27 bytes:    86700/    86700
diff --git a/tests/ref/vsynth/vsynth3-xface b/tests/ref/vsynth/vsynth3-xface
new file mode 100644
index 0000000..f98a5c5
--- /dev/null
+++ b/tests/ref/vsynth/vsynth3-xface
@@ -0,0 +1,4 @@
+f399a6b312d0a2d873b8a3bc761c5eba *tests/data/fate/vsynth3-xface.nut
+15696 tests/data/fate/vsynth3-xface.nut
+eafdc027c9c36f96e71e91a5682a0d2e *tests/data/fate/vsynth3-xface.out.rawvideo
+stddev:   97.22 PSNR:  8.37 MAXDIFF:  236 bytes:    86700/    86700
diff --git a/tests/reference.pnm b/tests/reference.pnm
new file mode 100644
index 0000000..e81bd7c
--- /dev/null
+++ b/tests/reference.pnm
Binary files differ
diff --git a/tests/tiny_psnr.c b/tests/tiny_psnr.c
index 6da177a..b35ed81 100644
--- a/tests/tiny_psnr.c
+++ b/tests/tiny_psnr.c
@@ -180,8 +180,7 @@
             switch (len) {
             case 1:
             case 2: {
-                int64_t a = buf[0][j];
-                int64_t b = buf[1][j];
+                int64_t a, b;
                 int dist;
                 if (len == 2) {
                     a = get_s16l(buf[0] + j);
diff --git a/tools/sidxindex.c b/tools/sidxindex.c
new file mode 100644
index 0000000..202d2f0
--- /dev/null
+++ b/tools/sidxindex.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2014 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "libavformat/avformat.h"
+#include "libavutil/avstring.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mathematics.h"
+
+static int usage(const char *argv0, int ret)
+{
+    fprintf(stderr, "%s -out foo.mpd file1\n", argv0);
+    return ret;
+}
+
+struct Track {
+    const char *name;
+    int64_t duration;
+    int bitrate;
+    int track_id;
+    int is_audio, is_video;
+    int width, height;
+    int sample_rate, channels;
+    int timescale;
+    char codec_str[30];
+    int64_t sidx_start, sidx_length;
+    int64_t  earliest_presentation;
+    uint32_t earliest_presentation_timescale;
+};
+
+struct Tracks {
+    int nb_tracks;
+    int64_t duration;
+    struct Track **tracks;
+    int multiple_tracks_per_file;
+};
+
+static void set_codec_str(AVCodecContext *codec, char *str, int size)
+{
+    switch (codec->codec_id) {
+    case AV_CODEC_ID_H264:
+        snprintf(str, size, "avc1");
+        if (codec->extradata_size >= 4 && codec->extradata[0] == 1) {
+            av_strlcatf(str, size, ".%02x%02x%02x",
+                        codec->extradata[1], codec->extradata[2], codec->extradata[3]);
+        }
+        break;
+    case AV_CODEC_ID_AAC:
+        snprintf(str, size, "mp4a.40"); // 0x40 is the mp4 object type for AAC
+        if (codec->extradata_size >= 2) {
+            int aot = codec->extradata[0] >> 3;
+            if (aot == 31)
+                aot = ((AV_RB16(codec->extradata) >> 5) & 0x3f) + 32;
+            av_strlcatf(str, size, ".%d", aot);
+        }
+        break;
+    }
+}
+
+static int find_sidx(struct Tracks *tracks, int start_index,
+                     const char *file)
+{
+    int err = 0;
+    AVIOContext *f = NULL;
+    int i;
+
+    if ((err = avio_open2(&f, file, AVIO_FLAG_READ, NULL, NULL)) < 0)
+        goto fail;
+
+    while (!f->eof_reached) {
+        int64_t pos = avio_tell(f);
+        int32_t size, tag;
+
+        size = avio_rb32(f);
+        tag  = avio_rb32(f);
+        if (size < 8)
+            break;
+        if (tag == MKBETAG('s', 'i', 'd', 'x')) {
+            int version, track_id;
+            uint32_t timescale;
+            int64_t earliest_presentation;
+            version = avio_r8(f);
+            avio_rb24(f); /* flags */
+            track_id = avio_rb32(f);
+            timescale = avio_rb32(f);
+            earliest_presentation = version ? avio_rb64(f) : avio_rb32(f);
+            for (i = start_index; i < tracks->nb_tracks; i++) {
+                struct Track *track = tracks->tracks[i];
+                if (!track->sidx_start) {
+                    track->sidx_start  = pos;
+                    track->sidx_length = size;
+                } else if (pos == track->sidx_start + track->sidx_length) {
+                    track->sidx_length = pos + size - track->sidx_start;
+                }
+                if (track->track_id == track_id) {
+                    track->earliest_presentation = earliest_presentation;
+                    track->earliest_presentation_timescale = timescale;
+                }
+            }
+        }
+        if (avio_seek(f, pos + size, SEEK_SET) != pos + size)
+            break;
+    }
+
+fail:
+    if (f)
+        avio_close(f);
+    return err;
+}
+
+static int handle_file(struct Tracks *tracks, const char *file)
+{
+    AVFormatContext *ctx = NULL;
+    int err = 0, i, orig_tracks = tracks->nb_tracks;
+    char errbuf[50], *ptr;
+    struct Track *track;
+
+    err = avformat_open_input(&ctx, file, NULL, NULL);
+    if (err < 0) {
+        av_strerror(err, errbuf, sizeof(errbuf));
+        fprintf(stderr, "Unable to open %s: %s\n", file, errbuf);
+        return 1;
+    }
+
+    err = avformat_find_stream_info(ctx, NULL);
+    if (err < 0) {
+        av_strerror(err, errbuf, sizeof(errbuf));
+        fprintf(stderr, "Unable to identify %s: %s\n", file, errbuf);
+        goto fail;
+    }
+
+    if (ctx->nb_streams < 1) {
+        fprintf(stderr, "No streams found in %s\n", file);
+        goto fail;
+    }
+    if (ctx->nb_streams > 1)
+        tracks->multiple_tracks_per_file = 1;
+
+    for (i = 0; i < ctx->nb_streams; i++) {
+        struct Track **temp;
+        AVStream *st = ctx->streams[i];
+
+        if (st->codec->bit_rate == 0) {
+            fprintf(stderr, "Skipping track %d in %s as it has zero bitrate\n",
+                    st->id, file);
+            continue;
+        }
+
+        track = av_mallocz(sizeof(*track));
+        if (!track) {
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+        temp = av_realloc(tracks->tracks,
+                          sizeof(*tracks->tracks) * (tracks->nb_tracks + 1));
+        if (!temp) {
+            av_free(track);
+            err = AVERROR(ENOMEM);
+            goto fail;
+        }
+        tracks->tracks = temp;
+        tracks->tracks[tracks->nb_tracks] = track;
+
+        track->name = file;
+        if ((ptr = strrchr(file, '/')))
+            track->name = ptr + 1;
+
+        track->bitrate   = st->codec->bit_rate;
+        track->track_id  = st->id;
+        track->timescale = st->time_base.den;
+        track->duration  = st->duration;
+        track->is_audio  = st->codec->codec_type == AVMEDIA_TYPE_AUDIO;
+        track->is_video  = st->codec->codec_type == AVMEDIA_TYPE_VIDEO;
+
+        if (!track->is_audio && !track->is_video) {
+            fprintf(stderr,
+                    "Track %d in %s is neither video nor audio, skipping\n",
+                    track->track_id, file);
+            av_freep(&tracks->tracks[tracks->nb_tracks]);
+            continue;
+        }
+
+        tracks->duration = FFMAX(tracks->duration,
+                                 av_rescale_rnd(track->duration, AV_TIME_BASE,
+                                                track->timescale, AV_ROUND_UP));
+
+        if (track->is_audio) {
+            track->channels    = st->codec->channels;
+            track->sample_rate = st->codec->sample_rate;
+        }
+        if (track->is_video) {
+            track->width  = st->codec->width;
+            track->height = st->codec->height;
+        }
+        set_codec_str(st->codec, track->codec_str, sizeof(track->codec_str));
+
+        tracks->nb_tracks++;
+    }
+
+    avformat_close_input(&ctx);
+
+    err = find_sidx(tracks, orig_tracks, file);
+
+fail:
+    if (ctx)
+        avformat_close_input(&ctx);
+    return err;
+}
+
+static void write_time(FILE *out, int64_t time, int decimals, enum AVRounding round)
+{
+    int seconds = time / AV_TIME_BASE;
+    int fractions = time % AV_TIME_BASE;
+    int minutes = seconds / 60;
+    int hours = minutes / 60;
+    fractions = av_rescale_rnd(fractions, pow(10, decimals), AV_TIME_BASE, round);
+    seconds %= 60;
+    minutes %= 60;
+    fprintf(out, "PT");
+    if (hours)
+        fprintf(out, "%dH", hours);
+    if (hours || minutes)
+        fprintf(out, "%dM", minutes);
+    fprintf(out, "%d.%0*dS", seconds, decimals, fractions);
+}
+
+static int output_mpd(struct Tracks *tracks, const char *filename)
+{
+    FILE *out;
+    int i, j, ret = 0;
+    struct Track **adaptation_sets_buf[2] = { NULL };
+    struct Track ***adaptation_sets;
+    int nb_tracks_buf[2] = { 0 };
+    int *nb_tracks;
+    int set, nb_sets;
+    int64_t latest_start = 0;
+
+    if (!tracks->multiple_tracks_per_file) {
+        adaptation_sets = adaptation_sets_buf;
+        nb_tracks = nb_tracks_buf;
+        nb_sets = 2;
+        for (i = 0; i < 2; i++) {
+            adaptation_sets[i] = av_malloc(sizeof(*adaptation_sets[i]) * tracks->nb_tracks);
+            if (!adaptation_sets[i]) {
+                ret = AVERROR(ENOMEM);
+                goto err;
+            }
+        }
+        for (i = 0; i < tracks->nb_tracks; i++) {
+            int set_index = -1;
+            if (tracks->tracks[i]->is_video)
+                set_index = 0;
+            else if (tracks->tracks[i]->is_audio)
+                set_index = 1;
+            else
+                continue;
+            adaptation_sets[set_index][nb_tracks[set_index]++] = tracks->tracks[i];
+        }
+    } else {
+        adaptation_sets = &tracks->tracks;
+        nb_tracks = &tracks->nb_tracks;
+        nb_sets = 1;
+    }
+
+    out = fopen(filename, "w");
+    if (!out) {
+        ret = AVERROR(errno);
+        perror(filename);
+        return ret;
+    }
+    fprintf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+    fprintf(out, "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
+                "\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
+                "\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
+                "\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
+                "\tprofiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\"\n"
+                "\ttype=\"static\"\n");
+    fprintf(out, "\tmediaPresentationDuration=\"");
+    write_time(out, tracks->duration, 1, AV_ROUND_DOWN);
+    fprintf(out, "\"\n");
+    fprintf(out, "\tminBufferTime=\"PT5S\">\n");
+
+    for (i = 0; i < tracks->nb_tracks; i++) {
+        int64_t start = av_rescale_rnd(tracks->tracks[i]->earliest_presentation,
+                                       AV_TIME_BASE,
+                                       tracks->tracks[i]->earliest_presentation_timescale,
+                                       AV_ROUND_UP);
+        latest_start = FFMAX(start, latest_start);
+    }
+    fprintf(out, "\t<Period start=\"");
+    write_time(out, latest_start, 3, AV_ROUND_UP);
+    fprintf(out, "\">\n");
+
+
+    for (set = 0; set < nb_sets; set++) {
+        if (nb_tracks[set] == 0)
+            continue;
+        fprintf(out, "\t\t<AdaptationSet segmentAlignment=\"true\">\n");
+        if (nb_sets == 1) {
+            for (i = 0; i < nb_tracks[set]; i++) {
+                struct Track *track = adaptation_sets[set][i];
+                if (strcmp(track->name, adaptation_sets[set][0]->name))
+                    break;
+                fprintf(out, "\t\t\t<ContentComponent id=\"%d\" contentType=\"%s\" />\n", track->track_id, track->is_audio ? "audio" : "video");
+            }
+        }
+
+        for (i = 0; i < nb_tracks[set]; ) {
+            struct Track *first_track = adaptation_sets[set][i];
+            int width = 0, height = 0, sample_rate = 0, channels = 0, bitrate = 0;
+            fprintf(out, "\t\t\t<Representation id=\"%d\" codecs=\"", i);
+            for (j = i; j < nb_tracks[set]; j++) {
+                struct Track *track = adaptation_sets[set][j];
+                if (strcmp(track->name, first_track->name))
+                    break;
+                if (track->is_audio) {
+                    sample_rate = track->sample_rate;
+                    channels = track->channels;
+                }
+                if (track->is_video) {
+                    width = track->width;
+                    height = track->height;
+                }
+                bitrate += track->bitrate;
+                if (j > i)
+                    fprintf(out, ",");
+                fprintf(out, "%s", track->codec_str);
+            }
+            fprintf(out, "\" mimeType=\"%s/mp4\" bandwidth=\"%d\"",
+                    width ? "video" : "audio", bitrate);
+            if (width > 0 && height > 0)
+                fprintf(out, " width=\"%d\" height=\"%d\"", width, height);
+            if (sample_rate > 0)
+                fprintf(out, " audioSamplingRate=\"%d\"", sample_rate);
+            fprintf(out, ">\n");
+            if (channels > 0)
+                fprintf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n", channels);
+            fprintf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", first_track->name);
+            fprintf(out, "\t\t\t\t<SegmentBase indexRange=\"%"PRId64"-%"PRId64"\" />\n", first_track->sidx_start, first_track->sidx_start + first_track->sidx_length - 1);
+            fprintf(out, "\t\t\t</Representation>\n");
+            i = j;
+        }
+        fprintf(out, "\t\t</AdaptationSet>\n");
+    }
+    fprintf(out, "\t</Period>\n");
+    fprintf(out, "</MPD>\n");
+
+    fclose(out);
+err:
+    for (i = 0; i < 2; i++)
+        av_free(adaptation_sets_buf[i]);
+    return ret;
+}
+
+static void clean_tracks(struct Tracks *tracks)
+{
+    int i;
+    for (i = 0; i < tracks->nb_tracks; i++) {
+        av_freep(&tracks->tracks[i]);
+    }
+    av_freep(&tracks->tracks);
+    tracks->nb_tracks = 0;
+}
+
+int main(int argc, char **argv)
+{
+    const char *out = NULL;
+    struct Tracks tracks = { 0 };
+    int i;
+
+    av_register_all();
+
+    for (i = 1; i < argc; i++) {
+        if (!strcmp(argv[i], "-out")) {
+            out = argv[i + 1];
+            i++;
+        } else if (argv[i][0] == '-') {
+            return usage(argv[0], 1);
+        } else {
+            if (handle_file(&tracks, argv[i]))
+                return 1;
+        }
+    }
+    if (!tracks.nb_tracks || !out)
+        return usage(argv[0], 1);
+
+    output_mpd(&tracks, out);
+
+    clean_tracks(&tracks);
+
+    return 0;
+}