diff --git a/configure b/configure
index b1280f98659e5e29608cc0625fb7ce14e3060993..38a7fbb8ef83f69d03cb68eba55df446ba5bab17 100755
--- a/configure
+++ b/configure
@@ -1607,6 +1607,7 @@ atrac3_decoder_select="mdct"
 binkaudio_dct_decoder_select="mdct rdft dct sinewin"
 binkaudio_rdft_decoder_select="mdct rdft sinewin"
 cavs_decoder_select="golomb mpegvideo"
+comfortnoise_encoder_select="lpc"
 cook_decoder_select="mdct sinewin"
 cscd_decoder_select="lzo"
 cscd_decoder_suggest="zlib"
diff --git a/doc/filters.texi b/doc/filters.texi
index 0e77914a6ea25893696c43800f8053b69b68a578..a264606d54d4b508f3a27929a869c8c31005f300 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -414,37 +414,34 @@ A description of each shown parameter follows:
 sequential number of the input frame, starting from 0
 
 @item pts
-presentation TimeStamp of the input frame, expressed as a number of
-time base units. The time base unit depends on the filter input pad, and
-is usually 1/@var{sample_rate}.
+Presentation timestamp of the input frame, in time base units; the time base
+depends on the filter input pad, and is usually 1/@var{sample_rate}.
 
 @item pts_time
-presentation TimeStamp of the input frame, expressed as a number of
-seconds
+presentation timestamp of the input frame in seconds
 
 @item pos
 position of the frame in the input stream, -1 if this information in
 unavailable and/or meaningless (for example in case of synthetic audio)
 
 @item fmt
-sample format name
+sample format
 
 @item chlayout
-channel layout description
-
-@item nb_samples
-number of samples (per each channel) contained in the filtered frame
+channel layout
 
 @item rate
 sample rate for the audio frame
 
+@item nb_samples
+number of samples (per channel) in the frame
+
 @item checksum
-Adler-32 checksum (printed in hexadecimal) of all the planes of the input frame
+Adler-32 checksum (printed in hexadecimal) of the audio data. For planar audio
+the data is treated as if all the planes were concatenated.
 
-@item plane_checksum
-Adler-32 checksum (printed in hexadecimal) for each input frame plane,
-expressed in the form "[@var{c0} @var{c1} @var{c2} @var{c3} @var{c4} @var{c5}
-@var{c6} @var{c7}]"
+@item plane_checksums
+A list of Adler-32 checksums for each data plane.
 @end table
 
 @section asplit
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index bb97e5df08a5bb39c740283c500b6d37472b2f9a..5f8776da0ad31f5cf1479446c656ca8ab257075d 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -145,6 +145,8 @@ OBJS-$(CONFIG_CLJR_DECODER)            += cljr.o
 OBJS-$(CONFIG_CLJR_ENCODER)            += cljr.o
 OBJS-$(CONFIG_CLLC_DECODER)            += cllc.o
 OBJS-$(CONFIG_COOK_DECODER)            += cook.o
+OBJS-$(CONFIG_COMFORTNOISE_DECODER)    += cngdec.o celp_filters.o
+OBJS-$(CONFIG_COMFORTNOISE_ENCODER)    += cngenc.o
 OBJS-$(CONFIG_CPIA_DECODER)            += cpia.o
 OBJS-$(CONFIG_CSCD_DECODER)            += cscd.o
 OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 8d11909ffbd96798fe9749690cf732e75f307461..6bad57361704a407a3acfb82e43ec46933641997 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -97,6 +97,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER (CINEPAK, cinepak);
     REGISTER_ENCDEC  (CLJR, cljr);
     REGISTER_DECODER (CLLC, cllc);
+    REGISTER_ENCDEC  (COMFORTNOISE, comfortnoise);
     REGISTER_DECODER (CPIA, cpia);
     REGISTER_DECODER (CSCD, cscd);
     REGISTER_DECODER (CYUV, cyuv);
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 1495c9e2bd50b86536ef0ab90fc2329707651dc3..a08cd031aa90c9e4ba0d6977f6285df4a20251d1 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -426,6 +426,7 @@ enum AVCodecID {
     AV_CODEC_ID_IAC,
     AV_CODEC_ID_ILBC,
     AV_CODEC_ID_OPUS_DEPRECATED,
+    AV_CODEC_ID_COMFORT_NOISE,
     AV_CODEC_ID_FFWAVESYNTH = MKBETAG('F','F','W','S'),
     AV_CODEC_ID_8SVX_RAW    = MKBETAG('8','S','V','X'),
     AV_CODEC_ID_SONIC       = MKBETAG('S','O','N','C'),
diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c
new file mode 100644
index 0000000000000000000000000000000000000000..0daeb9b969e5990fc2001c7f68126fa6ddd5a955
--- /dev/null
+++ b/libavcodec/cngdec.c
@@ -0,0 +1,162 @@
+/*
+ * RFC 3389 comfort noise generator
+ * Copyright (c) 2012 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 <math.h>
+
+#include "libavutil/common.h"
+#include "avcodec.h"
+#include "celp_filters.h"
+#include "libavutil/lfg.h"
+
+typedef struct CNGContext {
+    AVFrame avframe;
+    float *refl_coef, *target_refl_coef;
+    float *lpc_coef;
+    int order;
+    int energy, target_energy;
+    float *filter_out;
+    float *excitation;
+    AVLFG lfg;
+} CNGContext;
+
+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);
+    return 0;
+}
+
+static av_cold int cng_decode_init(AVCodecContext *avctx)
+{
+    CNGContext *p = avctx->priv_data;
+
+    avctx->sample_fmt  = AV_SAMPLE_FMT_S16;
+    avctx->channels    = 1;
+    avctx->sample_rate = 8000;
+
+    avcodec_get_frame_defaults(&p->avframe);
+    avctx->coded_frame  = &p->avframe;
+    p->order            = 12;
+    avctx->frame_size   = 640;
+    p->refl_coef        = av_mallocz(p->order * sizeof(*p->refl_coef));
+    p->target_refl_coef = av_mallocz(p->order * sizeof(*p->target_refl_coef));
+    p->lpc_coef         = av_mallocz(p->order * sizeof(*p->lpc_coef));
+    p->filter_out       = av_mallocz((avctx->frame_size + p->order) *
+                                     sizeof(*p->filter_out));
+    p->excitation       = av_mallocz(avctx->frame_size * sizeof(*p->excitation));
+    if (!p->refl_coef || !p->target_refl_coef || !p->lpc_coef ||
+        !p->filter_out || !p->excitation) {
+        cng_decode_close(avctx);
+        return AVERROR(ENOMEM);
+    }
+
+    av_lfg_init(&p->lfg, 0);
+
+    return 0;
+}
+
+static void make_lpc_coefs(float *lpc, const float *refl, int order)
+{
+    float buf[100];
+    float *next, *cur;
+    int m, i;
+    next = buf;
+    cur  = lpc;
+    for (m = 0; m < order; m++) {
+        next[m] = refl[m];
+        for (i = 0; i < m; i++)
+            next[i] = cur[i] + refl[m] * cur[m - i - 1];
+        FFSWAP(float*, next, cur);
+    }
+    if (cur != lpc)
+        memcpy(lpc, cur, sizeof(*lpc) * order);
+}
+
+static int cng_decode_frame(AVCodecContext *avctx, void *data,
+                              int *got_frame_ptr, AVPacket *avpkt)
+{
+
+    CNGContext *p = avctx->priv_data;
+    int buf_size  = avpkt->size;
+    int ret, i;
+    int16_t *buf_out;
+    float e = 1.0;
+    float scaling;
+
+    if (avpkt->size) {
+        float dbov = -avpkt->data[0] / 10.0;
+        p->target_energy = 1081109975 * pow(10, dbov) * 0.75;
+        memset(p->target_refl_coef, 0, sizeof(p->refl_coef));
+        for (i = 0; i < FFMIN(avpkt->size - 1, p->order); i++) {
+            p->target_refl_coef[i] = (avpkt->data[1 + i] - 127) / 128.0;
+        }
+        make_lpc_coefs(p->lpc_coef, p->refl_coef, p->order);
+    }
+
+    p->energy = p->energy / 2 + p->target_energy / 2;
+    for (i = 0; i < p->order; i++)
+        p->refl_coef[i] = 0.6 *p->refl_coef[i] + 0.4 * p->target_refl_coef[i];
+
+    for (i = 0; i < p->order; i++)
+        e *= 1.0 - p->refl_coef[i]*p->refl_coef[i];
+
+    scaling = sqrt(e * p->energy / 1081109975);
+    for (i = 0; i < avctx->frame_size; i++) {
+        int r = (av_lfg_get(&p->lfg) & 0xffff) - 0x8000;
+        p->excitation[i] = scaling * r;
+    }
+    ff_celp_lp_synthesis_filterf(p->filter_out + p->order, p->lpc_coef,
+                                 p->excitation, avctx->frame_size, p->order);
+
+    p->avframe.nb_samples = avctx->frame_size;
+    if ((ret = avctx->get_buffer(avctx, &p->avframe)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+        return ret;
+    }
+    buf_out = (int16_t *)p->avframe.data[0];
+    for (i = 0; i < avctx->frame_size; i++)
+        buf_out[i] = p->filter_out[i + p->order];
+    memcpy(p->filter_out, p->filter_out + avctx->frame_size,
+           p->order * sizeof(*p->filter_out));
+
+    *got_frame_ptr   = 1;
+    *(AVFrame *)data = p->avframe;
+
+    return buf_size;
+}
+
+AVCodec ff_comfortnoise_decoder = {
+    .name           = "comfortnoise",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_COMFORT_NOISE,
+    .priv_data_size = sizeof(CNGContext),
+    .init           = cng_decode_init,
+    .decode         = cng_decode_frame,
+    .close          = cng_decode_close,
+    .long_name      = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"),
+    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+                                                     AV_SAMPLE_FMT_NONE },
+    .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_DR1,
+};
diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c
new file mode 100644
index 0000000000000000000000000000000000000000..a1dcfa61153f0696b65c86679285defbf53e7b5f
--- /dev/null
+++ b/libavcodec/cngenc.c
@@ -0,0 +1,116 @@
+/*
+ * RFC 3389 comfort noise generator
+ * Copyright (c) 2012 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 <math.h>
+
+#include "libavutil/common.h"
+#include "avcodec.h"
+#include "internal.h"
+#include "lpc.h"
+
+typedef struct CNGContext {
+    LPCContext lpc;
+    int order;
+    int32_t *samples32;
+    double *ref_coef;
+} CNGContext;
+
+static av_cold int cng_encode_close(AVCodecContext *avctx)
+{
+    CNGContext *p = avctx->priv_data;
+    ff_lpc_end(&p->lpc);
+    av_free(p->samples32);
+    av_free(p->ref_coef);
+    return 0;
+}
+
+static av_cold int cng_encode_init(AVCodecContext *avctx)
+{
+    CNGContext *p = avctx->priv_data;
+    int ret;
+
+    if (avctx->channels != 1) {
+        av_log(avctx, AV_LOG_ERROR, "Only mono supported\n");
+        return AVERROR(EINVAL);
+    }
+
+    avctx->frame_size = 640;
+    p->order = 10;
+    if ((ret = ff_lpc_init(&p->lpc, avctx->frame_size, p->order, FF_LPC_TYPE_LEVINSON)) < 0)
+        return ret;
+    p->samples32 = av_malloc(avctx->frame_size * sizeof(*p->samples32));
+    p->ref_coef = av_malloc(p->order * sizeof(*p->ref_coef));
+    if (!p->samples32 || !p->ref_coef) {
+        cng_encode_close(avctx);
+        return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+static int cng_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
+                             const AVFrame *frame, int *got_packet_ptr)
+{
+    CNGContext *p = avctx->priv_data;
+    int ret, i;
+    double energy = 0;
+    int qdbov;
+    int16_t *samples = (int16_t*) frame->data[0];
+
+    if ((ret = ff_alloc_packet(avpkt, 1 + p->order))) {
+        av_log(avctx, AV_LOG_ERROR, "Error getting output packet\n");
+        return ret;
+    }
+
+    for (i = 0; i < frame->nb_samples; i++) {
+        p->samples32[i] = samples[i];
+        energy += samples[i] * samples[i];
+    }
+    energy /= frame->nb_samples;
+    if (energy > 0) {
+        double dbov = 10 * log10(energy / 1081109975);
+        qdbov = av_clip(-floor(dbov), 0, 127);
+    } else {
+        qdbov = 127;
+    }
+    ret = ff_lpc_calc_ref_coefs(&p->lpc, p->samples32, p->order, p->ref_coef);
+    avpkt->data[0] = qdbov;
+    for (i = 0; i < p->order; i++)
+        avpkt->data[1 + i] = p->ref_coef[i] * 127 + 127;
+
+    *got_packet_ptr = 1;
+    avpkt->size = 1 + p->order;
+
+    return 0;
+}
+
+AVCodec ff_comfortnoise_encoder = {
+    .name           = "comfortnoise",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = AV_CODEC_ID_COMFORT_NOISE,
+    .priv_data_size = sizeof(CNGContext),
+    .init           = cng_encode_init,
+    .encode2        = cng_encode_frame,
+    .close          = cng_encode_close,
+    .long_name      = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"),
+    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
+                                                     AV_SAMPLE_FMT_NONE },
+};
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 09b3015f3756f8b929d98e87adca27c994c05797..48dbe06b1fcc467eddab9ae0a6c094b3b74cb274 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -2264,6 +2264,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
         .long_name = NULL_IF_CONFIG_SMALL("Opus (Opus Interactive Audio Codec)"),
         .props     = AV_CODEC_PROP_LOSSY,
     },
+    {
+        .id        = AV_CODEC_ID_COMFORT_NOISE,
+        .type      = AVMEDIA_TYPE_AUDIO,
+        .name      = "comfortnoise",
+        .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 Comfort Noise"),
+        .props     = AV_CODEC_PROP_LOSSY,
+    },
     {
         .id        = AV_CODEC_ID_TAK,
         .type      = AVMEDIA_TYPE_AUDIO,
diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c
index 5ccd5a8e0843927632fac192704c19615fbfd85c..019689a2476c9d0a1d71680d867c1b4c072cd456 100644
--- a/libavcodec/lpc.c
+++ b/libavcodec/lpc.c
@@ -149,6 +149,18 @@ static int estimate_best_order(double *ref, int min_order, int max_order)
     return est;
 }
 
+int ff_lpc_calc_ref_coefs(LPCContext *s,
+                          const int32_t *samples, int order, double *ref)
+{
+    double autoc[MAX_LPC_ORDER + 1];
+
+    s->lpc_apply_welch_window(samples, s->blocksize, s->windowed_samples);
+    s->lpc_compute_autocorr(s->windowed_samples, s->blocksize, order, autoc);
+    compute_ref_coefs(autoc, order, ref, NULL);
+
+    return order;
+}
+
 /**
  * Calculate LPC coefficients for multiple orders
  *
diff --git a/libavcodec/lpc.h b/libavcodec/lpc.h
index b9c35bd30369f797133d611707ab90df613a9871..24f776a244faf098779b3d5133940b9a60a852a0 100644
--- a/libavcodec/lpc.h
+++ b/libavcodec/lpc.h
@@ -93,6 +93,9 @@ int ff_lpc_calc_coefs(LPCContext *s,
                       enum FFLPCType lpc_type, int lpc_passes,
                       int omethod, int max_shift, int zero_shift);
 
+int ff_lpc_calc_ref_coefs(LPCContext *s,
+                          const int32_t *samples, int order, double *ref);
+
 /**
  * Initialize LPCContext.
  */
@@ -111,6 +114,37 @@ void ff_lpc_end(LPCContext *s);
 #define LPC_TYPE float
 #endif
 
+/**
+ * Schur recursion.
+ * Produces reflection coefficients from autocorrelation data.
+ */
+static inline void compute_ref_coefs(const LPC_TYPE *autoc, int max_order,
+                                     LPC_TYPE *ref, LPC_TYPE *error)
+{
+    int i, j;
+    LPC_TYPE err;
+    LPC_TYPE gen0[MAX_LPC_ORDER], gen1[MAX_LPC_ORDER];
+
+    for (i = 0; i < max_order; i++)
+        gen0[i] = gen1[i] = autoc[i + 1];
+
+    err    = autoc[0];
+    ref[0] = -gen1[0] / err;
+    err   +=  gen1[0] * ref[0];
+    if (error)
+        error[0] = err;
+    for (i = 1; i < max_order; i++) {
+        for (j = 0; j < max_order - i; j++) {
+            gen1[j] = gen1[j + 1] + ref[i - 1] * gen0[j];
+            gen0[j] = gen1[j + 1] * ref[i - 1] + gen0[j];
+        }
+        ref[i] = -gen1[0] / err;
+        err   +=  gen1[0] * ref[i];
+        if (error)
+            error[i] = err;
+    }
+}
+
 /**
  * Levinson-Durbin recursion.
  * Produce LPC coefficients from autocorrelation data.
diff --git a/libavcodec/version.h b/libavcodec/version.h
index f878efe811a758067ebebf53753bf1a85b32d330..67ff16919d509ac6551d9e516ef253069d92d3e9 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 #include "libavutil/avutil.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 54
-#define LIBAVCODEC_VERSION_MINOR 69
+#define LIBAVCODEC_VERSION_MINOR 70
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c
index 25a5e2ca672034a70c3bb6672a1afb2f5b136e91..1a70deee28c2605c59593f32e5ef5ec3e22108ca 100644
--- a/libavfilter/af_ashowinfo.c
+++ b/libavfilter/af_ashowinfo.c
@@ -23,84 +23,117 @@
  * filter for showing textual audio frame information
  */
 
+#include <inttypes.h>
+#include <stddef.h>
+
 #include "libavutil/adler32.h"
 #include "libavutil/audioconvert.h"
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
 #include "libavutil/timestamp.h"
+#include "libavutil/samplefmt.h"
+
 #include "audio.h"
 #include "avfilter.h"
 
-typedef struct {
-    unsigned int frame;
-} ShowInfoContext;
+typedef struct AShowInfoContext {
+    /**
+     * Scratch space for individual plane checksums for planar audio
+     */
+    uint32_t *plane_checksums;
+
+    /**
+     * Frame counter
+     */
+    uint64_t frame;
+} AShowInfoContext;
 
-static av_cold int init(AVFilterContext *ctx, const char *args)
+static int config_input(AVFilterLink *inlink)
 {
-    ShowInfoContext *showinfo = ctx->priv;
-    showinfo->frame = 0;
+    AShowInfoContext *s = inlink->dst->priv;
+    int channels = av_get_channel_layout_nb_channels(inlink->channel_layout);
+    s->plane_checksums = av_malloc(channels * sizeof(*s->plane_checksums));
+    if (!s->plane_checksums)
+        return AVERROR(ENOMEM);
+
     return 0;
 }
 
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
+static void uninit(AVFilterContext *ctx)
+{
+    AShowInfoContext *s = ctx->priv;
+    av_freep(&s->plane_checksums);
+}
+
+static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
 {
     AVFilterContext *ctx = inlink->dst;
-    ShowInfoContext *showinfo = ctx->priv;
-    uint32_t plane_checksum[8] = {0}, checksum = 0;
+    AShowInfoContext *s  = ctx->priv;
     char chlayout_str[128];
-    int plane;
-    int linesize =
-        samplesref->audio->nb_samples *
-        av_get_bytes_per_sample(samplesref->format);
-    if (!av_sample_fmt_is_planar(samplesref->format))
-        linesize *= av_get_channel_layout_nb_channels(samplesref->audio->channel_layout);
-
-    for (plane = 0; plane < 8 && samplesref->data[plane]; plane++) {
-        uint8_t *data = samplesref->data[plane];
-
-        plane_checksum[plane] = av_adler32_update(plane_checksum[plane],
-                                                  data, linesize);
-        checksum = av_adler32_update(checksum, data, linesize);
+    uint32_t checksum = 0;
+    int channels    = av_get_channel_layout_nb_channels(buf->audio->channel_layout);
+    int planar      = av_sample_fmt_is_planar(buf->format);
+    int block_align = av_get_bytes_per_sample(buf->format) * (planar ? 1 : channels);
+    int data_size   = buf->audio->nb_samples * block_align;
+    int planes      = planar ? channels : 1;
+    int i;
+
+    for (i = 0; i < planes; i++) {
+        uint8_t *data = buf->extended_data[i];
+
+        s->plane_checksums[i] = av_adler32_update(0, data, data_size);
+        checksum = i ? av_adler32_update(checksum, data, data_size) :
+                       s->plane_checksums[0];
     }
 
     av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), -1,
-                                 samplesref->audio->channel_layout);
+                                 buf->audio->channel_layout);
 
     av_log(ctx, AV_LOG_INFO,
-           "n:%d pts:%s pts_time:%s pos:%"PRId64" "
-           "fmt:%s chlayout:%s nb_samples:%d rate:%d "
-           "checksum:%08X plane_checksum[%08X",
-           showinfo->frame,
-           av_ts2str(samplesref->pts), av_ts2timestr(samplesref->pts, &inlink->time_base),
-           samplesref->pos,
-           av_get_sample_fmt_name(samplesref->format),
-           chlayout_str,
-           samplesref->audio->nb_samples,
-           samplesref->audio->sample_rate,
-           checksum,
-           plane_checksum[0]);
-
-    for (plane = 1; plane < 8 && samplesref->data[plane]; plane++)
-        av_log(ctx, AV_LOG_INFO, " %08X", plane_checksum[plane]);
+           "n:%"PRIu64" pts:%s pts_time:%s pos:%"PRId64" "
+           "fmt:%s chlayout:%s rate:%d nb_samples:%d "
+           "checksum:%08X ",
+           s->frame,
+           av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base),
+           buf->pos,
+           av_get_sample_fmt_name(buf->format), chlayout_str,
+           buf->audio->sample_rate, buf->audio->nb_samples,
+           checksum);
+
+    av_log(ctx, AV_LOG_INFO, "plane_checksums: [ ");
+    for (i = 0; i < planes; i++)
+        av_log(ctx, AV_LOG_INFO, "%08X ", s->plane_checksums[i]);
     av_log(ctx, AV_LOG_INFO, "]\n");
 
-    showinfo->frame++;
-    return ff_filter_samples(inlink->dst->outputs[0], samplesref);
+    s->frame++;
+    return ff_filter_samples(inlink->dst->outputs[0], buf);
 }
 
+static const AVFilterPad inputs[] = {
+    {
+        .name       = "default",
+        .type             = AVMEDIA_TYPE_AUDIO,
+        .get_audio_buffer = ff_null_get_audio_buffer,
+        .config_props     = config_input,
+        .filter_samples   = filter_samples,
+        .min_perms        = AV_PERM_READ,
+    },
+    { NULL },
+};
+
+static const AVFilterPad outputs[] = {
+    {
+        .name = "default",
+        .type = AVMEDIA_TYPE_AUDIO,
+    },
+    { NULL },
+};
+
 AVFilter avfilter_af_ashowinfo = {
     .name        = "ashowinfo",
     .description = NULL_IF_CONFIG_SMALL("Show textual information for each audio frame."),
-
-    .priv_size = sizeof(ShowInfoContext),
-    .init      = init,
-
-    .inputs    = (const AVFilterPad[]) {{ .name       = "default",
-                                    .type             = AVMEDIA_TYPE_AUDIO,
-                                    .get_audio_buffer = ff_null_get_audio_buffer,
-                                    .filter_samples   = filter_samples,
-                                    .min_perms        = AV_PERM_READ, },
-                                  { .name = NULL}},
-
-    .outputs   = (const AVFilterPad[]) {{ .name       = "default",
-                                    .type             = AVMEDIA_TYPE_AUDIO },
-                                  { .name = NULL}},
+    .priv_size   = sizeof(AShowInfoContext),
+    .uninit      = uninit,
+    .inputs      = inputs,
+    .outputs     = outputs,
 };
diff --git a/libavfilter/version.h b/libavfilter/version.h
index ff381079c5fcff7d582461a3334bf2f2107ea43f..f09b6cb0e414ba93159315256de49d5f6e87eaa9 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -30,7 +30,7 @@
 
 #define LIBAVFILTER_VERSION_MAJOR  3
 #define LIBAVFILTER_VERSION_MINOR  20
-#define LIBAVFILTER_VERSION_MICRO 109
+#define LIBAVFILTER_VERSION_MICRO 110
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                LIBAVFILTER_VERSION_MINOR, \
diff --git a/libavformat/dv.c b/libavformat/dv.c
index 1d5ec2cf895088bd792e15b022f90a5d6fcb11cf..75d213662887a703c81635b77c138c2a5a21d359 100644
--- a/libavformat/dv.c
+++ b/libavformat/dv.c
@@ -391,7 +391,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt,
     pkt->pos          = pos;
     pkt->size         = size;
     pkt->flags       |= AV_PKT_FLAG_KEY;
-    pkt->stream_index = c->vst->id;
+    pkt->stream_index = c->vst->index;
     pkt->pts          = c->frames;
 
     c->frames++;
diff --git a/libavresample/avresample.h b/libavresample/avresample.h
index ea93952e2eeed97acf78c145790d5d444acabebe..b0a9e247e87cba1144630cb44cf692baca42f273 100644
--- a/libavresample/avresample.h
+++ b/libavresample/avresample.h
@@ -23,9 +23,76 @@
 
 /**
  * @file
+ * @ingroup lavr
  * external API header
  */
 
+/**
+ * @defgroup lavr Libavresample
+ * @{
+ *
+ * Libavresample (lavr) is a library that handles audio resampling, sample
+ * format conversion and mixing.
+ *
+ * Interaction with lavr is done through AVAudioResampleContext, which is
+ * allocated with avresample_alloc_context(). It is opaque, so all parameters
+ * must be set with the @ref avoptions API.
+ *
+ * For example the following code will setup conversion from planar float sample
+ * format to interleaved signed 16-bit integer, downsampling from 48kHz to
+ * 44.1kHz and downmixing from 5.1 channels to stereo (using the default mixing
+ * matrix):
+ * @code
+ * AVAudioResampleContext *avr = avresample_alloc_context();
+ * av_opt_set_int(avr, "in_channel_layout",  AV_CH_LAYOUT_5POINT1, 0);
+ * av_opt_set_int(avr, "out_channel_layout", AV_CH_LAYOUT_STEREO,  0);
+ * av_opt_set_int(avr, "in_sample_rate",     48000,                0);
+ * av_opt_set_int(avr, "out_sample_rate",    44100,                0);
+ * av_opt_set_int(avr, "in_sample_fmt",      AV_SAMPLE_FMT_FLTP,   0);
+ * av_opt_set_int(avr, "out_sample_fmt,      AV_SAMPLE_FMT_S16,    0);
+ * @endcode
+ *
+ * Once the context is initialized, it must be opened with avresample_open(). If
+ * you need to change the conversion parameters, you must close the context with
+ * avresample_close(), change the parameters as described above, then reopen it
+ * again.
+ *
+ * The conversion itself is done by repeatedly calling avresample_convert().
+ * Note that the samples may get buffered in two places in lavr. The first one
+ * is the output FIFO, where the samples end up if the output buffer is not
+ * large enough. The data stored in there may be retrieved at any time with
+ * avresample_read(). The second place is the resampling delay buffer,
+ * applicable only when resampling is done. The samples in it require more input
+ * before they can be processed. Their current amount is returned by
+ * avresample_get_delay(). At the end of conversion the resampling buffer can be
+ * flushed by calling avresample_convert() with NULL input.
+ *
+ * The following code demonstrates the conversion loop assuming the parameters
+ * from above and caller-defined functions get_input() and handle_output():
+ * @code
+ * uint8_t **input;
+ * int in_linesize, in_samples;
+ *
+ * while (get_input(&input, &in_linesize, &in_samples)) {
+ *     uint8_t *output
+ *     int out_linesize;
+ *     int out_samples = avresample_available(avr) +
+ *                       av_rescale_rnd(avresample_get_delay(avr) +
+ *                                      in_samples, 44100, 48000, AV_ROUND_UP);
+ *     av_samples_alloc(&output, &out_linesize, 2, out_samples,
+ *                      AV_SAMPLE_FMT_S16, 0);
+ *     out_samples = avresample_convert(avr, &output, out_linesize, out_samples,
+ *                                      input, in_linesize, in_samples);
+ *     handle_output(output, out_linesize, out_samples);
+ *     av_freep(&output);
+ *  }
+ *  @endcode
+ *
+ *  When the conversion is finished and the FIFOs are flushed if required, the
+ *  conversion context and everything associated with it must be freed with
+ *  avresample_free().
+ */
+
 #include "libavutil/audioconvert.h"
 #include "libavutil/avutil.h"
 #include "libavutil/dict.h"
@@ -198,6 +265,10 @@ int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta,
 /**
  * Convert input samples and write them to the output FIFO.
  *
+ * The upper bound on the number of output samples is given by
+ * avresample_available() + (avresample_get_delay() + number of input samples) *
+ * output sample rate / input sample rate.
+ *
  * The output data can be NULL or have fewer allocated samples than required.
  * In this case, any remaining samples not written to the output will be added
  * to an internal FIFO buffer, to be returned at the next call to this function
@@ -289,4 +360,8 @@ int avresample_available(AVAudioResampleContext *avr);
  */
 int avresample_read(AVAudioResampleContext *avr, uint8_t **output, int nb_samples);
 
+/**
+ * @}
+ */
+
 #endif /* AVRESAMPLE_AVRESAMPLE_H */
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index ae6eef12454cc942c4bdfebdcc8e1afcf8e5ac20..db016a58dd451620844e7f34628e416fd17f3957 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -39,6 +39,7 @@
  * @li @ref libavf "libavformat" I/O and muxing/demuxing library
  * @li @ref lavd "libavdevice" special devices muxing/demuxing library
  * @li @ref lavu "libavutil" common utility library
+ * @li @ref libswresample "libswresample" audio resampling, format conversion and mixing
  * @li @subpage libpostproc post processing library
  * @li @subpage libswscale  color conversion and scaling library
  */
diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak
index d15c7cd5be6a69bbd58178125e0959c8d8d4437c..cde214175cd7ab926dfe9185f9d86037aedf1468 100644
--- a/tests/fate/ac3.mak
+++ b/tests/fate/ac3.mak
@@ -44,14 +44,17 @@ fate-eac3-4: REF = $(SAMPLES)/eac3/serenity_english_5.1_1536_small.pcm
 
 $(FATE_AC3) $(FATE_EAC3): CMP = oneoff
 
-FATE_AC3_ENCODE += fate-ac3-encode
+FATE_AC3-$(call  DEMDEC, AC3,  AC3)  += $(FATE_AC3)
+FATE_EAC3-$(call DEMDEC, EAC3, EAC3) += $(FATE_EAC3)
+
+FATE_AC3-$(call ENCDEC, AC3, AC3) += fate-ac3-encode
 fate-ac3-encode: CMD = enc_dec_pcm ac3 wav s16le $(REF) -c:a ac3 -b:a 128k
 fate-ac3-encode: CMP_SHIFT = -1024
 fate-ac3-encode: CMP_TARGET = 399.62
 fate-ac3-encode: SIZE_TOLERANCE = 488
 fate-ac3-encode: FUZZ = 4
 
-FATE_EAC3_ENCODE += fate-eac3-encode
+FATE_EAC3-$(call ENCDEC, EAC3, EAC3) += fate-eac3-encode
 fate-eac3-encode: CMD = enc_dec_pcm eac3 wav s16le $(REF) -c:a eac3 -b:a 128k
 fate-eac3-encode: CMP_SHIFT = -1024
 fate-eac3-encode: CMP_TARGET = 514.02
@@ -61,15 +64,13 @@ fate-eac3-encode: FUZZ = 3
 fate-ac3-encode fate-eac3-encode: CMP = stddev
 fate-ac3-encode fate-eac3-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
 
-FATE_AC3_FIXED_ENCODE += fate-ac3-fixed-encode
+FATE_AC3-$(call ENCMUX, AC3_FIXED, AC3) += fate-ac3-fixed-encode
 fate-ac3-fixed-encode: tests/data/asynth-44100-2.wav
 fate-ac3-fixed-encode: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav
 fate-ac3-fixed-encode: CMD = md5 -i $(SRC) -c ac3_fixed -ab 128k -f ac3 -flags +bitexact
 fate-ac3-fixed-encode: CMP = oneline
 fate-ac3-fixed-encode: REF = a1d1fc116463b771abf5aef7ed37d7b1
 
-FATE_SAMPLES_AVCONV += $(FATE_AC3) $(FATE_AC3_ENCODE) $(FATE_AC3_FIXED_ENCODE)
-FATE_SAMPLES_AVCONV += $(FATE_EAC3) $(FATE_EAC3_ENCODE)
+FATE_SAMPLES_AVCONV- += $(FATE_AC3-yes) $(FATE_EAC3-yes)
 
-fate-ac3: $(FATE_AC3) $(FATE_AC3_ENCODE) $(FATE_AC3_FIXED_ENCODE)
-fate-ac3: $(FATE_EAC3) $(FATE_EAC3_ENCODE)
+fate-ac3: $(FATE_AC3-yes) $(FATE_EAC3-yes)