OSDN Git Service

Merge commit '759001c534287a96dc96d1e274665feb7059145d'
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 12 Mar 2013 02:20:18 +0000 (03:20 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 12 Mar 2013 02:23:28 +0000 (03:23 +0100)
* commit '759001c534287a96dc96d1e274665feb7059145d':
  lavc decoders: work with refcounted frames.

Anton Khirnov (1):
      lavc decoders: work with refcounted frames.

Clément Bœsch (47):
      lavc/ansi: reset file
      lavc/ansi: re-do refcounted frame changes from Anton
      fraps: reset file
      lavc/fraps: switch to refcounted frames
      gifdec: reset file
      lavc/gifdec: switch to refcounted frames
      dsicinav: resolve conflicts
      smc: resolve conflicts
      zmbv: resolve conflicts
      rpza: resolve conflicts
      vble: resolve conflicts
      xxan: resolve conflicts
      targa: resolve conflicts
      vmnc: resolve conflicts
      utvideodec: resolve conflicts
      tscc: resolve conflicts
      ulti: resolve conflicts
      ffv1dec: resolve conflicts
      dnxhddec: resolve conflicts
      v210dec: resolve conflicts
      vp3: resolve conflicts
      vcr1: resolve conflicts
      v210x: resolve conflicts
      wavpack: resolve conflicts
      pngdec: fix compilation
      roqvideodec: resolve conflicts
      pictordec: resolve conflicts
      mdec: resolve conflicts
      tiertexseqv: resolve conflicts
      smacker: resolve conflicts
      vb: resolve conflicts
      vqavideo: resolve conflicts
      xl: resolve conflicts
      tmv: resolve conflicts
      vmdav: resolve conflicts
      truemotion1: resolve conflicts
      truemotion2: resolve conflicts
      lcldec: fix compilation
      libcelt_dec: fix compilation
      qdrw: fix compilation
      r210dec: fix compilation
      rl2: fix compilation
      wnv1: fix compilation
      yop: fix compilation
      tiff: resolve conflicts
      interplayvideo: fix compilation
      qpeg: resolve conflicts (FIXME/TESTME).

Hendrik Leppkes (33):
      012v: convert to refcounted frames
      8bps: fix compilation
      8svx: resolve conflicts
      4xm: resolve conflicts
      aasc: resolve conflicts
      bfi: fix compilation
      aura: fix compilation
      alsdec: resolve conflicts
      avrndec: convert to refcounted frames
      avuidec: convert to refcounted frames
      bintext: convert to refcounted frames
      cavsdec: resolve conflicts
      brender_pix: convert to refcounted frames
      cinepak: resolve conflicts
      cinepak: avoid using AVFrame struct directly in private context
      cljr: fix compilation
      cpia: convert to refcounted frames
      cscd: resolve conflicts
      iff: resolve conflicts and do proper conversion to refcounted frames
      4xm: fix reference frame handling
      cyuv: fix compilation
      dxa: fix compilation
      eacmv: fix compilation
      eamad: fix compilation
      eatgv: fix compilation
      escape124: remove unused variable.
      escape130: convert to refcounted frames
      evrcdec: convert to refcounted frames
      exr: convert to refcounted frames
      mvcdec: convert to refcounted frames
      paf: properly free the frame data on decode close
      sgirle: convert to refcounted frames
      lavfi/moviesrc: use refcounted frames

Michael Niedermayer (56):
      Merge commit '759001c534287a96dc96d1e274665feb7059145d'
      resolve conflicts in headers
      motion_est: resolve conflict
      mpeg4videodec: fix conflicts
      dpcm conflict fix
      dpx: fix conflicts
      indeo3: resolve confilcts
      kmvc: resolve conflicts
      kmvc: resolve conflicts
      h264: resolve conflicts
      utils: resolve conflicts
      rawdec: resolve conflcits
      mpegvideo: resolve conflicts
      svq1enc: resolve conflicts
      mpegvideo: dont clear data, fix assertion failure on fate vsynth1 with threads
      pthreads: resolve conflicts
      frame_thread_encoder: simple compilefix not yet tested
      snow: update to buffer refs
      crytsalhd: fix compile
      dirac: switch to new API
      sonic: update to new API
      svq1: resolve conflict, update to new API
      ffwavesynth: update to new buffer API
      g729: update to new API
      indeo5: fix compile
      j2kdec: update to new buffer API
      linopencore-amr: fix compile
      libvorbisdec: update to new API
      loco: fix compile
      paf: update to new API
      proresdec: update to new API
      vp56: update to new api / resolve conflicts
      xface: convert to refcounted frames
      xan: fix compile&fate
      v408: update to ref counted buffers
      v308: update to ref counted buffers
      yuv4dec: update to ref counted buffers
      y41p: update to ref counted frames
      xbm: update to refcounted frames
      targa_y216: update to refcounted buffers
      qpeg: fix fate/crash
      cdxl: fix fate
      tscc: fix reget buffer useage
      targa_y216dec: fix style
      msmpeg4: fix fate
      h264: ref_picture() copy fields that have been lost too
      update_frame_pool: use channel field
      h264: Put code that prevents deadlocks back
      mpegvideo: dont allow last == current
      wmalossless: fix buffer ref messup
      ff_alloc_picture: free tables in case of dimension mismatches
      h264: fix null pointer dereference and assertion failure
      frame_thread_encoder: update to bufrefs
      ec: fix used arrays
      snowdec: fix off by 1 error in dimensions check
      h264: disallow single unpaired fields as references of frames

Paul B Mahol (2):
      lavc/vima: convert to refcounted frames
      sanm: convert to refcounted frames

Conflicts:
libavcodec/4xm.c
libavcodec/8bps.c
libavcodec/8svx.c
libavcodec/aasc.c
libavcodec/alsdec.c
libavcodec/anm.c
libavcodec/ansi.c
libavcodec/avs.c
libavcodec/bethsoftvideo.c
libavcodec/bfi.c
libavcodec/c93.c
libavcodec/cavsdec.c
libavcodec/cdgraphics.c
libavcodec/cinepak.c
libavcodec/cljr.c
libavcodec/cscd.c
libavcodec/dnxhddec.c
libavcodec/dpcm.c
libavcodec/dpx.c
libavcodec/dsicinav.c
libavcodec/dvdec.c
libavcodec/dxa.c
libavcodec/eacmv.c
libavcodec/eamad.c
libavcodec/eatgq.c
libavcodec/eatgv.c
libavcodec/eatqi.c
libavcodec/error_resilience.c
libavcodec/escape124.c
libavcodec/ffv1.h
libavcodec/ffv1dec.c
libavcodec/flicvideo.c
libavcodec/fraps.c
libavcodec/frwu.c
libavcodec/g723_1.c
libavcodec/gifdec.c
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_direct.c
libavcodec/h264_loopfilter.c
libavcodec/h264_refs.c
libavcodec/huffyuvdec.c
libavcodec/idcinvideo.c
libavcodec/iff.c
libavcodec/indeo2.c
libavcodec/indeo3.c
libavcodec/internal.h
libavcodec/interplayvideo.c
libavcodec/ivi_common.c
libavcodec/jvdec.c
libavcodec/kgv1dec.c
libavcodec/kmvc.c
libavcodec/lagarith.c
libavcodec/libopenjpegdec.c
libavcodec/mdec.c
libavcodec/mimic.c
libavcodec/mjpegbdec.c
libavcodec/mjpegdec.c
libavcodec/mmvideo.c
libavcodec/motion_est.c
libavcodec/motionpixels.c
libavcodec/mpc7.c
libavcodec/mpeg12.c
libavcodec/mpeg4videodec.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/msrle.c
libavcodec/msvideo1.c
libavcodec/nuv.c
libavcodec/options_table.h
libavcodec/pcx.c
libavcodec/pictordec.c
libavcodec/pngdec.c
libavcodec/pnmdec.c
libavcodec/pthread.c
libavcodec/qpeg.c
libavcodec/qtrle.c
libavcodec/r210dec.c
libavcodec/rawdec.c
libavcodec/roqvideodec.c
libavcodec/rpza.c
libavcodec/smacker.c
libavcodec/smc.c
libavcodec/svq1dec.c
libavcodec/svq1enc.c
libavcodec/targa.c
libavcodec/tiertexseqv.c
libavcodec/tiff.c
libavcodec/tmv.c
libavcodec/truemotion1.c
libavcodec/truemotion2.c
libavcodec/tscc.c
libavcodec/ulti.c
libavcodec/utils.c
libavcodec/utvideodec.c
libavcodec/v210dec.c
libavcodec/v210x.c
libavcodec/vb.c
libavcodec/vble.c
libavcodec/vcr1.c
libavcodec/vmdav.c
libavcodec/vmnc.c
libavcodec/vp3.c
libavcodec/vp56.c
libavcodec/vp56.h
libavcodec/vp6.c
libavcodec/vqavideo.c
libavcodec/wavpack.c
libavcodec/xl.c
libavcodec/xxan.c
libavcodec/zmbv.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
272 files changed:
1  2 
doc/multithreading.txt
libavcodec/012v.c
libavcodec/4xm.c
libavcodec/8bps.c
libavcodec/8svx.c
libavcodec/aacdec.c
libavcodec/aasc.c
libavcodec/ac3dec.c
libavcodec/adpcm.c
libavcodec/adxdec.c
libavcodec/alac.c
libavcodec/alsdec.c
libavcodec/amrnbdec.c
libavcodec/amrwbdec.c
libavcodec/anm.c
libavcodec/ansi.c
libavcodec/apedec.c
libavcodec/asvdec.c
libavcodec/atrac1.c
libavcodec/atrac3.c
libavcodec/aura.c
libavcodec/avcodec.h
libavcodec/avrndec.c
libavcodec/avs.c
libavcodec/avuidec.c
libavcodec/bethsoftvideo.c
libavcodec/bfi.c
libavcodec/bink.c
libavcodec/binkaudio.c
libavcodec/bintext.c
libavcodec/bmp.c
libavcodec/bmv.c
libavcodec/brender_pix.c
libavcodec/c93.c
libavcodec/cavs.c
libavcodec/cavsdec.c
libavcodec/cdgraphics.c
libavcodec/cdxl.c
libavcodec/cinepak.c
libavcodec/cljr.c
libavcodec/cllc.c
libavcodec/cngdec.c
libavcodec/cook.c
libavcodec/cpia.c
libavcodec/crystalhd.c
libavcodec/cscd.c
libavcodec/cyuv.c
libavcodec/dcadec.c
libavcodec/dfa.c
libavcodec/diracdec.c
libavcodec/dnxhddec.c
libavcodec/dpcm.c
libavcodec/dpx.c
libavcodec/dsicinav.c
libavcodec/dvdec.c
libavcodec/dxa.c
libavcodec/dxva2_h264.c
libavcodec/eacmv.c
libavcodec/eamad.c
libavcodec/eatgq.c
libavcodec/eatgv.c
libavcodec/eatqi.c
libavcodec/error_resilience.c
libavcodec/escape124.c
libavcodec/escape130.c
libavcodec/evrcdec.c
libavcodec/exr.c
libavcodec/ffv1.c
libavcodec/ffv1.h
libavcodec/ffv1dec.c
libavcodec/ffwavesynth.c
libavcodec/flacdec.c
libavcodec/flashsv.c
libavcodec/flicvideo.c
libavcodec/frame_thread_encoder.c
libavcodec/fraps.c
libavcodec/frwu.c
libavcodec/g722dec.c
libavcodec/g723_1.c
libavcodec/g726.c
libavcodec/g729dec.c
libavcodec/gifdec.c
libavcodec/gsmdec.c
libavcodec/h261dec.c
libavcodec/h263.c
libavcodec/h263dec.c
libavcodec/h264.c
libavcodec/h264.h
libavcodec/h264_cabac.c
libavcodec/h264_cavlc.c
libavcodec/h264_direct.c
libavcodec/h264_loopfilter.c
libavcodec/h264_mb_template.c
libavcodec/h264_mc_template.c
libavcodec/h264_mvpred.h
libavcodec/h264_refs.c
libavcodec/huffyuvdec.c
libavcodec/idcinvideo.c
libavcodec/iff.c
libavcodec/imc.c
libavcodec/indeo2.c
libavcodec/indeo3.c
libavcodec/indeo5.c
libavcodec/internal.h
libavcodec/interplayvideo.c
libavcodec/intrax8.c
libavcodec/ituh263dec.c
libavcodec/ituh263enc.c
libavcodec/ivi_common.c
libavcodec/ivi_common.h
libavcodec/j2kdec.c
libavcodec/jvdec.c
libavcodec/kgv1dec.c
libavcodec/kmvc.c
libavcodec/lagarith.c
libavcodec/lcldec.c
libavcodec/libcelt_dec.c
libavcodec/libgsm.c
libavcodec/libilbc.c
libavcodec/libopencore-amr.c
libavcodec/libopenjpegdec.c
libavcodec/libopusdec.c
libavcodec/libschroedingerdec.c
libavcodec/libspeexdec.c
libavcodec/libvorbisdec.c
libavcodec/libvpxdec.c
libavcodec/ljpegenc.c
libavcodec/loco.c
libavcodec/mace.c
libavcodec/mdec.c
libavcodec/mimic.c
libavcodec/mjpegbdec.c
libavcodec/mjpegdec.c
libavcodec/mlpdec.c
libavcodec/mmvideo.c
libavcodec/motion_est.c
libavcodec/motionpixels.c
libavcodec/mpc7.c
libavcodec/mpc8.c
libavcodec/mpeg12.c
libavcodec/mpeg4video.c
libavcodec/mpeg4videodec.c
libavcodec/mpeg4videoenc.c
libavcodec/mpegaudiodec.c
libavcodec/mpegvideo.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/mpegvideo_motion.c
libavcodec/mpegvideo_xvmc.c
libavcodec/msmpeg4.c
libavcodec/msrle.c
libavcodec/mss1.c
libavcodec/mss2.c
libavcodec/mss3.c
libavcodec/mss4.c
libavcodec/msvideo1.c
libavcodec/mvcdec.c
libavcodec/mxpegdec.c
libavcodec/nellymoserdec.c
libavcodec/nuv.c
libavcodec/options.c
libavcodec/options_table.h
libavcodec/paf.c
libavcodec/pcm-mpeg.c
libavcodec/pcm.c
libavcodec/pcx.c
libavcodec/pictordec.c
libavcodec/pngdec.c
libavcodec/pnm.c
libavcodec/pnm.h
libavcodec/pnmdec.c
libavcodec/proresdec.h
libavcodec/proresdec2.c
libavcodec/proresdec_lgpl.c
libavcodec/pthread.c
libavcodec/ptx.c
libavcodec/qcelpdec.c
libavcodec/qdm2.c
libavcodec/qdrw.c
libavcodec/qpeg.c
libavcodec/qtrle.c
libavcodec/r210dec.c
libavcodec/ra144dec.c
libavcodec/ra288.c
libavcodec/rawdec.c
libavcodec/rl2.c
libavcodec/roqvideodec.c
libavcodec/roqvideoenc.c
libavcodec/rpza.c
libavcodec/rv10.c
libavcodec/rv30.c
libavcodec/rv34.c
libavcodec/rv40.c
libavcodec/s302m.c
libavcodec/sanm.c
libavcodec/sgidec.c
libavcodec/sgirledec.c
libavcodec/shorten.c
libavcodec/sipr.c
libavcodec/smacker.c
libavcodec/smc.c
libavcodec/snow.c
libavcodec/snowdec.c
libavcodec/snowenc.c
libavcodec/sonic.c
libavcodec/sunrast.c
libavcodec/svq1dec.c
libavcodec/svq1enc.c
libavcodec/svq3.c
libavcodec/takdec.c
libavcodec/targa.c
libavcodec/targa_y216dec.c
libavcodec/thread.h
libavcodec/tiertexseqv.c
libavcodec/tiff.c
libavcodec/tmv.c
libavcodec/truemotion1.c
libavcodec/truemotion2.c
libavcodec/truespeech.c
libavcodec/tscc.c
libavcodec/tscc2.c
libavcodec/tta.c
libavcodec/twinvq.c
libavcodec/txd.c
libavcodec/ulti.c
libavcodec/utils.c
libavcodec/utvideo.h
libavcodec/utvideodec.c
libavcodec/v210dec.c
libavcodec/v210x.c
libavcodec/v308dec.c
libavcodec/v408dec.c
libavcodec/v410dec.c
libavcodec/vaapi_h264.c
libavcodec/vb.c
libavcodec/vble.c
libavcodec/vc1dec.c
libavcodec/vcr1.c
libavcodec/vdpau.c
libavcodec/vdpau_h264.c
libavcodec/version.h
libavcodec/vima.c
libavcodec/vmdav.c
libavcodec/vmnc.c
libavcodec/vorbisdec.c
libavcodec/vp3.c
libavcodec/vp5.c
libavcodec/vp56.c
libavcodec/vp56.h
libavcodec/vp56data.h
libavcodec/vp6.c
libavcodec/vp8.c
libavcodec/vp8.h
libavcodec/vqavideo.c
libavcodec/wavpack.c
libavcodec/wmadec.c
libavcodec/wmalosslessdec.c
libavcodec/wmaprodec.c
libavcodec/wmavoice.c
libavcodec/wmv2dec.c
libavcodec/wnv1.c
libavcodec/ws-snd1.c
libavcodec/xan.c
libavcodec/xbmdec.c
libavcodec/xfacedec.c
libavcodec/xl.c
libavcodec/xwddec.c
libavcodec/xxan.c
libavcodec/y41pdec.c
libavcodec/yop.c
libavcodec/yuv4dec.c
libavcodec/zmbv.c

Simple merge
index 6f4533b,0000000..51c0d0c
mode 100644,000000..100644
--- /dev/null
@@@ -1,172 -1,0 +1,153 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame)
-         return AVERROR(ENOMEM);
 +/*
 + * 012v decoder
 + *
 + * Copyright (C) 2012 Carl Eugen Hoyos
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "libavutil/intreadwrite.h"
 +
 +static av_cold int zero12v_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt             = PIX_FMT_YUV422P16;
 +    avctx->bits_per_raw_sample = 10;
 +
-     avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
-     avctx->coded_frame->key_frame = 1;
 +    if (avctx->codec_tag == MKTAG('a', '1', '2', 'v'))
 +        av_log_ask_for_sample(avctx, "Samples with actual transparency needed\n");
 +
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
 +                                int *got_frame, AVPacket *avpkt)
 +{
 +    int line = 0, ret;
 +    const int width = avctx->width;
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    uint16_t *y, *u, *v;
 +    const uint8_t *line_end, *src = avpkt->data;
 +    int stride = avctx->width * 8 / 3;
 +
-     pic->reference = 0;
-     if ((ret = ff_get_buffer(avctx, pic)) < 0)
 +    if (width == 1) {
 +        av_log(avctx, AV_LOG_ERROR, "Width 1 not supported.\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +    if (avpkt->size < avctx->height * stride) {
 +        av_log(avctx, AV_LOG_ERROR, "Packet too small: %d instead of %d\n",
 +               avpkt->size, avctx->height * stride);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
-     *(AVFrame*)data= *avctx->coded_frame;
++    if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
 +        return ret;
 +
++    pic->pict_type = AV_PICTURE_TYPE_I;
++    pic->key_frame = 1;
++
 +    y = (uint16_t *)pic->data[0];
 +    u = (uint16_t *)pic->data[1];
 +    v = (uint16_t *)pic->data[2];
 +    line_end = avpkt->data + stride;
 +
 +    while (line++ < avctx->height) {
 +        while (1) {
 +            uint32_t t = AV_RL32(src);
 +            src += 4;
 +            *u++ = t <<  6 & 0xFFC0;
 +            *y++ = t >>  4 & 0xFFC0;
 +            *v++ = t >> 14 & 0xFFC0;
 +
 +            if (src >= line_end - 1) {
 +                *y = 0x80;
 +                src++;
 +                line_end += stride;
 +                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
 +                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
 +                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
 +                break;
 +            }
 +
 +            t = AV_RL32(src);
 +            src += 4;
 +            *y++ = t <<  6 & 0xFFC0;
 +            *u++ = t >>  4 & 0xFFC0;
 +            *y++ = t >> 14 & 0xFFC0;
 +            if (src >= line_end - 2) {
 +                if (!(width & 1)) {
 +                    *y = 0x80;
 +                    src += 2;
 +                }
 +                line_end += stride;
 +                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
 +                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
 +                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
 +                break;
 +            }
 +
 +            t = AV_RL32(src);
 +            src += 4;
 +            *v++ = t <<  6 & 0xFFC0;
 +            *y++ = t >>  4 & 0xFFC0;
 +            *u++ = t >> 14 & 0xFFC0;
 +
 +            if (src >= line_end - 1) {
 +                *y = 0x80;
 +                src++;
 +                line_end += stride;
 +                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
 +                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
 +                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
 +                break;
 +            }
 +
 +            t = AV_RL32(src);
 +            src += 4;
 +            *y++ = t <<  6 & 0xFFC0;
 +            *v++ = t >>  4 & 0xFFC0;
 +            *y++ = t >> 14 & 0xFFC0;
 +
 +            if (src >= line_end - 2) {
 +                if (width & 1) {
 +                    *y = 0x80;
 +                    src += 2;
 +                }
 +                line_end += stride;
 +                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
 +                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
 +                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
 +                break;
 +            }
 +        }
 +    }
 +
 +    *got_frame = 1;
- static av_cold int zero12v_decode_close(AVCodecContext *avctx)
- {
-     AVFrame *pic = avctx->coded_frame;
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
-     av_freep(&avctx->coded_frame);
-     return 0;
- }
 +
 +    return avpkt->size;
 +}
 +
-     .close          = zero12v_decode_close,
 +AVCodec ff_zero12v_decoder = {
 +    .name           = "012v",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_012V,
 +    .init           = zero12v_decode_init,
 +    .decode         = zero12v_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
 +};
@@@ -688,9 -655,8 +690,9 @@@ static int decode_i2_frame(FourXContex
      const int width  = f->avctx->width;
      const int height = f->avctx->height;
      const int mbs    = (FFALIGN(width, 16) >> 4) * (FFALIGN(height, 16) >> 4);
-     uint16_t *dst    = (uint16_t*)f->current_picture->data[0];
-     const int stride =            f->current_picture->linesize[0]>>1;
+     uint16_t *dst    = (uint16_t*)frame->data[0];
+     const int stride =            frame->linesize[0]>>1;
 +    const uint8_t *buf_end = buf + length;
      GetByteContext g3;
  
      if (length < mbs * 8) {
@@@ -802,11 -766,8 +804,10 @@@ static int decode_frame(AVCodecContext 
      int buf_size          = avpkt->size;
      FourXContext *const f = avctx->priv_data;
      AVFrame *picture      = data;
-     AVFrame *p;
      int i, frame_4cc, frame_size, ret;
  
 +    if (buf_size < 12)
 +        return AVERROR_INVALIDDATA;
      frame_4cc = AV_RL32(buf);
      if (buf_size != AV_RL32(buf + 4) + 8 || buf_size < 20)
          av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n",
          frame_size = buf_size - 12;
      }
  
-     p                  = f->current_picture;
-     avctx->coded_frame = p;
 +    FFSWAP(AVFrame*, f->current_picture, f->last_picture);
 +
      // alternatively we would have to use our own buffer management
      avctx->flags |= CODEC_FLAG_EMU_EDGE;
  
-     p->reference= 3;
-     if ((ret = avctx->reget_buffer(avctx, p)) < 0) {
 -    if ((ret = ff_get_buffer(avctx, picture, AV_GET_BUFFER_FLAG_REF)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
++    if ((ret = ff_reget_buffer(avctx, f->current_picture)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
  
      if (frame_4cc == AV_RL32("ifr2")) {
-         p->pict_type= AV_PICTURE_TYPE_I;
-         if ((ret = decode_i2_frame(f, buf - 4, frame_size + 4)) < 0) {
 -        picture->pict_type = AV_PICTURE_TYPE_I;
 -        if ((ret = decode_i2_frame(f, picture, buf - 4, frame_size + 4)) < 0)
++        f->current_picture->pict_type = AV_PICTURE_TYPE_I;
++        if ((ret = decode_i2_frame(f, f->current_picture, buf - 4, frame_size + 4)) < 0) {
 +            av_log(f->avctx, AV_LOG_ERROR, "decode i2 frame failed\n");
              return ret;
 +        }
      } else if (frame_4cc == AV_RL32("ifrm")) {
-         p->pict_type= AV_PICTURE_TYPE_I;
-         if ((ret = decode_i_frame(f, buf, frame_size)) < 0) {
 -        picture->pict_type = AV_PICTURE_TYPE_I;
 -        if ((ret = decode_i_frame(f, picture, buf, frame_size)) < 0)
++        f->current_picture->pict_type = AV_PICTURE_TYPE_I;
++        if ((ret = decode_i_frame(f, f->current_picture, buf, frame_size)) < 0) {
 +            av_log(f->avctx, AV_LOG_ERROR, "decode i frame failed\n");
              return ret;
 +        }
      } else if (frame_4cc == AV_RL32("pfrm") || frame_4cc == AV_RL32("pfr2")) {
          if (!f->last_picture->data[0]) {
-             f->last_picture->reference = 3;
-             if ((ret = ff_get_buffer(avctx, f->last_picture)) < 0) {
+             if ((ret = ff_get_buffer(avctx, f->last_picture,
+                                      AV_GET_BUFFER_FLAG_REF)) < 0) {
                  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                  return ret;
              }
 -            memset(f->last_picture->data[0], 0, avctx->height * FFABS(f->last_picture->linesize[0]));
 +            for (i=0; i<avctx->height; i++)
 +                memset(f->last_picture->data[0] + i*f->last_picture->linesize[0], 0, 2*avctx->width);
          }
  
-         p->pict_type = AV_PICTURE_TYPE_P;
-         if ((ret = decode_p_frame(f, buf, frame_size)) < 0) {
 -        picture->pict_type = AV_PICTURE_TYPE_P;
 -        if ((ret = decode_p_frame(f, picture, buf, frame_size)) < 0)
++        f->current_picture->pict_type = AV_PICTURE_TYPE_P;
++        if ((ret = decode_p_frame(f, f->current_picture, buf, frame_size)) < 0) {
 +            av_log(f->avctx, AV_LOG_ERROR, "decode p frame failed\n");
              return ret;
 +        }
      } else if (frame_4cc == AV_RL32("snd_")) {
          av_log(avctx, AV_LOG_ERROR, "ignoring snd_ chunk length:%d\n",
                 buf_size);
                 buf_size);
      }
  
-     p->key_frame = p->pict_type == AV_PICTURE_TYPE_I;
 -    picture->key_frame = picture->pict_type == AV_PICTURE_TYPE_I;
++    f->current_picture->key_frame = f->current_picture->pict_type == AV_PICTURE_TYPE_I;
  
-     *picture   = *p;
 -    av_frame_unref(f->last_picture);
 -    if ((ret = av_frame_ref(f->last_picture, picture)) < 0)
++    if ((ret = av_frame_ref(picture, f->current_picture)) < 0)
+         return ret;
      *got_frame = 1;
  
      emms_c();
@@@ -961,13 -894,9 +959,10 @@@ static av_cold int decode_init(AVCodecC
      else
          avctx->pix_fmt = AV_PIX_FMT_BGR555;
  
-     f->current_picture = avcodec_alloc_frame();
-     f->last_picture    = avcodec_alloc_frame();
-     if (!f->current_picture || !f->last_picture) {
-         avcodec_free_frame(&f->current_picture);
-         avcodec_free_frame(&f->last_picture);
 -    f->last_picture = av_frame_alloc();
 -    if (!f->last_picture)
++    f->current_picture = av_frame_alloc();
++    f->last_picture    = av_frame_alloc();
++    if (!f->current_picture  || !f->last_picture)
          return AVERROR(ENOMEM);
-     }
  
      return 0;
  }
@@@ -985,12 -914,7 +980,8 @@@ static av_cold int decode_end(AVCodecCo
          f->cfrm[i].allocated_size = 0;
      }
      ff_free_vlc(&f->pre_vlc);
-     if (f->current_picture->data[0])
-         avctx->release_buffer(avctx, f->current_picture);
-     if (f->last_picture->data[0])
-         avctx->release_buffer(avctx, f->last_picture);
-     avcodec_free_frame(&f->current_picture);
-     avcodec_free_frame(&f->last_picture);
++    av_frame_free(&f->current_picture);
+     av_frame_free(&f->last_picture);
  
      return 0;
  }
@@@ -89,10 -91,8 +84,10 @@@ static int decode_frame(AVCodecContext 
  
          /* Decode a plane */
          for (row = 0; row < height; row++) {
-             pixptr = c->pic.data[0] + row * c->pic.linesize[0] + planemap[p];
-             pixptr_end = pixptr + c->pic.linesize[0];
+             pixptr = frame->data[0] + row * frame->linesize[0] + planemap[p];
+             pixptr_end = pixptr + frame->linesize[0];
 +            if(lp - encoded + row*2 + 1 >= buf_size)
 +                return -1;
              dlen = av_be2ne16(*(const unsigned short *)(lp + row * 2));
              /* Decode a row of this plane */
              while (dlen > 0) {
@@@ -135,8 -136,8 +135,8 @@@ static int eightsvx_decode_frame(AVCode
      }
  
      /* get output buffer */
 -    frame->nb_samples = buf_size * (is_compr + 1);
 +    frame->nb_samples = buf_size * 2;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
Simple merge
  typedef struct AascContext {
      AVCodecContext *avctx;
      GetByteContext gb;
-     AVFrame frame;
+     AVFrame *frame;
 +
 +    uint32_t palette[AVPALETTE_COUNT];
 +    int palette_size;
  } AascContext;
  
  static av_cold int aasc_decode_init(AVCodecContext *avctx)
  {
      AascContext *s = avctx->priv_data;
 +    uint8_t *ptr;
 +    int i;
  
      s->avctx = avctx;
 -
 -    avctx->pix_fmt = AV_PIX_FMT_BGR24;
 +    switch (avctx->bits_per_coded_sample) {
 +    case 8:
 +        avctx->pix_fmt = AV_PIX_FMT_PAL8;
 +
 +        ptr = avctx->extradata;
 +        s->palette_size = FFMIN(avctx->extradata_size, AVPALETTE_SIZE);
 +        for (i = 0; i < s->palette_size / 4; i++) {
 +            s->palette[i] = 0xFFU << 24 | AV_RL32(ptr);
 +            ptr += 4;
 +        }
 +        break;
 +    case 16:
 +        avctx->pix_fmt = AV_PIX_FMT_RGB555LE;
 +        break;
 +    case 24:
 +        avctx->pix_fmt = AV_PIX_FMT_BGR24;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", avctx->bits_per_coded_sample);
 +        return -1;
 +    }
-     avcodec_get_frame_defaults(&s->frame);
+     s->frame = av_frame_alloc();
+     if (!s->frame)
+         return AVERROR(ENOMEM);
  
      return 0;
  }
@@@ -80,16 -60,9 +84,14 @@@ static int aasc_decode_frame(AVCodecCon
      const uint8_t *buf = avpkt->data;
      int buf_size       = avpkt->size;
      AascContext *s     = avctx->priv_data;
 -    int compr, i, stride, ret;
 +    int compr, i, stride, psize, ret;
 +
 +    if (buf_size < 4) {
 +        av_log(avctx, AV_LOG_ERROR, "frame too short\n");
 +        return AVERROR_INVALIDDATA;
 +    }
  
-     s->frame.reference = 3;
-     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     if ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
+     if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
      compr     = AV_RL32(buf);
      buf      += 4;
      buf_size -= 4;
 +    psize = avctx->bits_per_coded_sample / 8;
 +    switch (avctx->codec_tag) {
 +    case MKTAG('A', 'A', 'S', '4'):
 +        bytestream2_init(&s->gb, buf - 4, buf_size + 4);
 +        ff_msrle_decode(avctx, (AVPicture*)&s->frame, 8, &s->gb);
 +        break;
 +    case MKTAG('A', 'A', 'S', 'C'):
      switch (compr) {
      case 0:
 -        stride = (avctx->width * 3 + 3) & ~3;
 +        stride = (avctx->width * psize + psize) & ~psize;
          for (i = avctx->height - 1; i >= 0; i--) {
 -            memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * 3);
 +            if (avctx->width * psize > buf_size) {
 +                av_log(avctx, AV_LOG_ERROR, "Next line is beyond buffer bounds\n");
 +                break;
 +            }
-             memcpy(s->frame.data[0] + i*s->frame.linesize[0], buf, avctx->width * psize);
++            memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * psize);
              buf += stride;
 +            buf_size -= stride;
          }
          break;
      case 1:
          av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr);
          return AVERROR_INVALIDDATA;
      }
-         memcpy(s->frame.data[1], s->palette, s->palette_size);
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "Unknown FourCC: %X\n", avctx->codec_tag);
 +        return -1;
 +    }
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_PAL8)
++        memcpy(s->frame->data[1], s->palette, s->palette_size);
  
      *got_frame = 1;
-     *(AVFrame*)data = s->frame;
+     if ((ret = av_frame_ref(data, s->frame)) < 0)
+         return ret;
  
      /* report that the buffer was completely consumed */
      return buf_size;
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -1480,8 -1462,8 +1480,8 @@@ static int decode_frame(AVCodecContext 
  
      /* get output buffer */
      frame->nb_samples = ctx->cur_frame_length;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed.\n");
          return ret;
      }
  
Simple merge
Simple merge
Simple merge
@@@ -25,8 -25,8 +25,9 @@@
   */
  
  #include "libavutil/common.h"
+ #include "libavutil/frame.h"
  #include "libavutil/lfg.h"
 +#include "libavutil/xga_font_data.h"
  #include "avcodec.h"
  #include "cga_data.h"
  #include "internal.h"
@@@ -79,8 -78,12 +80,12 @@@ static av_cold int decode_init(AVCodecC
      AnsiContext *s = avctx->priv_data;
      avctx->pix_fmt = AV_PIX_FMT_PAL8;
  
+     s->frame = av_frame_alloc();
+     if (!s->frame)
+         return AVERROR(ENOMEM);
      /* defaults */
 -    s->font        = ff_vga16_font;
 +    s->font        = avpriv_vga16_font;
      s->font_height = 16;
      s->fg          = DEFAULT_FG_COLOR;
      s->bg          = DEFAULT_BG_COLOR;
@@@ -248,9 -232,9 +251,9 @@@ static int execute_code(AVCodecContext 
                  av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                  return ret;
              }
-             s->frame.pict_type           = AV_PICTURE_TYPE_I;
-             s->frame.palette_has_changed = 1;
-             set_palette((uint32_t *)s->frame.data[1]);
+             s->frame->pict_type           = AV_PICTURE_TYPE_I;
+             s->frame->palette_has_changed = 1;
 -            memcpy(s->frame->data[1], ff_cga_palette, 16 * 4);
++            set_palette((uint32_t *)s->frame->data[1]);
              erase_screen(avctx);
          } else if (c == 'l') {
              erase_screen(avctx);
@@@ -354,18 -330,13 +357,18 @@@ static int decode_frame(AVCodecContext 
          return ret;
      }
      if (!avctx->frame_number) {
 -        memset(s->frame->data[0], 0, avctx->height * FFABS(s->frame->linesize[0]));
 +        for (i=0; i<avctx->height; i++)
-             memset(s->frame.data[0]+ i*s->frame.linesize[0], 0, avctx->width);
-         memset(s->frame.data[1], 0, AVPALETTE_SIZE);
++            memset(s->frame->data[0]+ i*s->frame->linesize[0], 0, avctx->width);
+         memset(s->frame->data[1], 0, AVPALETTE_SIZE);
      }
  
-     s->frame.pict_type           = AV_PICTURE_TYPE_I;
-     s->frame.palette_has_changed = 1;
-     set_palette((uint32_t *)s->frame.data[1]);
+     s->frame->pict_type           = AV_PICTURE_TYPE_I;
+     s->frame->palette_has_changed = 1;
 -    memcpy(s->frame->data[1], ff_cga_palette, 16 * 4);
++    set_palette((uint32_t *)s->frame->data[1]);
 +    if (!s->first_frame) {
 +        erase_screen(avctx);
 +        s->first_frame = 1;
 +    }
  
      while(buf < buf_end) {
          switch(s->state) {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0fc431d,0000000..882ee50
mode 100644,000000..100644
--- /dev/null
@@@ -1,143 -1,0 +1,134 @@@
-     AVFrame frame;
 +/*
 + * AVRn decoder
 + * Copyright (c) 2012 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 "avcodec.h"
 +#include "internal.h"
 +#include "mjpeg.h"
 +#include "mjpegdec.h"
 +#include "libavutil/imgutils.h"
 +
 +typedef struct {
 +    MJpegDecodeContext mjpeg_ctx;
-     avcodec_get_frame_defaults(&a->frame);
 +    int is_mjpeg;
 +    int interlace; //FIXME use frame.interlaced_frame
 +    int tff;
 +} AVRnContext;
 +
 +static av_cold int init(AVCodecContext *avctx)
 +{
 +    AVRnContext *a = avctx->priv_data;
 +    int ret;
 +
 +    // Support "Resolution 1:1" for Avid AVI Codec
 +    a->is_mjpeg = avctx->extradata_size < 31 || memcmp(&avctx->extradata[28], "1:1", 3);
 +
 +    if(!a->is_mjpeg && avctx->lowres) {
 +        av_log(avctx, AV_LOG_ERROR, "lowres is not possible with rawvideo\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if(a->is_mjpeg)
 +        return ff_mjpeg_decode_init(avctx);
 +
 +    if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
 +        return ret;
 +
-     AVFrame *p = &a->frame;
-     if(p->data[0])
-         avctx->release_buffer(avctx, p);
 +    avctx->pix_fmt = AV_PIX_FMT_UYVY422;
 +
 +    if(avctx->extradata_size >= 9 && avctx->extradata[4]+28 < avctx->extradata_size) {
 +        int ndx = avctx->extradata[4] + 4;
 +        a->interlace = !memcmp(avctx->extradata + ndx, "1:1(", 4);
 +        if(a->interlace) {
 +            a->tff = avctx->extradata[ndx + 24] == 1;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold int end(AVCodecContext *avctx)
 +{
 +    AVRnContext *a = avctx->priv_data;
-     AVFrame *p = &a->frame;
 +
 +    if(a->is_mjpeg)
 +        ff_mjpeg_decode_end(avctx);
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data,
 +                        int *got_frame, AVPacket *avpkt)
 +{
 +    AVRnContext *a = avctx->priv_data;
-     if(p->data[0])
-         avctx->release_buffer(avctx, p);
++    AVFrame *p = data;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size       = avpkt->size;
 +    int y, ret, true_height;
 +
 +    if(a->is_mjpeg)
 +        return ff_mjpeg_decode_frame(avctx, data, got_frame, avpkt);
 +
 +    true_height    = buf_size / (2*avctx->width);
-     if((ret = ff_get_buffer(avctx, p)) < 0){
 +
 +    if(buf_size < 2*avctx->width * avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR, "packet too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
-     *(AVFrame*)data = a->frame;
++    if((ret = ff_get_buffer(avctx, p, 0)) < 0){
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +    p->pict_type= AV_PICTURE_TYPE_I;
 +    p->key_frame= 1;
 +
 +    if(a->interlace) {
 +        buf += (true_height - avctx->height)*avctx->width;
 +        for(y = 0; y < avctx->height-1; y+=2) {
 +            memcpy(p->data[0] + (y+ a->tff)*p->linesize[0], buf                             , 2*avctx->width);
 +            memcpy(p->data[0] + (y+!a->tff)*p->linesize[0], buf + avctx->width*true_height+4, 2*avctx->width);
 +            buf += 2*avctx->width;
 +        }
 +    } else {
 +        buf += (true_height - avctx->height)*avctx->width*2;
 +        for(y = 0; y < avctx->height; y++) {
 +            memcpy(p->data[0] + y*p->linesize[0], buf, 2*avctx->width);
 +            buf += 2*avctx->width;
 +        }
 +    }
 +
 +    *got_frame      = 1;
 +    return buf_size;
 +}
 +
 +AVCodec ff_avrn_decoder = {
 +    .name           = "avrn",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_AVRN,
 +    .priv_data_size = sizeof(AVRnContext),
 +    .init           = init,
 +    .close          = end,
 +    .decode         = decode_frame,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Avid AVI Codec"),
 +    .capabilities   = CODEC_CAP_DR1,
 +    .max_lowres     = 3,
 +};
 +
@@@ -57,9 -58,9 +58,9 @@@ avs_decode_frame(AVCodecContext * avctx
      int i, j, x, y, stride, ret, vect_w = 3, vect_h = 3;
      AvsVideoSubType sub_type;
      AvsBlockType type;
 -    GetBitContext change_map;
 +    GetBitContext change_map = {0}; //init to silence warning
  
-     if ((ret = avctx->reget_buffer(avctx, p)) < 0) {
+     if ((ret = ff_reget_buffer(avctx, p)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
index 22af719,0000000..689191d
mode 100644,000000..100644
--- /dev/null
@@@ -1,156 -1,0 +1,131 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame) {
-         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-         return AVERROR(ENOMEM);
-     }
 +/*
 + * AVID Meridien decoder
 + *
 + * Copyright (c) 2012 Carl Eugen Hoyos
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "libavutil/intreadwrite.h"
 +
 +static av_cold int avui_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int avui_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame, AVPacket *avpkt)
 +{
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    const uint8_t *src = avpkt->data, *extradata = avctx->extradata;
 +    const uint8_t *srca;
 +    uint8_t *y, *u, *v, *a;
 +    int transparent, interlaced = 1, skip, opaque_length, i, j, k;
 +    uint32_t extradata_size = avctx->extradata_size;
 +
-     pic->reference = 0;
-     if (ff_get_buffer(avctx, pic) < 0) {
 +    while (extradata_size >= 24) {
 +        uint32_t atom_size = AV_RB32(extradata);
 +        if (!memcmp(&extradata[4], "APRGAPRG0001", 12)) {
 +            interlaced = extradata[19] != 1;
 +            break;
 +        }
 +        if (atom_size && atom_size <= extradata_size) {
 +            extradata      += atom_size;
 +            extradata_size -= atom_size;
 +        } else {
 +            break;
 +        }
 +    }
 +    if (avctx->height == 486) {
 +        skip = 10;
 +    } else {
 +        skip = 16;
 +    }
 +    opaque_length = 2 * avctx->width * (avctx->height + skip) + 4 * interlaced;
 +    if (avpkt->size < opaque_length) {
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +    transparent = avctx->bits_per_coded_sample == 32 &&
 +                  avpkt->size >= opaque_length * 2 + 4;
 +    srca = src + opaque_length + 5;
 +
-     *(AVFrame *)data = *pic;
++    if (ff_get_buffer(avctx, pic, 0) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    pic->key_frame = 1;
 +    pic->pict_type = AV_PICTURE_TYPE_I;
 +
 +    if (!interlaced) {
 +        src  += avctx->width * skip;
 +        srca += avctx->width * skip;
 +    }
 +
 +    for (i = 0; i < interlaced + 1; i++) {
 +        src  += avctx->width * skip;
 +        srca += avctx->width * skip;
 +        if (interlaced && avctx->height == 486) {
 +            y = pic->data[0] + (1 - i) * pic->linesize[0];
 +            u = pic->data[1] + (1 - i) * pic->linesize[1];
 +            v = pic->data[2] + (1 - i) * pic->linesize[2];
 +            a = pic->data[3] + (1 - i) * pic->linesize[3];
 +        } else {
 +            y = pic->data[0] + i * pic->linesize[0];
 +            u = pic->data[1] + i * pic->linesize[1];
 +            v = pic->data[2] + i * pic->linesize[2];
 +            a = pic->data[3] + i * pic->linesize[3];
 +        }
 +
 +        for (j = 0; j < avctx->height >> interlaced; j++) {
 +            for (k = 0; k < avctx->width >> 1; k++) {
 +                u[    k    ] = *src++;
 +                y[2 * k    ] = *src++;
 +                a[2 * k    ] = 0xFF - (transparent ? *srca++ : 0);
 +                srca++;
 +                v[    k    ] = *src++;
 +                y[2 * k + 1] = *src++;
 +                a[2 * k + 1] = 0xFF - (transparent ? *srca++ : 0);
 +                srca++;
 +            }
 +
 +            y += (interlaced + 1) * pic->linesize[0];
 +            u += (interlaced + 1) * pic->linesize[1];
 +            v += (interlaced + 1) * pic->linesize[2];
 +            a += (interlaced + 1) * pic->linesize[3];
 +        }
 +        src  += 4;
 +        srca += 4;
 +    }
 +    *got_frame       = 1;
- static av_cold int avui_decode_close(AVCodecContext *avctx)
- {
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
-     return 0;
- }
 +
 +    return avpkt->size;
 +}
 +
-     .close        = avui_decode_close,
 +AVCodec ff_avui_decoder = {
 +    .name         = "avui",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_AVUI,
 +    .init         = avui_decode_init,
 +    .decode       = avui_decode_frame,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"),
 +};
@@@ -40,10 -41,6 +41,7 @@@ typedef struct BethsoftvidContext 
  static av_cold int bethsoftvid_decode_init(AVCodecContext *avctx)
  {
      BethsoftvidContext *vid = avctx->priv_data;
-     vid->frame.reference = 3;
-     vid->frame.buffer_hints = FF_BUFFER_HINTS_VALID |
-         FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
 +    avcodec_get_frame_defaults(&vid->frame);
      avctx->pix_fmt = AV_PIX_FMT_PAL8;
      return 0;
  }
@@@ -33,9 -33,7 +33,8 @@@
  
  typedef struct BFIContext {
      AVCodecContext *avctx;
-     AVFrame frame;
      uint8_t *dst;
 +    uint32_t pal[256];
  } BFIContext;
  
  static av_cold int bfi_decode_init(AVCodecContext *avctx)
@@@ -80,22 -73,19 +74,22 @@@ static int bfi_decode_frame(AVCodecCont
              av_log(NULL, AV_LOG_ERROR, "Palette is too large.\n");
              return AVERROR_INVALIDDATA;
          }
-         pal = (uint32_t *)bfi->frame.data[1];
+         pal = (uint32_t *)frame->data[1];
          for (i = 0; i < avctx->extradata_size / 3; i++) {
              int shift = 16;
 -            *pal = 0;
 +            *pal = 0xFFU << 24;
              for (j = 0; j < 3; j++, shift -= 8)
                  *pal += ((avctx->extradata[i * 3 + j] << 2) |
                           (avctx->extradata[i * 3 + j] >> 4)) << shift;
              pal++;
          }
-         memcpy(bfi->pal, bfi->frame.data[1], sizeof(bfi->pal));
-         bfi->frame.palette_has_changed = 1;
++        memcpy(bfi->pal, frame->data[1], sizeof(bfi->pal));
+         frame->palette_has_changed = 1;
      } else {
-         bfi->frame.pict_type = AV_PICTURE_TYPE_P;
-         bfi->frame.key_frame = 0;
-         bfi->frame.palette_has_changed = 0;
-         memcpy(bfi->frame.data[1], bfi->pal, sizeof(bfi->pal));
+         frame->pict_type = AV_PICTURE_TYPE_P;
+         frame->key_frame = 0;
++        frame->palette_has_changed = 0;
++        memcpy(frame->data[1], bfi->pal, sizeof(bfi->pal));
      }
  
      bytestream2_skip(&g, 4); // Unpacked size, not required.
Simple merge
Simple merge
index 1c9bc3e,0000000..b6d7d0f
mode 100644,000000..100644
--- /dev/null
@@@ -1,257 -1,0 +1,260 @@@
-     AVFrame frame;
 +/*
 + * Binary text decoder
 + * eXtended BINary text (XBIN) decoder
 + * iCEDraw File decoder
 + * Copyright (c) 2010 Peter Ross (pross@xvid.org)
 + *
 + * 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
 + * Binary text decoder
 + * eXtended BINary text (XBIN) decoder
 + * iCEDraw File decoder
 + */
 +
 +#include "libavutil/intreadwrite.h"
 +#include "libavutil/xga_font_data.h"
 +#include "avcodec.h"
 +#include "cga_data.h"
 +#include "bintext.h"
++#include "internal.h"
 +
 +typedef struct XbinContext {
-         memmove(s->frame.data[0], s->frame.data[0] + s->font_height*s->frame.linesize[0],
-             (avctx->height - s->font_height)*s->frame.linesize[0]);
-         memset(s->frame.data[0] + (avctx->height - s->font_height)*s->frame.linesize[0],
-             DEFAULT_BG_COLOR, s->font_height * s->frame.linesize[0]);
++    AVFrame *frame;
 +    int palette[16];
 +    int flags;
 +    int font_height;
 +    const uint8_t *font;
 +    int x, y;
 +} XbinContext;
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    XbinContext *s = avctx->priv_data;
 +    uint8_t *p;
 +    int i;
 +
 +    avctx->pix_fmt = AV_PIX_FMT_PAL8;
 +    p = avctx->extradata;
 +    if (p) {
 +        s->font_height = p[0];
 +        s->flags = p[1];
 +        p += 2;
 +        if(avctx->extradata_size < 2 + (!!(s->flags & BINTEXT_PALETTE))*3*16
 +                                     + (!!(s->flags & BINTEXT_FONT))*s->font_height*256) {
 +            av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +    } else {
 +        s->font_height = 8;
 +        s->flags = 0;
 +    }
 +
 +    if ((s->flags & BINTEXT_PALETTE)) {
 +        for (i = 0; i < 16; i++) {
 +            s->palette[i] = 0xFF000000 | (AV_RB24(p) << 2) | ((AV_RB24(p) >> 4) & 0x30303);
 +            p += 3;
 +        }
 +    } else {
 +        for (i = 0; i < 16; i++)
 +            s->palette[i] = 0xFF000000 | ff_cga_palette[i];
 +    }
 +
 +    if ((s->flags & BINTEXT_FONT)) {
 +        s->font = p;
 +    } else {
 +        switch(s->font_height) {
 +        default:
 +            av_log(avctx, AV_LOG_WARNING, "font height %i not supported\n", s->font_height);
 +            s->font_height = 8;
 +        case 8:
 +            s->font = avpriv_cga_font;
 +            break;
 +        case 16:
 +            s->font = avpriv_vga16_font;
 +            break;
 +        }
 +    }
 +
++    s->frame = av_frame_alloc();
++    if (!s->frame)
++        return AVERROR(ENOMEM);
++
 +    return 0;
 +}
 +
 +#define DEFAULT_BG_COLOR 0
 +av_unused static void hscroll(AVCodecContext *avctx)
 +{
 +    XbinContext *s = avctx->priv_data;
 +    if (s->y < avctx->height - s->font_height) {
 +        s->y += s->font_height;
 +    } else {
-     ff_draw_pc_font(s->frame.data[0] + s->y * s->frame.linesize[0] + s->x,
-                     s->frame.linesize[0], s->font, s->font_height, c,
++        memmove(s->frame->data[0], s->frame->data[0] + s->font_height*s->frame->linesize[0],
++            (avctx->height - s->font_height)*s->frame->linesize[0]);
++        memset(s->frame->data[0] + (avctx->height - s->font_height)*s->frame->linesize[0],
++            DEFAULT_BG_COLOR, s->font_height * s->frame->linesize[0]);
 +    }
 +}
 +
 +#define FONT_WIDTH 8
 +
 +/**
 + * Draw character to screen
 + */
 +static void draw_char(AVCodecContext *avctx, int c, int a)
 +{
 +    XbinContext *s = avctx->priv_data;
 +    if (s->y > avctx->height - s->font_height)
 +        return;
-     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID |
-                             FF_BUFFER_HINTS_PRESERVE |
-                             FF_BUFFER_HINTS_REUSABLE;
-     if (avctx->reget_buffer(avctx, &s->frame)) {
++    ff_draw_pc_font(s->frame->data[0] + s->y * s->frame->linesize[0] + s->x,
++                    s->frame->linesize[0], s->font, s->font_height, c,
 +                    a & 0x0F, a >> 4);
 +    s->x += FONT_WIDTH;
 +    if (s->x > avctx->width - FONT_WIDTH) {
 +        s->x = 0;
 +        s->y += s->font_height;
 +    }
 +}
 +
 +static int decode_frame(AVCodecContext *avctx,
 +                            void *data, int *got_frame,
 +                            AVPacket *avpkt)
 +{
 +    XbinContext *s = avctx->priv_data;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    const uint8_t *buf_end = buf+buf_size;
++    int ret;
 +
 +    s->x = s->y = 0;
-     s->frame.pict_type           = AV_PICTURE_TYPE_I;
-     s->frame.palette_has_changed = 1;
-     memcpy(s->frame.data[1], s->palette, 16 * 4);
++    if (ff_reget_buffer(avctx, s->frame) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return -1;
 +    }
-     *(AVFrame*)data = s->frame;
++    s->frame->pict_type           = AV_PICTURE_TYPE_I;
++    s->frame->palette_has_changed = 1;
++    memcpy(s->frame->data[1], s->palette, 16 * 4);
 +
 +    if (avctx->codec_id == AV_CODEC_ID_XBIN) {
 +        while (buf + 2 < buf_end) {
 +            int i,c,a;
 +            int type  = *buf >> 6;
 +            int count = (*buf & 0x3F) + 1;
 +            buf++;
 +            switch (type) {
 +            case 0: //no compression
 +                for (i = 0; i < count && buf + 1 < buf_end; i++) {
 +                    draw_char(avctx, buf[0], buf[1]);
 +                    buf += 2;
 +                }
 +                break;
 +            case 1: //character compression
 +                c = *buf++;
 +                for (i = 0; i < count && buf < buf_end; i++)
 +                    draw_char(avctx, c, *buf++);
 +                break;
 +            case 2: //attribute compression
 +                a = *buf++;
 +                for (i = 0; i < count && buf < buf_end; i++)
 +                    draw_char(avctx, *buf++, a);
 +                break;
 +            case 3: //character/attribute compression
 +                c = *buf++;
 +                a = *buf++;
 +                for (i = 0; i < count && buf < buf_end; i++)
 +                    draw_char(avctx, c, a);
 +                break;
 +            }
 +        }
 +    } else if (avctx->codec_id == AV_CODEC_ID_IDF) {
 +        while (buf + 2 < buf_end) {
 +            if (AV_RL16(buf) == 1) {
 +               int i;
 +               if (buf + 6 > buf_end)
 +                   break;
 +               for (i = 0; i < buf[2]; i++)
 +                   draw_char(avctx, buf[4], buf[5]);
 +               buf += 6;
 +            } else {
 +               draw_char(avctx, buf[0], buf[1]);
 +               buf += 2;
 +            }
 +        }
 +    } else {
 +        while (buf + 1 < buf_end) {
 +            draw_char(avctx, buf[0], buf[1]);
 +            buf += 2;
 +        }
 +    }
 +
++    if ((ret = av_frame_ref(data, s->frame)) < 0)
++        return ret;
 +    *got_frame      = 1;
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
 +    return buf_size;
 +}
 +
 +static av_cold int decode_end(AVCodecContext *avctx)
 +{
 +    XbinContext *s = avctx->priv_data;
 +
++    av_frame_free(&s->frame);
 +
 +    return 0;
 +}
 +
 +#if CONFIG_BINTEXT_DECODER
 +AVCodec ff_bintext_decoder = {
 +    .name           = "bintext",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_BINTEXT,
 +    .priv_data_size = sizeof(XbinContext),
 +    .init           = decode_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Binary text"),
 +};
 +#endif
 +#if CONFIG_XBIN_DECODER
 +AVCodec ff_xbin_decoder = {
 +    .name           = "xbin",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_XBIN,
 +    .priv_data_size = sizeof(XbinContext),
 +    .init           = decode_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("eXtended BINary text"),
 +};
 +#endif
 +#if CONFIG_IDF_DECODER
 +AVCodec ff_idf_decoder = {
 +    .name           = "idf",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_IDF,
 +    .priv_data_size = sizeof(XbinContext),
 +    .init           = decode_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("iCEDraw text"),
 +};
 +#endif
Simple merge
Simple merge
index 6c63244,0000000..67bec05
mode 100644,000000..100644
--- /dev/null
@@@ -1,253 -1,0 +1,221 @@@
- typedef struct BRPixContext {
-     AVFrame frame;
- } BRPixContext;
 +/*
 + * BRender PIX (.pix) image decoder
 + * Copyright (c) 2012 Aleksi Nurmi
 + *
 + * 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
 + */
 +
 +/*
 + * Tested against samples from I-War / Independence War and Defiance.
 + * If the PIX file does not contain a palette, the
 + * palette_has_changed property of the AVFrame is set to 0.
 + */
 +
 +#include "libavutil/imgutils.h"
 +#include "avcodec.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +
- static av_cold int brpix_init(AVCodecContext *avctx)
- {
-     BRPixContext *s = avctx->priv_data;
-     avcodec_get_frame_defaults(&s->frame);
-     avctx->coded_frame = &s->frame;
-     return 0;
- }
 +typedef struct BRPixHeader {
 +    int format;
 +    unsigned int width, height;
 +} BRPixHeader;
 +
-     BRPixContext *s = avctx->priv_data;
-     AVFrame *frame_out = data;
 +static int brpix_decode_header(BRPixHeader *out, GetByteContext *pgb)
 +{
 +    unsigned int header_len = bytestream2_get_be32(pgb);
 +
 +    out->format = bytestream2_get_byte(pgb);
 +    bytestream2_skip(pgb, 2);
 +    out->width = bytestream2_get_be16(pgb);
 +    out->height = bytestream2_get_be16(pgb);
 +
 +    // the header is at least 11 bytes long; we read the first 7
 +    if (header_len < 11) {
 +        return 0;
 +    }
 +
 +    // skip the rest of the header
 +    bytestream2_skip(pgb, header_len-7);
 +
 +    return 1;
 +}
 +
 +static int brpix_decode_frame(AVCodecContext *avctx,
 +                              void *data, int *got_frame,
 +                              AVPacket *avpkt)
 +{
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
++    AVFrame *frame = data;
 +
 +    int ret;
 +    GetByteContext gb;
 +
 +    unsigned int bytes_pp;
 +
 +    unsigned int magic[4];
 +    unsigned int chunk_type;
 +    unsigned int data_len;
 +    BRPixHeader hdr;
 +
 +    bytestream2_init(&gb, avpkt->data, avpkt->size);
 +
 +    magic[0] = bytestream2_get_be32(&gb);
 +    magic[1] = bytestream2_get_be32(&gb);
 +    magic[2] = bytestream2_get_be32(&gb);
 +    magic[3] = bytestream2_get_be32(&gb);
 +
 +    if (magic[0] != 0x12 ||
 +        magic[1] != 0x8 ||
 +        magic[2] != 0x2 ||
 +        magic[3] != 0x2) {
 +        av_log(avctx, AV_LOG_ERROR, "Not a BRender PIX file\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    chunk_type = bytestream2_get_be32(&gb);
 +    if (chunk_type != 0x3 && chunk_type != 0x3d) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid chunk type %d\n", chunk_type);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    ret = brpix_decode_header(&hdr, &gb);
 +    if (!ret) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid header length\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +    switch (hdr.format) {
 +    case 3:
 +        avctx->pix_fmt = AV_PIX_FMT_PAL8;
 +        bytes_pp = 1;
 +        break;
 +    case 4:
 +        avctx->pix_fmt = AV_PIX_FMT_RGB555BE;
 +        bytes_pp = 2;
 +        break;
 +    case 5:
 +        avctx->pix_fmt = AV_PIX_FMT_RGB565BE;
 +        bytes_pp = 2;
 +        break;
 +    case 6:
 +        avctx->pix_fmt = AV_PIX_FMT_RGB24;
 +        bytes_pp = 3;
 +        break;
 +    case 7:
 +        avctx->pix_fmt = AV_PIX_FMT_0RGB;
 +        bytes_pp = 4;
 +        break;
 +    case 18:
 +        avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
 +        bytes_pp = 2;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "Format %d is not supported\n",
 +                                    hdr.format);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
-     if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
 +    if (av_image_check_size(hdr.width, hdr.height, 0, avctx) < 0)
 +        return AVERROR_INVALIDDATA;
 +
 +    if (hdr.width != avctx->width || hdr.height != avctx->height)
 +        avcodec_set_dimensions(avctx, hdr.width, hdr.height);
 +
-         uint32_t *pal_out = (uint32_t *)s->frame.data[1];
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +
 +    chunk_type = bytestream2_get_be32(&gb);
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_PAL8 &&
 +        (chunk_type == 0x3 || chunk_type == 0x3d)) {
 +        BRPixHeader palhdr;
-         s->frame.palette_has_changed = 1;
++        uint32_t *pal_out = (uint32_t *)frame->data[1];
 +        int i;
 +
 +        ret = brpix_decode_header(&palhdr, &gb);
 +        if (!ret) {
 +            av_log(avctx, AV_LOG_ERROR, "Invalid palette header length\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        if (palhdr.format != 7) {
 +            av_log(avctx, AV_LOG_ERROR, "Palette is not in 0RGB format\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        chunk_type = bytestream2_get_be32(&gb);
 +        data_len = bytestream2_get_be32(&gb);
 +        bytestream2_skip(&gb, 8);
 +        if (chunk_type != 0x21 || data_len != 1032 ||
 +            bytestream2_get_bytes_left(&gb) < 1032) {
 +            av_log(avctx, AV_LOG_ERROR, "Invalid palette data\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        // convert 0RGB to machine endian format (ARGB32)
 +        for (i = 0; i < 256; ++i) {
 +            bytestream2_skipu(&gb, 1);
 +            *pal_out++ = (0xFFU << 24) | bytestream2_get_be24u(&gb);
 +        }
 +        bytestream2_skip(&gb, 8);
 +
-         uint32_t *pal_out = (uint32_t *)s->frame.data[1];
++        frame->palette_has_changed = 1;
 +
 +        chunk_type = bytestream2_get_be32(&gb);
 +    } else if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-         s->frame.palette_has_changed = 1;
++        uint32_t *pal_out = (uint32_t *)frame->data[1];
 +        int i;
 +
 +        for (i = 0; i < 256; ++i) {
 +            *pal_out++ = (0xFFU << 24) | (i * 0x010101);
 +        }
-         av_image_copy_plane(s->frame.data[0], s->frame.linesize[0],
++        frame->palette_has_changed = 1;
 +    }
 +
 +    data_len = bytestream2_get_be32(&gb);
 +    bytestream2_skip(&gb, 8);
 +
 +    // read the image data to the buffer
 +    {
 +        unsigned int bytes_per_scanline = bytes_pp * hdr.width;
 +        unsigned int bytes_left = bytestream2_get_bytes_left(&gb);
 +
 +        if (chunk_type != 0x21 || data_len != bytes_left ||
 +            bytes_left / bytes_per_scanline < hdr.height)
 +        {
 +            av_log(avctx, AV_LOG_ERROR, "Invalid image data\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
-     *frame_out = s->frame;
++        av_image_copy_plane(frame->data[0], frame->linesize[0],
 +                            avpkt->data + bytestream2_tell(&gb),
 +                            bytes_per_scanline,
 +                            bytes_per_scanline, hdr.height);
 +    }
 +
- static av_cold int brpix_end(AVCodecContext *avctx)
- {
-     BRPixContext *s = avctx->priv_data;
-     if(s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
-     return 0;
- }
 +    *got_frame = 1;
 +
 +    return avpkt->size;
 +}
 +
-     .priv_data_size = sizeof(BRPixContext),
-     .init           = brpix_init,
-     .close          = brpix_end,
 +AVCodec ff_brender_pix_decoder = {
 +    .name           = "brender_pix",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_BRENDER_PIX,
 +    .decode         = brpix_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("BRender PIX image"),
 +};
Simple merge
Simple merge
@@@ -945,9 -929,10 +945,11 @@@ static inline int check_for_slice(AVSCo
  static int decode_pic(AVSContext *h)
  {
      int skip_count    = -1;
 +    int ret;
      enum cavs_mb mb_type;
  
+     av_frame_unref(h->cur.f);
      skip_bits(&h->gb, 16);//bbv_dwlay
      if (h->stc == PIC_PB_START_CODE) {
          h->cur.f->pict_type = get_bits(&h->gb, 2) + AV_PICTURE_TYPE_I;
          if (h->stream_revision > 0)
              skip_bits(&h->gb, 1); //marker_bit
      }
-     /* release last B frame */
-     if (h->cur.f->data[0])
-         h->avctx->release_buffer(h->avctx, h->cur.f);
  
-     if ((ret = ff_get_buffer(h->avctx, h->cur.f)) < 0)
 -    ff_get_buffer(h->avctx, h->cur.f, h->cur.f->pict_type == AV_PICTURE_TYPE_B ?
 -                  0 : AV_GET_BUFFER_FLAG_REF);
++    if ((ret = ff_get_buffer(h->avctx, h->cur.f,
++                             h->cur.f->pict_type == AV_PICTURE_TYPE_B ?
++                             0 : AV_GET_BUFFER_FLAG_REF)) < 0)
 +        return ret;
  
      if (!h->edge_emu_buffer) {
          int alloc_size = FFALIGN(FFABS(h->cur.f->linesize[0]) + 32, 32);
@@@ -127,9 -119,9 +119,9 @@@ static void cdg_load_palette(CDGraphics
          r = ((color >> 8) & 0x000F) * 17;
          g = ((color >> 4) & 0x000F) * 17;
          b = ((color     ) & 0x000F) * 17;
 -        palette[i + array_offset] = r << 16 | g << 8 | b;
 +        palette[i + array_offset] = 0xFFU << 24 | r << 16 | g << 8 | b;
      }
-     cc->frame.palette_has_changed = 1;
+     cc->frame->palette_has_changed = 1;
  }
  
  static int cdg_tile_block(CDGraphicsContext *cc, uint8_t *data, int b)
@@@ -281,20 -273,14 +273,20 @@@ static int cdg_decode_frame(AVCodecCont
          av_log(avctx, AV_LOG_ERROR, "buffer too small for decoder\n");
          return AVERROR(EINVAL);
      }
 +    if (buf_size > CDG_HEADER_SIZE + CDG_DATA_SIZE) {
 +        av_log(avctx, AV_LOG_ERROR, "buffer too big for decoder\n");
 +        return AVERROR(EINVAL);
 +    }
  
-     ret = avctx->reget_buffer(avctx, &cc->frame);
+     ret = ff_reget_buffer(avctx, cc->frame);
      if (ret) {
          av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
 -    if (!avctx->frame_number)
 +    if (!avctx->frame_number) {
-         memset(cc->frame.data[0], 0, cc->frame.linesize[0] * avctx->height);
-         memset(cc->frame.data[1], 0, AVPALETTE_SIZE);
+         memset(cc->frame->data[0], 0, cc->frame->linesize[0] * avctx->height);
++        memset(cc->frame->data[1], 0, AVPALETTE_SIZE);
 +    }
  
      command = bytestream_get_byte(&buf);
      inst    = bytestream_get_byte(&buf);
@@@ -35,7 -33,7 +35,6 @@@
  
  typedef struct {
      AVCodecContext *avctx;
--    AVFrame        frame;
      int            bpp;
      int            format;
      int            padded_bits;
@@@ -115,16 -112,15 +113,16 @@@ static void import_format(CDXLVideoCont
      }
  }
  
- static void cdxl_decode_rgb(CDXLVideoContext *c)
+ static void cdxl_decode_rgb(CDXLVideoContext *c, AVFrame *frame)
  {
-     uint32_t *new_palette = (uint32_t *)c->frame.data[1];
+     uint32_t *new_palette = (uint32_t *)frame->data[1];
  
-     memset(c->frame.data[1], 0, AVPALETTE_SIZE);
++    memset(frame->data[1], 0, AVPALETTE_SIZE);
      import_palette(c, new_palette);
-     import_format(c, c->frame.linesize[0], c->frame.data[0]);
+     import_format(c, frame->linesize[0], frame->data[0]);
  }
  
- static void cdxl_decode_ham6(CDXLVideoContext *c)
+ static void cdxl_decode_ham6(CDXLVideoContext *c, AVFrame *frame)
  {
      AVCodecContext *avctx = c->avctx;
      uint32_t new_palette[16], r, g, b;
  #include "libavutil/common.h"
  #include "libavutil/intreadwrite.h"
  #include "avcodec.h"
+ #include "internal.h"
  
  
 -typedef struct {
 -    uint8_t  y0, y1, y2, y3;
 -    uint8_t  u, v;
 -} cvid_codebook;
 +typedef uint8_t cvid_codebook[12];
  
  #define MAX_STRIPS      32
  
@@@ -57,7 -58,7 +58,7 @@@ typedef struct 
  typedef struct CinepakContext {
  
      AVCodecContext *avctx;
--    AVFrame frame;
++    AVFrame *frame;
  
      const unsigned char *data;
      int size;
@@@ -142,22 -138,14 +143,22 @@@ static int cinepak_decode_vectors (Cine
  
      for (y=strip->y1; y < strip->y2; y+=4) {
  
 -        iy[0] = strip->x1 + (y * s->frame.linesize[0]);
 -        iy[1] = iy[0] + s->frame.linesize[0];
 -        iy[2] = iy[1] + s->frame.linesize[0];
 -        iy[3] = iy[2] + s->frame.linesize[0];
 -        iu[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[1]);
 -        iu[1] = iu[0] + s->frame.linesize[1];
 -        iv[0] = (strip->x1/2) + ((y/2) * s->frame.linesize[2]);
 -        iv[1] = iv[0] + s->frame.linesize[2];
 +/* take care of y dimension not being multiple of 4, such streams exist */
-         ip0 = ip1 = ip2 = ip3 = s->frame.data[0] +
-           (s->palette_video?strip->x1:strip->x1*3) + (y * s->frame.linesize[0]);
++        ip0 = ip1 = ip2 = ip3 = s->frame->data[0] +
++          (s->palette_video?strip->x1:strip->x1*3) + (y * s->frame->linesize[0]);
 +        if(s->avctx->height - y > 1) {
-             ip1 = ip0 + s->frame.linesize[0];
++            ip1 = ip0 + s->frame->linesize[0];
 +            if(s->avctx->height - y > 2) {
-                 ip2 = ip1 + s->frame.linesize[0];
++                ip2 = ip1 + s->frame->linesize[0];
 +                if(s->avctx->height - y > 3) {
-                     ip3 = ip2 + s->frame.linesize[0];
++                    ip3 = ip2 + s->frame->linesize[0];
 +                }
 +            }
 +        }
 +/* to get the correct picture for not-multiple-of-4 cases let us fill
 + * each block from the bottom up, thus possibly overwriting the top line
 + * more than once but ending with the correct data in place
 + * (instead of in-loop checking) */
  
          for (x=strip->x1; x < strip->x2; x+=4) {
              if ((chunk_id & 0x01) && !(mask >>= 1)) {
@@@ -359,23 -362,15 +360,23 @@@ static int cinepak_decode (CinepakConte
  
      num_strips = FFMIN(num_strips, MAX_STRIPS);
  
-     s->frame.key_frame = 0;
++    s->frame->key_frame = 0;
 +
      for (i=0; i < num_strips; i++) {
          if ((s->data + 12) > eod)
              return AVERROR_INVALIDDATA;
  
          s->strips[i].id = s->data[0];
 -        s->strips[i].y1 = y0;
 -        s->strips[i].x1 = 0;
 -        s->strips[i].y2 = y0 + AV_RB16 (&s->data[8]);
 -        s->strips[i].x2 = s->avctx->width;
 +/* zero y1 means "relative to the previous stripe" */
 +        if (!(s->strips[i].y1 = AV_RB16 (&s->data[4])))
 +            s->strips[i].y2 = (s->strips[i].y1 = y0) + AV_RB16 (&s->data[8]);
 +        else
 +            s->strips[i].y2 = AV_RB16 (&s->data[8]);
 +        s->strips[i].x1 = AV_RB16 (&s->data[6]);
 +        s->strips[i].x2 = AV_RB16 (&s->data[10]);
 +
 +        if (s->strips[i].id == 0x10)
-             s->frame.key_frame = 1;
++            s->frame->key_frame = 1;
  
          strip_size = AV_RB24 (&s->data[1]) - 12;
          if (strip_size < 0)
@@@ -420,8 -414,7 +421,9 @@@ static av_cold int cinepak_decode_init(
          avctx->pix_fmt = AV_PIX_FMT_PAL8;
      }
  
-     avcodec_get_frame_defaults(&s->frame);
--    s->frame.data[0] = NULL;
++    s->frame = av_frame_alloc();
++    if (!s->frame)
++        return AVERROR(ENOMEM);
  
      return 0;
  }
@@@ -437,10 -430,7 +439,7 @@@ static int cinepak_decode_frame(AVCodec
      s->data = buf;
      s->size = buf_size;
  
-     s->frame.reference = 3;
-     s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
-                             FF_BUFFER_HINTS_REUSABLE;
-     if ((ret = avctx->reget_buffer(avctx, &s->frame))) {
 -    if ((ret = ff_reget_buffer(avctx, &s->frame))) {
++    if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
      if (s->palette_video) {
          const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
          if (pal) {
--            s->frame.palette_has_changed = 1;
++            s->frame->palette_has_changed = 1;
              memcpy(s->pal, pal, AVPALETTE_SIZE);
          }
      }
  
 -    cinepak_decode(s);
 +    if ((ret = cinepak_decode(s)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "cinepak_decode failed\n");
 +    }
  
      if (s->palette_video)
--        memcpy (s->frame.data[1], s->pal, AVPALETTE_SIZE);
++        memcpy (s->frame->data[1], s->pal, AVPALETTE_SIZE);
 -    if ((ret = av_frame_ref(data, &s->frame)) < 0)
++    if ((ret = av_frame_ref(data, s->frame)) < 0)
+         return ret;
  
      *got_frame = 1;
-     *(AVFrame*)data = s->frame;
  
      /* report that the buffer was completely consumed */
      return buf_size;
@@@ -471,8 -461,7 +472,7 @@@ static av_cold int cinepak_decode_end(A
  {
      CinepakContext *s = avctx->priv_data;
  
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
 -    av_frame_unref(&s->frame);
++    av_frame_free(&s->frame);
  
      return 0;
  }
@@@ -84,14 -61,14 +62,14 @@@ static int decode_frame(AVCodecContext 
      init_get_bits(&gb, buf, buf_size * 8);
  
      for (y = 0; y < avctx->height; y++) {
-         uint8_t *luma = &a->picture.data[0][y * a->picture.linesize[0]];
-         uint8_t *cb   = &a->picture.data[1][y * a->picture.linesize[1]];
-         uint8_t *cr   = &a->picture.data[2][y * a->picture.linesize[2]];
+         uint8_t *luma = &p->data[0][y * p->linesize[0]];
+         uint8_t *cb   = &p->data[1][y * p->linesize[1]];
+         uint8_t *cr   = &p->data[2][y * p->linesize[2]];
          for (x = 0; x < avctx->width; x += 4) {
 -            luma[3] = get_bits(&gb, 5) << 3;
 -            luma[2] = get_bits(&gb, 5) << 3;
 -            luma[1] = get_bits(&gb, 5) << 3;
 -            luma[0] = get_bits(&gb, 5) << 3;
 +            luma[3] = (get_bits(&gb, 5)*33) >> 2;
 +            luma[2] = (get_bits(&gb, 5)*33) >> 2;
 +            luma[1] = (get_bits(&gb, 5)*33) >> 2;
 +            luma[0] = (get_bits(&gb, 5)*33) >> 2;
              luma += 4;
              *(cb++) = get_bits(&gb, 6) << 2;
              *(cr++) = get_bits(&gb, 6) << 2;
@@@ -133,6 -98,19 +99,21 @@@ AVCodec ff_cljr_decoder = 
  #endif
  
  #if CONFIG_CLJR_ENCODER
+ typedef struct CLJRContext {
++    AVClass        *avclass;
+     AVFrame         picture;
++    int             dither_type;
+ } CLJRContext;
+ static av_cold int encode_init(AVCodecContext *avctx)
+ {
+     CLJRContext * const a = avctx->priv_data;
+     avctx->coded_frame = &a->picture;
+     return 0;
+ }
  static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                          const AVFrame *p, int *got_packet)
  {
Simple merge
Simple merge
Simple merge
index a5ebc2f,0000000..a29b651
mode 100644,000000..100644
--- /dev/null
@@@ -1,218 -1,0 +1,235 @@@
-     AVFrame frame;
 +/*
 + * CPiA video decoder.
 + * Copyright (c) 2010 Hans de Goede <hdegoede@redhat.com>
 + *
 + * This decoder is based on the LGPL code available at
 + * https://v4l4j.googlecode.com/svn/v4l4j/trunk/libvideo/libv4lconvert/cpia1.c
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "get_bits.h"
++#include "internal.h"
 +
 +
 +#define FRAME_HEADER_SIZE 64
 +#define MAGIC_0         0x19    /**< First header byte */
 +#define MAGIC_1         0x68    /**< Second header byte */
 +#define SUBSAMPLE_420      0
 +#define SUBSAMPLE_422      1
 +#define YUVORDER_YUYV      0
 +#define YUVORDER_UYVY      1
 +#define NOT_COMPRESSED     0
 +#define COMPRESSED         1
 +#define NO_DECIMATION      0
 +#define DECIMATION_ENAB    1
 +#define EOL             0xfd    /**< End Of Line marker */
 +#define EOI             0xff    /**< End Of Image marker */
 +
 +
 +typedef struct {
-     AVFrame* const frame = &cpia->frame;
++    AVFrame *frame;
 +} CpiaContext;
 +
 +
 +static int cpia_decode_frame(AVCodecContext *avctx,
 +                             void *data, int *got_frame, AVPacket* avpkt)
 +{
 +    CpiaContext* const cpia = avctx->priv_data;
 +    int i,j,ret;
 +
 +    uint8_t* const header = avpkt->data;
 +    uint8_t* src;
 +    int src_size;
 +    uint16_t linelength;
 +    uint8_t skip;
 +
-     if ((ret = avctx->reget_buffer(avctx, frame)) < 0) {
++    AVFrame *frame = cpia->frame;
 +    uint8_t *y, *u, *v, *y_end, *u_end, *v_end;
 +
 +    // Check header
 +    if ( avpkt->size < FRAME_HEADER_SIZE
 +      || header[0] != MAGIC_0 || header[1] != MAGIC_1
 +      || (header[17] != SUBSAMPLE_420 && header[17] != SUBSAMPLE_422)
 +      || (header[18] != YUVORDER_YUYV && header[18] != YUVORDER_UYVY)
 +      || (header[28] != NOT_COMPRESSED && header[28] != COMPRESSED)
 +      || (header[29] != NO_DECIMATION && header[29] != DECIMATION_ENAB)
 +    ) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid header!\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    // currently unsupported properties
 +    if (header[17] == SUBSAMPLE_422) {
 +        av_log(avctx, AV_LOG_ERROR, "Unsupported subsample!\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +    if (header[18] == YUVORDER_UYVY) {
 +        av_log(avctx, AV_LOG_ERROR, "Unsupported YUV byte order!\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +    if (header[29] == DECIMATION_ENAB) {
 +        av_log(avctx, AV_LOG_ERROR, "Decimation unsupported!\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    src = header + FRAME_HEADER_SIZE;
 +    src_size = avpkt->size - FRAME_HEADER_SIZE;
 +
 +    if (header[28] == NOT_COMPRESSED) {
 +        frame->pict_type = AV_PICTURE_TYPE_I;
 +        frame->key_frame = 1;
 +    } else {
 +        frame->pict_type = AV_PICTURE_TYPE_P;
 +        frame->key_frame = 0;
 +    }
 +
 +    // Get buffer filled with previous frame
-     *(AVFrame*) data = *frame;
++    if ((ret = ff_reget_buffer(avctx, frame)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed!\n");
 +        return ret;
 +    }
 +
 +
 +    for ( i = 0;
 +          i < frame->height;
 +          i++, src += linelength, src_size -= linelength
 +    ) {
 +        // Read line length, two byte little endian
 +        linelength = AV_RL16(src);
 +        src += 2;
 +
 +        if (src_size < linelength) {
 +            av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM);
 +            av_log(avctx, AV_LOG_WARNING, "Frame ended enexpectedly!\n");
 +            break;
 +        }
 +        if (src[linelength - 1] != EOL) {
 +            av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM);
 +            av_log(avctx, AV_LOG_WARNING, "Wrong line length %d or line not terminated properly (found 0x%02x)!\n", linelength, src[linelength - 1]);
 +            break;
 +        }
 +
 +        /* Update the data pointers. Y data is on every line.
 +         * U and V data on every second line
 +         */
 +        y = &frame->data[0][i * frame->linesize[0]];
 +        u = &frame->data[1][(i >> 1) * frame->linesize[1]];
 +        v = &frame->data[2][(i >> 1) * frame->linesize[2]];
 +        y_end = y + frame->linesize[0] - 1;
 +        u_end = u + frame->linesize[1] - 1;
 +        v_end = v + frame->linesize[2] - 1;
 +
 +        if ((i & 1) && header[17] == SUBSAMPLE_420) {
 +            /* We are on a odd line and 420 subsample is used.
 +             * On this line only Y values are specified, one per pixel.
 +             */
 +            for (j = 0; j < linelength - 1; j++) {
 +                if (y > y_end) {
 +                    av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM);
 +                    av_log(avctx, AV_LOG_WARNING, "Decoded data exceeded linesize!\n");
 +                    break;
 +                }
 +                if ((src[j] & 1) && header[28] == COMPRESSED) {
 +                    /* It seems that odd lines are always uncompressed, but
 +                     * we do it according to specification anyways.
 +                     */
 +                    skip = src[j] >> 1;
 +                    y += skip;
 +                } else {
 +                    *(y++) = src[j];
 +                }
 +            }
 +        } else if (header[17] == SUBSAMPLE_420) {
 +            /* We are on an even line and 420 subsample is used.
 +             * On this line each pair of pixels is described by four bytes.
 +             */
 +            for (j = 0; j < linelength - 4; ) {
 +                if (y + 1 > y_end || u > u_end || v > v_end) {
 +                    av_frame_set_decode_error_flags(frame, FF_DECODE_ERROR_INVALID_BITSTREAM);
 +                    av_log(avctx, AV_LOG_WARNING, "Decoded data exceeded linesize!\n");
 +                    break;
 +                }
 +                if ((src[j] & 1) && header[28] == COMPRESSED) {
 +                    // Skip amount of pixels and move forward one byte
 +                    skip = src[j] >> 1;
 +                    y += skip;
 +                    u += skip >> 1;
 +                    v += skip >> 1;
 +                    j++;
 +                } else {
 +                    // Set image data as specified and move forward 4 bytes
 +                    *(y++) = src[j];
 +                    *(u++) = src[j+1];
 +                    *(y++) = src[j+2];
 +                    *(v++) = src[j+3];
 +                    j += 4;
 +                }
 +            }
 +        }
 +    }
 +
 +    *got_frame = 1;
++    if ((ret = av_frame_ref(data, cpia->frame)) < 0)
++        return ret;
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int cpia_decode_init(AVCodecContext *avctx)
 +{
++    CpiaContext *s = avctx->priv_data;
++
 +    // output pixel format
 +    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
 +
 +    /* The default timebase set by the v4l2 demuxer leads to probing which is buggy.
 +     * Set some reasonable time_base to skip this.
 +     */
 +    if (avctx->time_base.num == 1 && avctx->time_base.den == 1000000) {
 +        avctx->time_base.num = 1;
 +        avctx->time_base.den = 60;
 +    }
 +
++    s->frame = av_frame_alloc();
++    if (!s->frame)
++        return AVERROR(ENOMEM);
++
 +    return 0;
 +}
 +
++static av_cold int cpia_decode_end(AVCodecContext *avctx)
++{
++    CpiaContext *s = avctx->priv_data;
++
++    av_frame_free(&s->frame);
++
++    return 0;
++}
 +
 +AVCodec ff_cpia_decoder = {
 +    .name           = "cpia",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_CPIA,
 +    .priv_data_size = sizeof(CpiaContext),
 +    .init           = cpia_decode_init,
++    .close          = cpia_decode_end,
 +    .decode         = cpia_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("CPiA video format"),
 +};
index e2596a2,0000000..3e9b62b
mode 100644,000000..100644
--- /dev/null
@@@ -1,1226 -1,0 +1,1226 @@@
-         if (ff_get_buffer(avctx, &priv->pic) < 0) {
 +/*
 + * - CrystalHD decoder module -
 + *
 + * Copyright(C) 2010,2011 Philip Langdale <ffmpeg.philipl@overt.org>
 + *
 + * 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
 + */
 +
 +/*
 + * - Principles of Operation -
 + *
 + * The CrystalHD decoder operates at the bitstream level - which is an even
 + * higher level than the decoding hardware you typically see in modern GPUs.
 + * This means it has a very simple interface, in principle. You feed demuxed
 + * packets in one end and get decoded picture (fields/frames) out the other.
 + *
 + * Of course, nothing is ever that simple. Due, at the very least, to b-frame
 + * dependencies in the supported formats, the hardware has a delay between
 + * when a packet goes in, and when a picture comes out. Furthermore, this delay
 + * is not just a function of time, but also one of the dependency on additional
 + * frames being fed into the decoder to satisfy the b-frame dependencies.
 + *
 + * As such, a pipeline will build up that is roughly equivalent to the required
 + * DPB for the file being played. If that was all it took, things would still
 + * be simple - so, of course, it isn't.
 + *
 + * The hardware has a way of indicating that a picture is ready to be copied out,
 + * but this is unreliable - and sometimes the attempt will still fail so, based
 + * on testing, the code will wait until 3 pictures are ready before starting
 + * to copy out - and this has the effect of extending the pipeline.
 + *
 + * Finally, while it is tempting to say that once the decoder starts outputting
 + * frames, the software should never fail to return a frame from a decode(),
 + * this is a hard assertion to make, because the stream may switch between
 + * differently encoded content (number of b-frames, interlacing, etc) which
 + * might require a longer pipeline than before. If that happened, you could
 + * deadlock trying to retrieve a frame that can't be decoded without feeding
 + * in additional packets.
 + *
 + * As such, the code will return in the event that a picture cannot be copied
 + * out, leading to an increase in the length of the pipeline. This in turn,
 + * means we have to be sensitive to the time it takes to decode a picture;
 + * We do not want to give up just because the hardware needed a little more
 + * time to prepare the picture! For this reason, there are delays included
 + * in the decode() path that ensure that, under normal conditions, the hardware
 + * will only fail to return a frame if it really needs additional packets to
 + * complete the decoding.
 + *
 + * Finally, to be explicit, we do not want the pipeline to grow without bound
 + * for two reasons: 1) The hardware can only buffer a finite number of packets,
 + * and 2) The client application may not be able to cope with arbitrarily long
 + * delays in the video path relative to the audio path. For example. MPlayer
 + * can only handle a 20 picture delay (although this is arbitrary, and needs
 + * to be extended to fully support the CrystalHD where the delay could be up
 + * to 32 pictures - consider PAFF H.264 content with 16 b-frames).
 + */
 +
 +/*****************************************************************************
 + * Includes
 + ****************************************************************************/
 +
 +#define _XOPEN_SOURCE 600
 +#include <inttypes.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <unistd.h>
 +
 +#include <libcrystalhd/bc_dts_types.h>
 +#include <libcrystalhd/bc_dts_defs.h>
 +#include <libcrystalhd/libcrystalhd_if.h>
 +
 +#include "avcodec.h"
 +#include "h264.h"
 +#include "internal.h"
 +#include "libavutil/imgutils.h"
 +#include "libavutil/intreadwrite.h"
 +#include "libavutil/opt.h"
 +
 +/** Timeout parameter passed to DtsProcOutput() in us */
 +#define OUTPUT_PROC_TIMEOUT 50
 +/** Step between fake timestamps passed to hardware in units of 100ns */
 +#define TIMESTAMP_UNIT 100000
 +/** Initial value in us of the wait in decode() */
 +#define BASE_WAIT 10000
 +/** Increment in us to adjust wait in decode() */
 +#define WAIT_UNIT 1000
 +
 +
 +/*****************************************************************************
 + * Module private data
 + ****************************************************************************/
 +
 +typedef enum {
 +    RET_ERROR           = -1,
 +    RET_OK              = 0,
 +    RET_COPY_AGAIN      = 1,
 +    RET_SKIP_NEXT_COPY  = 2,
 +    RET_COPY_NEXT_FIELD = 3,
 +} CopyRet;
 +
 +typedef struct OpaqueList {
 +    struct OpaqueList *next;
 +    uint64_t fake_timestamp;
 +    uint64_t reordered_opaque;
 +    uint8_t pic_type;
 +} OpaqueList;
 +
 +typedef struct {
 +    AVClass *av_class;
 +    AVCodecContext *avctx;
 +    AVFrame pic;
 +    HANDLE dev;
 +
 +    uint8_t *orig_extradata;
 +    uint32_t orig_extradata_size;
 +
 +    AVBitStreamFilterContext *bsfc;
 +    AVCodecParserContext *parser;
 +
 +    uint8_t is_70012;
 +    uint8_t *sps_pps_buf;
 +    uint32_t sps_pps_size;
 +    uint8_t is_nal;
 +    uint8_t output_ready;
 +    uint8_t need_second_field;
 +    uint8_t skip_next_output;
 +    uint64_t decode_wait;
 +
 +    uint64_t last_picture;
 +
 +    OpaqueList *head;
 +    OpaqueList *tail;
 +
 +    /* Options */
 +    uint32_t sWidth;
 +    uint8_t bframe_bug;
 +} CHDContext;
 +
 +static const AVOption options[] = {
 +    { "crystalhd_downscale_width",
 +      "Turn on downscaling to the specified width",
 +      offsetof(CHDContext, sWidth),
 +      AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT32_MAX,
 +      AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, },
 +    { NULL, },
 +};
 +
 +
 +/*****************************************************************************
 + * Helper functions
 + ****************************************************************************/
 +
 +static inline BC_MEDIA_SUBTYPE id2subtype(CHDContext *priv, enum AVCodecID id)
 +{
 +    switch (id) {
 +    case AV_CODEC_ID_MPEG4:
 +        return BC_MSUBTYPE_DIVX;
 +    case AV_CODEC_ID_MSMPEG4V3:
 +        return BC_MSUBTYPE_DIVX311;
 +    case AV_CODEC_ID_MPEG2VIDEO:
 +        return BC_MSUBTYPE_MPEG2VIDEO;
 +    case AV_CODEC_ID_VC1:
 +        return BC_MSUBTYPE_VC1;
 +    case AV_CODEC_ID_WMV3:
 +        return BC_MSUBTYPE_WMV3;
 +    case AV_CODEC_ID_H264:
 +        return priv->is_nal ? BC_MSUBTYPE_AVC1 : BC_MSUBTYPE_H264;
 +    default:
 +        return BC_MSUBTYPE_INVALID;
 +    }
 +}
 +
 +static inline void print_frame_info(CHDContext *priv, BC_DTS_PROC_OUT *output)
 +{
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffSz: %u\n", output->YbuffSz);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tYBuffDoneSz: %u\n",
 +           output->YBuffDoneSz);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tUVBuffDoneSz: %u\n",
 +           output->UVBuffDoneSz);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tTimestamp: %"PRIu64"\n",
 +           output->PicInfo.timeStamp);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tPicture Number: %u\n",
 +           output->PicInfo.picture_number);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tWidth: %u\n",
 +           output->PicInfo.width);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tHeight: %u\n",
 +           output->PicInfo.height);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tChroma: 0x%03x\n",
 +           output->PicInfo.chroma_format);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tPulldown: %u\n",
 +           output->PicInfo.pulldown);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tFlags: 0x%08x\n",
 +           output->PicInfo.flags);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrame Rate/Res: %u\n",
 +           output->PicInfo.frame_rate);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tAspect Ratio: %u\n",
 +           output->PicInfo.aspect_ratio);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tColor Primaries: %u\n",
 +           output->PicInfo.colour_primaries);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tMetaData: %u\n",
 +           output->PicInfo.picture_meta_payload);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tSession Number: %u\n",
 +           output->PicInfo.sess_num);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tycom: %u\n",
 +           output->PicInfo.ycom);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tCustom Aspect: %u\n",
 +           output->PicInfo.custom_aspect_ratio_width_height);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tFrames to Drop: %u\n",
 +           output->PicInfo.n_drop);
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "\tH264 Valid Fields: 0x%08x\n",
 +           output->PicInfo.other.h264.valid);
 +}
 +
 +
 +/*****************************************************************************
 + * OpaqueList functions
 + ****************************************************************************/
 +
 +static uint64_t opaque_list_push(CHDContext *priv, uint64_t reordered_opaque,
 +                                 uint8_t pic_type)
 +{
 +    OpaqueList *newNode = av_mallocz(sizeof (OpaqueList));
 +    if (!newNode) {
 +        av_log(priv->avctx, AV_LOG_ERROR,
 +               "Unable to allocate new node in OpaqueList.\n");
 +        return 0;
 +    }
 +    if (!priv->head) {
 +        newNode->fake_timestamp = TIMESTAMP_UNIT;
 +        priv->head              = newNode;
 +    } else {
 +        newNode->fake_timestamp = priv->tail->fake_timestamp + TIMESTAMP_UNIT;
 +        priv->tail->next        = newNode;
 +    }
 +    priv->tail = newNode;
 +    newNode->reordered_opaque = reordered_opaque;
 +    newNode->pic_type = pic_type;
 +
 +    return newNode->fake_timestamp;
 +}
 +
 +/*
 + * The OpaqueList is built in decode order, while elements will be removed
 + * in presentation order. If frames are reordered, this means we must be
 + * able to remove elements that are not the first element.
 + *
 + * Returned node must be freed by caller.
 + */
 +static OpaqueList *opaque_list_pop(CHDContext *priv, uint64_t fake_timestamp)
 +{
 +    OpaqueList *node = priv->head;
 +
 +    if (!priv->head) {
 +        av_log(priv->avctx, AV_LOG_ERROR,
 +               "CrystalHD: Attempted to query non-existent timestamps.\n");
 +        return NULL;
 +    }
 +
 +    /*
 +     * The first element is special-cased because we have to manipulate
 +     * the head pointer rather than the previous element in the list.
 +     */
 +    if (priv->head->fake_timestamp == fake_timestamp) {
 +        priv->head = node->next;
 +
 +        if (!priv->head->next)
 +            priv->tail = priv->head;
 +
 +        node->next = NULL;
 +        return node;
 +    }
 +
 +    /*
 +     * The list is processed at arm's length so that we have the
 +     * previous element available to rewrite its next pointer.
 +     */
 +    while (node->next) {
 +        OpaqueList *current = node->next;
 +        if (current->fake_timestamp == fake_timestamp) {
 +            node->next = current->next;
 +
 +            if (!node->next)
 +               priv->tail = node;
 +
 +            current->next = NULL;
 +            return current;
 +        } else {
 +            node = current;
 +        }
 +    }
 +
 +    av_log(priv->avctx, AV_LOG_VERBOSE,
 +           "CrystalHD: Couldn't match fake_timestamp.\n");
 +    return NULL;
 +}
 +
 +
 +/*****************************************************************************
 + * Video decoder API function definitions
 + ****************************************************************************/
 +
 +static void flush(AVCodecContext *avctx)
 +{
 +    CHDContext *priv = avctx->priv_data;
 +
 +    avctx->has_b_frames     = 0;
 +    priv->last_picture      = -1;
 +    priv->output_ready      = 0;
 +    priv->need_second_field = 0;
 +    priv->skip_next_output  = 0;
 +    priv->decode_wait       = BASE_WAIT;
 +
 +    if (priv->pic.data[0])
 +        avctx->release_buffer(avctx, &priv->pic);
 +
 +    /* Flush mode 4 flushes all software and hardware buffers. */
 +    DtsFlushInput(priv->dev, 4);
 +}
 +
 +
 +static av_cold int uninit(AVCodecContext *avctx)
 +{
 +    CHDContext *priv = avctx->priv_data;
 +    HANDLE device;
 +
 +    device = priv->dev;
 +    DtsStopDecoder(device);
 +    DtsCloseDecoder(device);
 +    DtsDeviceClose(device);
 +
 +    /*
 +     * Restore original extradata, so that if the decoder is
 +     * reinitialised, the bitstream detection and filtering
 +     * will work as expected.
 +     */
 +    if (priv->orig_extradata) {
 +        av_free(avctx->extradata);
 +        avctx->extradata = priv->orig_extradata;
 +        avctx->extradata_size = priv->orig_extradata_size;
 +        priv->orig_extradata = NULL;
 +        priv->orig_extradata_size = 0;
 +    }
 +
 +    av_parser_close(priv->parser);
 +    if (priv->bsfc) {
 +        av_bitstream_filter_close(priv->bsfc);
 +    }
 +
 +    av_free(priv->sps_pps_buf);
 +
 +    if (priv->pic.data[0])
 +        avctx->release_buffer(avctx, &priv->pic);
 +
 +    if (priv->head) {
 +       OpaqueList *node = priv->head;
 +       while (node) {
 +          OpaqueList *next = node->next;
 +          av_free(node);
 +          node = next;
 +       }
 +    }
 +
 +    return 0;
 +}
 +
 +
 +static av_cold int init(AVCodecContext *avctx)
 +{
 +    CHDContext* priv;
 +    BC_STATUS ret;
 +    BC_INFO_CRYSTAL version;
 +    BC_INPUT_FORMAT format = {
 +        .FGTEnable   = FALSE,
 +        .Progressive = TRUE,
 +        .OptFlags    = 0x80000000 | vdecFrameRate59_94 | 0x40,
 +        .width       = avctx->width,
 +        .height      = avctx->height,
 +    };
 +
 +    BC_MEDIA_SUBTYPE subtype;
 +
 +    uint32_t mode = DTS_PLAYBACK_MODE |
 +                    DTS_LOAD_FILE_PLAY_FW |
 +                    DTS_SKIP_TX_CHK_CPB |
 +                    DTS_PLAYBACK_DROP_RPT_MODE |
 +                    DTS_SINGLE_THREADED_MODE |
 +                    DTS_DFLT_RESOLUTION(vdecRESOLUTION_1080p23_976);
 +
 +    av_log(avctx, AV_LOG_VERBOSE, "CrystalHD Init for %s\n",
 +           avctx->codec->name);
 +
 +    avctx->pix_fmt = AV_PIX_FMT_YUYV422;
 +
 +    /* Initialize the library */
 +    priv               = avctx->priv_data;
 +    priv->avctx        = avctx;
 +    priv->is_nal       = avctx->extradata_size > 0 && *(avctx->extradata) == 1;
 +    priv->last_picture = -1;
 +    priv->decode_wait  = BASE_WAIT;
 +
 +    subtype = id2subtype(priv, avctx->codec->id);
 +    switch (subtype) {
 +    case BC_MSUBTYPE_AVC1:
 +        {
 +            uint8_t *dummy_p;
 +            int dummy_int;
 +
 +            /* Back up the extradata so it can be restored at close time. */
 +            priv->orig_extradata = av_malloc(avctx->extradata_size);
 +            if (!priv->orig_extradata) {
 +                av_log(avctx, AV_LOG_ERROR,
 +                       "Failed to allocate copy of extradata\n");
 +                return AVERROR(ENOMEM);
 +            }
 +            priv->orig_extradata_size = avctx->extradata_size;
 +            memcpy(priv->orig_extradata, avctx->extradata, avctx->extradata_size);
 +
 +            priv->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
 +            if (!priv->bsfc) {
 +                av_log(avctx, AV_LOG_ERROR,
 +                       "Cannot open the h264_mp4toannexb BSF!\n");
 +                return AVERROR_BSF_NOT_FOUND;
 +            }
 +            av_bitstream_filter_filter(priv->bsfc, avctx, NULL, &dummy_p,
 +                                       &dummy_int, NULL, 0, 0);
 +        }
 +        subtype = BC_MSUBTYPE_H264;
 +        // Fall-through
 +    case BC_MSUBTYPE_H264:
 +        format.startCodeSz = 4;
 +        // Fall-through
 +    case BC_MSUBTYPE_VC1:
 +    case BC_MSUBTYPE_WVC1:
 +    case BC_MSUBTYPE_WMV3:
 +    case BC_MSUBTYPE_WMVA:
 +    case BC_MSUBTYPE_MPEG2VIDEO:
 +    case BC_MSUBTYPE_DIVX:
 +    case BC_MSUBTYPE_DIVX311:
 +        format.pMetaData  = avctx->extradata;
 +        format.metaDataSz = avctx->extradata_size;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: Unknown codec name\n");
 +        return AVERROR(EINVAL);
 +    }
 +    format.mSubtype = subtype;
 +
 +    if (priv->sWidth) {
 +        format.bEnableScaling = 1;
 +        format.ScalingParams.sWidth = priv->sWidth;
 +    }
 +
 +    /* Get a decoder instance */
 +    av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: starting up\n");
 +    // Initialize the Link and Decoder devices
 +    ret = DtsDeviceOpen(&priv->dev, mode);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: DtsDeviceOpen failed\n");
 +        goto fail;
 +    }
 +
 +    ret = DtsCrystalHDVersion(priv->dev, &version);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_VERBOSE,
 +               "CrystalHD: DtsCrystalHDVersion failed\n");
 +        goto fail;
 +    }
 +    priv->is_70012 = version.device == 0;
 +
 +    if (priv->is_70012 &&
 +        (subtype == BC_MSUBTYPE_DIVX || subtype == BC_MSUBTYPE_DIVX311)) {
 +        av_log(avctx, AV_LOG_VERBOSE,
 +               "CrystalHD: BCM70012 doesn't support MPEG4-ASP/DivX/Xvid\n");
 +        goto fail;
 +    }
 +
 +    ret = DtsSetInputFormat(priv->dev, &format);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: SetInputFormat failed\n");
 +        goto fail;
 +    }
 +
 +    ret = DtsOpenDecoder(priv->dev, BC_STREAM_TYPE_ES);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsOpenDecoder failed\n");
 +        goto fail;
 +    }
 +
 +    ret = DtsSetColorSpace(priv->dev, OUTPUT_MODE422_YUY2);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsSetColorSpace failed\n");
 +        goto fail;
 +    }
 +    ret = DtsStartDecoder(priv->dev);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartDecoder failed\n");
 +        goto fail;
 +    }
 +    ret = DtsStartCapture(priv->dev);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: DtsStartCapture failed\n");
 +        goto fail;
 +    }
 +
 +    if (avctx->codec->id == AV_CODEC_ID_H264) {
 +        priv->parser = av_parser_init(avctx->codec->id);
 +        if (!priv->parser)
 +            av_log(avctx, AV_LOG_WARNING,
 +                   "Cannot open the h.264 parser! Interlaced h.264 content "
 +                   "will not be detected reliably.\n");
 +        priv->parser->flags = PARSER_FLAG_COMPLETE_FRAMES;
 +    }
 +    av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Init complete.\n");
 +
 +    return 0;
 +
 + fail:
 +    uninit(avctx);
 +    return -1;
 +}
 +
 +
 +static inline CopyRet copy_frame(AVCodecContext *avctx,
 +                                 BC_DTS_PROC_OUT *output,
 +                                 void *data, int *got_frame)
 +{
 +    BC_STATUS ret;
 +    BC_DTS_STATUS decoder_status = { 0, };
 +    uint8_t trust_interlaced;
 +    uint8_t interlaced;
 +
 +    CHDContext *priv = avctx->priv_data;
 +    int64_t pkt_pts  = AV_NOPTS_VALUE;
 +    uint8_t pic_type = 0;
 +
 +    uint8_t bottom_field = (output->PicInfo.flags & VDEC_FLAG_BOTTOMFIELD) ==
 +                           VDEC_FLAG_BOTTOMFIELD;
 +    uint8_t bottom_first = !!(output->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
 +
 +    int width    = output->PicInfo.width;
 +    int height   = output->PicInfo.height;
 +    int bwidth;
 +    uint8_t *src = output->Ybuff;
 +    int sStride;
 +    uint8_t *dst;
 +    int dStride;
 +
 +    if (output->PicInfo.timeStamp != 0) {
 +        OpaqueList *node = opaque_list_pop(priv, output->PicInfo.timeStamp);
 +        if (node) {
 +            pkt_pts = node->reordered_opaque;
 +            pic_type = node->pic_type;
 +            av_free(node);
 +        } else {
 +            /*
 +             * We will encounter a situation where a timestamp cannot be
 +             * popped if a second field is being returned. In this case,
 +             * each field has the same timestamp and the first one will
 +             * cause it to be popped. To keep subsequent calculations
 +             * simple, pic_type should be set a FIELD value - doesn't
 +             * matter which, but I chose BOTTOM.
 +             */
 +            pic_type = PICT_BOTTOM_FIELD;
 +        }
 +        av_log(avctx, AV_LOG_VERBOSE, "output \"pts\": %"PRIu64"\n",
 +               output->PicInfo.timeStamp);
 +        av_log(avctx, AV_LOG_VERBOSE, "output picture type %d\n",
 +               pic_type);
 +    }
 +
 +    ret = DtsGetDriverStatus(priv->dev, &decoder_status);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR,
 +               "CrystalHD: GetDriverStatus failed: %u\n", ret);
 +       return RET_ERROR;
 +    }
 +
 +    /*
 +     * For most content, we can trust the interlaced flag returned
 +     * by the hardware, but sometimes we can't. These are the
 +     * conditions under which we can trust the flag:
 +     *
 +     * 1) It's not h.264 content
 +     * 2) The UNKNOWN_SRC flag is not set
 +     * 3) We know we're expecting a second field
 +     * 4) The hardware reports this picture and the next picture
 +     *    have the same picture number.
 +     *
 +     * Note that there can still be interlaced content that will
 +     * fail this check, if the hardware hasn't decoded the next
 +     * picture or if there is a corruption in the stream. (In either
 +     * case a 0 will be returned for the next picture number)
 +     */
 +    trust_interlaced = avctx->codec->id != AV_CODEC_ID_H264 ||
 +                       !(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
 +                       priv->need_second_field ||
 +                       (decoder_status.picNumFlags & ~0x40000000) ==
 +                       output->PicInfo.picture_number;
 +
 +    /*
 +     * If we got a false negative for trust_interlaced on the first field,
 +     * we will realise our mistake here when we see that the picture number is that
 +     * of the previous picture. We cannot recover the frame and should discard the
 +     * second field to keep the correct number of output frames.
 +     */
 +    if (output->PicInfo.picture_number == priv->last_picture && !priv->need_second_field) {
 +        av_log(avctx, AV_LOG_WARNING,
 +               "Incorrectly guessed progressive frame. Discarding second field\n");
 +        /* Returning without providing a picture. */
 +        return RET_OK;
 +    }
 +
 +    interlaced = (output->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
 +                 trust_interlaced;
 +
 +    if (!trust_interlaced && (decoder_status.picNumFlags & ~0x40000000) == 0) {
 +        av_log(avctx, AV_LOG_VERBOSE,
 +               "Next picture number unknown. Assuming progressive frame.\n");
 +    }
 +
 +    av_log(avctx, AV_LOG_VERBOSE, "Interlaced state: %d | trust_interlaced %d\n",
 +           interlaced, trust_interlaced);
 +
 +    if (priv->pic.data[0] && !priv->need_second_field)
 +        avctx->release_buffer(avctx, &priv->pic);
 +
 +    priv->need_second_field = interlaced && !priv->need_second_field;
 +
 +    priv->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
 +                             FF_BUFFER_HINTS_REUSABLE;
 +    if (!priv->pic.data[0]) {
++        if (ff_get_buffer(avctx, &priv->pic, 0) < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +            return RET_ERROR;
 +        }
 +    }
 +
 +    bwidth = av_image_get_linesize(avctx->pix_fmt, width, 0);
 +    if (priv->is_70012) {
 +        int pStride;
 +
 +        if (width <= 720)
 +            pStride = 720;
 +        else if (width <= 1280)
 +            pStride = 1280;
 +        else pStride = 1920;
 +        sStride = av_image_get_linesize(avctx->pix_fmt, pStride, 0);
 +    } else {
 +        sStride = bwidth;
 +    }
 +
 +    dStride = priv->pic.linesize[0];
 +    dst     = priv->pic.data[0];
 +
 +    av_log(priv->avctx, AV_LOG_VERBOSE, "CrystalHD: Copying out frame\n");
 +
 +    if (interlaced) {
 +        int dY = 0;
 +        int sY = 0;
 +
 +        height /= 2;
 +        if (bottom_field) {
 +            av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: bottom field\n");
 +            dY = 1;
 +        } else {
 +            av_log(priv->avctx, AV_LOG_VERBOSE, "Interlaced: top field\n");
 +            dY = 0;
 +        }
 +
 +        for (sY = 0; sY < height; dY++, sY++) {
 +            memcpy(&(dst[dY * dStride]), &(src[sY * sStride]), bwidth);
 +            dY++;
 +        }
 +    } else {
 +        av_image_copy_plane(dst, dStride, src, sStride, bwidth, height);
 +    }
 +
 +    priv->pic.interlaced_frame = interlaced;
 +    if (interlaced)
 +        priv->pic.top_field_first = !bottom_first;
 +
 +    priv->pic.pkt_pts = pkt_pts;
 +
 +    if (!priv->need_second_field) {
 +        *got_frame       = 1;
 +        *(AVFrame *)data = priv->pic;
 +    }
 +
 +    /*
 +     * Two types of PAFF content have been observed. One form causes the
 +     * hardware to return a field pair and the other individual fields,
 +     * even though the input is always individual fields. We must skip
 +     * copying on the next decode() call to maintain pipeline length in
 +     * the first case.
 +     */
 +    if (!interlaced && (output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) &&
 +        (pic_type == PICT_TOP_FIELD || pic_type == PICT_BOTTOM_FIELD)) {
 +        av_log(priv->avctx, AV_LOG_VERBOSE, "Fieldpair from two packets.\n");
 +        return RET_SKIP_NEXT_COPY;
 +    }
 +
 +    /*
 +     * The logic here is purely based on empirical testing with samples.
 +     * If we need a second field, it could come from a second input packet,
 +     * or it could come from the same field-pair input packet at the current
 +     * field. In the first case, we should return and wait for the next time
 +     * round to get the second field, while in the second case, we should
 +     * ask the decoder for it immediately.
 +     *
 +     * Testing has shown that we are dealing with the fieldpair -> two fields
 +     * case if the VDEC_FLAG_UNKNOWN_SRC is not set or if the input picture
 +     * type was PICT_FRAME (in this second case, the flag might still be set)
 +     */
 +    return priv->need_second_field &&
 +           (!(output->PicInfo.flags & VDEC_FLAG_UNKNOWN_SRC) ||
 +            pic_type == PICT_FRAME) ?
 +           RET_COPY_NEXT_FIELD : RET_OK;
 +}
 +
 +
 +static inline CopyRet receive_frame(AVCodecContext *avctx,
 +                                    void *data, int *got_frame)
 +{
 +    BC_STATUS ret;
 +    BC_DTS_PROC_OUT output = {
 +        .PicInfo.width  = avctx->width,
 +        .PicInfo.height = avctx->height,
 +    };
 +    CHDContext *priv = avctx->priv_data;
 +    HANDLE dev       = priv->dev;
 +
 +    *got_frame = 0;
 +
 +    // Request decoded data from the driver
 +    ret = DtsProcOutputNoCopy(dev, OUTPUT_PROC_TIMEOUT, &output);
 +    if (ret == BC_STS_FMT_CHANGE) {
 +        av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Initial format change\n");
 +        avctx->width  = output.PicInfo.width;
 +        avctx->height = output.PicInfo.height;
 +        switch ( output.PicInfo.aspect_ratio ) {
 +        case vdecAspectRatioSquare:
 +            avctx->sample_aspect_ratio = (AVRational) {  1,  1};
 +            break;
 +        case vdecAspectRatio12_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 12, 11};
 +            break;
 +        case vdecAspectRatio10_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 10, 11};
 +            break;
 +        case vdecAspectRatio16_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 16, 11};
 +            break;
 +        case vdecAspectRatio40_33:
 +            avctx->sample_aspect_ratio = (AVRational) { 40, 33};
 +            break;
 +        case vdecAspectRatio24_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 24, 11};
 +            break;
 +        case vdecAspectRatio20_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 20, 11};
 +            break;
 +        case vdecAspectRatio32_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 32, 11};
 +            break;
 +        case vdecAspectRatio80_33:
 +            avctx->sample_aspect_ratio = (AVRational) { 80, 33};
 +            break;
 +        case vdecAspectRatio18_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 18, 11};
 +            break;
 +        case vdecAspectRatio15_11:
 +            avctx->sample_aspect_ratio = (AVRational) { 15, 11};
 +            break;
 +        case vdecAspectRatio64_33:
 +            avctx->sample_aspect_ratio = (AVRational) { 64, 33};
 +            break;
 +        case vdecAspectRatio160_99:
 +            avctx->sample_aspect_ratio = (AVRational) {160, 99};
 +            break;
 +        case vdecAspectRatio4_3:
 +            avctx->sample_aspect_ratio = (AVRational) {  4,  3};
 +            break;
 +        case vdecAspectRatio16_9:
 +            avctx->sample_aspect_ratio = (AVRational) { 16,  9};
 +            break;
 +        case vdecAspectRatio221_1:
 +            avctx->sample_aspect_ratio = (AVRational) {221,  1};
 +            break;
 +        }
 +        return RET_COPY_AGAIN;
 +    } else if (ret == BC_STS_SUCCESS) {
 +        int copy_ret = -1;
 +        if (output.PoutFlags & BC_POUT_FLAGS_PIB_VALID) {
 +            if (priv->last_picture == -1) {
 +                /*
 +                 * Init to one less, so that the incrementing code doesn't
 +                 * need to be special-cased.
 +                 */
 +                priv->last_picture = output.PicInfo.picture_number - 1;
 +            }
 +
 +            if (avctx->codec->id == AV_CODEC_ID_MPEG4 &&
 +                output.PicInfo.timeStamp == 0 && priv->bframe_bug) {
 +                av_log(avctx, AV_LOG_VERBOSE,
 +                       "CrystalHD: Not returning packed frame twice.\n");
 +                priv->last_picture++;
 +                DtsReleaseOutputBuffs(dev, NULL, FALSE);
 +                return RET_COPY_AGAIN;
 +            }
 +
 +            print_frame_info(priv, &output);
 +
 +            if (priv->last_picture + 1 < output.PicInfo.picture_number) {
 +                av_log(avctx, AV_LOG_WARNING,
 +                       "CrystalHD: Picture Number discontinuity\n");
 +                /*
 +                 * Have we lost frames? If so, we need to shrink the
 +                 * pipeline length appropriately.
 +                 *
 +                 * XXX: I have no idea what the semantics of this situation
 +                 * are so I don't even know if we've lost frames or which
 +                 * ones.
 +                 *
 +                 * In any case, only warn the first time.
 +                 */
 +               priv->last_picture = output.PicInfo.picture_number - 1;
 +            }
 +
 +            copy_ret = copy_frame(avctx, &output, data, got_frame);
 +            if (*got_frame > 0) {
 +                avctx->has_b_frames--;
 +                priv->last_picture++;
 +                av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Pipeline length: %u\n",
 +                       avctx->has_b_frames);
 +            }
 +        } else {
 +            /*
 +             * An invalid frame has been consumed.
 +             */
 +            av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput succeeded with "
 +                                        "invalid PIB\n");
 +            avctx->has_b_frames--;
 +            copy_ret = RET_OK;
 +        }
 +        DtsReleaseOutputBuffs(dev, NULL, FALSE);
 +
 +        return copy_ret;
 +    } else if (ret == BC_STS_BUSY) {
 +        return RET_COPY_AGAIN;
 +    } else {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: ProcOutput failed %d\n", ret);
 +        return RET_ERROR;
 +    }
 +}
 +
 +
 +static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
 +{
 +    BC_STATUS ret;
 +    BC_DTS_STATUS decoder_status = { 0, };
 +    CopyRet rec_ret;
 +    CHDContext *priv   = avctx->priv_data;
 +    HANDLE dev         = priv->dev;
 +    uint8_t *in_data   = avpkt->data;
 +    int len            = avpkt->size;
 +    int free_data      = 0;
 +    uint8_t pic_type   = 0;
 +
 +    av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: decode_frame\n");
 +
 +    if (avpkt->size == 7 && !priv->bframe_bug) {
 +        /*
 +         * The use of a drop frame triggers the bug
 +         */
 +        av_log(avctx, AV_LOG_INFO,
 +               "CrystalHD: Enabling work-around for packed b-frame bug\n");
 +        priv->bframe_bug = 1;
 +    } else if (avpkt->size == 8 && priv->bframe_bug) {
 +        /*
 +         * Delay frames don't trigger the bug
 +         */
 +        av_log(avctx, AV_LOG_INFO,
 +               "CrystalHD: Disabling work-around for packed b-frame bug\n");
 +        priv->bframe_bug = 0;
 +    }
 +
 +    if (len) {
 +        int32_t tx_free = (int32_t)DtsTxFreeSize(dev);
 +
 +        if (priv->parser) {
 +            int ret = 0;
 +
 +            if (priv->bsfc) {
 +                ret = av_bitstream_filter_filter(priv->bsfc, avctx, NULL,
 +                                                 &in_data, &len,
 +                                                 avpkt->data, len, 0);
 +            }
 +            free_data = ret > 0;
 +
 +            if (ret >= 0) {
 +                uint8_t *pout;
 +                int psize;
 +                int index;
 +                H264Context *h = priv->parser->priv_data;
 +
 +                index = av_parser_parse2(priv->parser, avctx, &pout, &psize,
 +                                         in_data, len, avctx->pkt->pts,
 +                                         avctx->pkt->dts, 0);
 +                if (index < 0) {
 +                    av_log(avctx, AV_LOG_WARNING,
 +                           "CrystalHD: Failed to parse h.264 packet to "
 +                           "detect interlacing.\n");
 +                } else if (index != len) {
 +                    av_log(avctx, AV_LOG_WARNING,
 +                           "CrystalHD: Failed to parse h.264 packet "
 +                           "completely. Interlaced frames may be "
 +                           "incorrectly detected.\n");
 +                } else {
 +                    av_log(avctx, AV_LOG_VERBOSE,
 +                           "CrystalHD: parser picture type %d\n",
 +                           h->picture_structure);
 +                    pic_type = h->picture_structure;
 +                }
 +            } else {
 +                av_log(avctx, AV_LOG_WARNING,
 +                       "CrystalHD: mp4toannexb filter failed to filter "
 +                       "packet. Interlaced frames may be incorrectly "
 +                       "detected.\n");
 +            }
 +        }
 +
 +        if (len < tx_free - 1024) {
 +            /*
 +             * Despite being notionally opaque, either libcrystalhd or
 +             * the hardware itself will mangle pts values that are too
 +             * small or too large. The docs claim it should be in units
 +             * of 100ns. Given that we're nominally dealing with a black
 +             * box on both sides, any transform we do has no guarantee of
 +             * avoiding mangling so we need to build a mapping to values
 +             * we know will not be mangled.
 +             */
 +            uint64_t pts = opaque_list_push(priv, avctx->pkt->pts, pic_type);
 +            if (!pts) {
 +                if (free_data) {
 +                    av_freep(&in_data);
 +                }
 +                return AVERROR(ENOMEM);
 +            }
 +            av_log(priv->avctx, AV_LOG_VERBOSE,
 +                   "input \"pts\": %"PRIu64"\n", pts);
 +            ret = DtsProcInput(dev, in_data, len, pts, 0);
 +            if (free_data) {
 +                av_freep(&in_data);
 +            }
 +            if (ret == BC_STS_BUSY) {
 +                av_log(avctx, AV_LOG_WARNING,
 +                       "CrystalHD: ProcInput returned busy\n");
 +                usleep(BASE_WAIT);
 +                return AVERROR(EBUSY);
 +            } else if (ret != BC_STS_SUCCESS) {
 +                av_log(avctx, AV_LOG_ERROR,
 +                       "CrystalHD: ProcInput failed: %u\n", ret);
 +                return -1;
 +            }
 +            avctx->has_b_frames++;
 +        } else {
 +            av_log(avctx, AV_LOG_WARNING, "CrystalHD: Input buffer full\n");
 +            len = 0; // We didn't consume any bytes.
 +        }
 +    } else {
 +        av_log(avctx, AV_LOG_INFO, "CrystalHD: No more input data\n");
 +    }
 +
 +    if (priv->skip_next_output) {
 +        av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Skipping next output.\n");
 +        priv->skip_next_output = 0;
 +        avctx->has_b_frames--;
 +        return len;
 +    }
 +
 +    ret = DtsGetDriverStatus(dev, &decoder_status);
 +    if (ret != BC_STS_SUCCESS) {
 +        av_log(avctx, AV_LOG_ERROR, "CrystalHD: GetDriverStatus failed\n");
 +        return -1;
 +    }
 +
 +    /*
 +     * No frames ready. Don't try to extract.
 +     *
 +     * Empirical testing shows that ReadyListCount can be a damn lie,
 +     * and ProcOut still fails when count > 0. The same testing showed
 +     * that two more iterations were needed before ProcOutput would
 +     * succeed.
 +     */
 +    if (priv->output_ready < 2) {
 +        if (decoder_status.ReadyListCount != 0)
 +            priv->output_ready++;
 +        usleep(BASE_WAIT);
 +        av_log(avctx, AV_LOG_INFO, "CrystalHD: Filling pipeline.\n");
 +        return len;
 +    } else if (decoder_status.ReadyListCount == 0) {
 +        /*
 +         * After the pipeline is established, if we encounter a lack of frames
 +         * that probably means we're not giving the hardware enough time to
 +         * decode them, so start increasing the wait time at the end of a
 +         * decode call.
 +         */
 +        usleep(BASE_WAIT);
 +        priv->decode_wait += WAIT_UNIT;
 +        av_log(avctx, AV_LOG_INFO, "CrystalHD: No frames ready. Returning\n");
 +        return len;
 +    }
 +
 +    do {
 +        rec_ret = receive_frame(avctx, data, got_frame);
 +        if (rec_ret == RET_OK && *got_frame == 0) {
 +            /*
 +             * This case is for when the encoded fields are stored
 +             * separately and we get a separate avpkt for each one. To keep
 +             * the pipeline stable, we should return nothing and wait for
 +             * the next time round to grab the second field.
 +             * H.264 PAFF is an example of this.
 +             */
 +            av_log(avctx, AV_LOG_VERBOSE, "Returning after first field.\n");
 +            avctx->has_b_frames--;
 +        } else if (rec_ret == RET_COPY_NEXT_FIELD) {
 +            /*
 +             * This case is for when the encoded fields are stored in a
 +             * single avpkt but the hardware returns then separately. Unless
 +             * we grab the second field before returning, we'll slip another
 +             * frame in the pipeline and if that happens a lot, we're sunk.
 +             * So we have to get that second field now.
 +             * Interlaced mpeg2 and vc1 are examples of this.
 +             */
 +            av_log(avctx, AV_LOG_VERBOSE, "Trying to get second field.\n");
 +            while (1) {
 +                usleep(priv->decode_wait);
 +                ret = DtsGetDriverStatus(dev, &decoder_status);
 +                if (ret == BC_STS_SUCCESS &&
 +                    decoder_status.ReadyListCount > 0) {
 +                    rec_ret = receive_frame(avctx, data, got_frame);
 +                    if ((rec_ret == RET_OK && *got_frame > 0) ||
 +                        rec_ret == RET_ERROR)
 +                        break;
 +                }
 +            }
 +            av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: Got second field.\n");
 +        } else if (rec_ret == RET_SKIP_NEXT_COPY) {
 +            /*
 +             * Two input packets got turned into a field pair. Gawd.
 +             */
 +            av_log(avctx, AV_LOG_VERBOSE,
 +                   "Don't output on next decode call.\n");
 +            priv->skip_next_output = 1;
 +        }
 +        /*
 +         * If rec_ret == RET_COPY_AGAIN, that means that either we just handled
 +         * a FMT_CHANGE event and need to go around again for the actual frame,
 +         * we got a busy status and need to try again, or we're dealing with
 +         * packed b-frames, where the hardware strangely returns the packed
 +         * p-frame twice. We choose to keep the second copy as it carries the
 +         * valid pts.
 +         */
 +    } while (rec_ret == RET_COPY_AGAIN);
 +    usleep(priv->decode_wait);
 +    return len;
 +}
 +
 +
 +#if CONFIG_H264_CRYSTALHD_DECODER
 +static AVClass h264_class = {
 +    "h264_crystalhd",
 +    av_default_item_name,
 +    options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_h264_crystalhd_decoder = {
 +    .name           = "h264_crystalhd",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_H264,
 +    .priv_data_size = sizeof(CHDContext),
 +    .init           = init,
 +    .close          = uninit,
 +    .decode         = decode,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
 +    .flush          = flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (CrystalHD acceleration)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE},
 +    .priv_class     = &h264_class,
 +};
 +#endif
 +
 +#if CONFIG_MPEG2_CRYSTALHD_DECODER
 +static AVClass mpeg2_class = {
 +    "mpeg2_crystalhd",
 +    av_default_item_name,
 +    options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_mpeg2_crystalhd_decoder = {
 +    .name           = "mpeg2_crystalhd",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_MPEG2VIDEO,
 +    .priv_data_size = sizeof(CHDContext),
 +    .init           = init,
 +    .close          = uninit,
 +    .decode         = decode,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
 +    .flush          = flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-2 Video (CrystalHD acceleration)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE},
 +    .priv_class     = &mpeg2_class,
 +};
 +#endif
 +
 +#if CONFIG_MPEG4_CRYSTALHD_DECODER
 +static AVClass mpeg4_class = {
 +    "mpeg4_crystalhd",
 +    av_default_item_name,
 +    options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_mpeg4_crystalhd_decoder = {
 +    .name           = "mpeg4_crystalhd",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_MPEG4,
 +    .priv_data_size = sizeof(CHDContext),
 +    .init           = init,
 +    .close          = uninit,
 +    .decode         = decode,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
 +    .flush          = flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 (CrystalHD acceleration)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE},
 +    .priv_class     = &mpeg4_class,
 +};
 +#endif
 +
 +#if CONFIG_MSMPEG4_CRYSTALHD_DECODER
 +static AVClass msmpeg4_class = {
 +    "msmpeg4_crystalhd",
 +    av_default_item_name,
 +    options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_msmpeg4_crystalhd_decoder = {
 +    .name           = "msmpeg4_crystalhd",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_MSMPEG4V3,
 +    .priv_data_size = sizeof(CHDContext),
 +    .init           = init,
 +    .close          = uninit,
 +    .decode         = decode,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_EXPERIMENTAL,
 +    .flush          = flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("MPEG-4 Part 2 Microsoft variant version 3 (CrystalHD acceleration)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE},
 +    .priv_class     = &msmpeg4_class,
 +};
 +#endif
 +
 +#if CONFIG_VC1_CRYSTALHD_DECODER
 +static AVClass vc1_class = {
 +    "vc1_crystalhd",
 +    av_default_item_name,
 +    options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_vc1_crystalhd_decoder = {
 +    .name           = "vc1_crystalhd",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_VC1,
 +    .priv_data_size = sizeof(CHDContext),
 +    .init           = init,
 +    .close          = uninit,
 +    .decode         = decode,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
 +    .flush          = flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("SMPTE VC-1 (CrystalHD acceleration)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE},
 +    .priv_class     = &vc1_class,
 +};
 +#endif
 +
 +#if CONFIG_WMV3_CRYSTALHD_DECODER
 +static AVClass wmv3_class = {
 +    "wmv3_crystalhd",
 +    av_default_item_name,
 +    options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_wmv3_crystalhd_decoder = {
 +    .name           = "wmv3_crystalhd",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_WMV3,
 +    .priv_data_size = sizeof(CHDContext),
 +    .init           = init,
 +    .close          = uninit,
 +    .decode         = decode,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_DELAY,
 +    .flush          = flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Windows Media Video 9 (CrystalHD acceleration)"),
 +    .pix_fmts       = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE},
 +    .priv_class     = &wmv3_class,
 +};
 +#endif
@@@ -31,7 -31,6 +31,7 @@@
  #include "libavutil/lzo.h"
  
  typedef struct {
-     AVFrame pic;
++    AVFrame *pic;
      int linelen, height, bpp;
      unsigned int decomp_size;
      unsigned char* decomp_buf;
@@@ -67,7 -141,7 +67,6 @@@ static int decode_frame(AVCodecContext 
      const uint8_t *buf = avpkt->data;
      int buf_size = avpkt->size;
      CamStudioContext *c = avctx->priv_data;
--    AVFrame *picture = data;
      int ret;
  
      if (buf_size < 2) {
          return AVERROR_INVALIDDATA;
      }
  
-     c->pic.reference = 3;
-     c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
-                           FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     if ((ret = avctx->reget_buffer(avctx, &c->pic)) < 0) {
 -    if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) {
++    if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
  
      // flip upside down, add difference frame
      if (buf[0] & 1) { // keyframe
-         c->pic.pict_type = AV_PICTURE_TYPE_I;
-         c->pic.key_frame = 1;
-               copy_frame_default(&c->pic, c->decomp_buf,
 -        picture->pict_type = AV_PICTURE_TYPE_I;
 -        picture->key_frame = 1;
 -        switch (c->bpp) {
 -          case 16:
 -              copy_frame_16(picture, c->decomp_buf, c->linelen, c->height);
 -              break;
 -          case 32:
 -              copy_frame_32(picture, c->decomp_buf, c->linelen, c->height);
 -              break;
 -          default:
 -              copy_frame_default(picture, c->decomp_buf, FFALIGN(c->linelen, 4),
++        c->pic->pict_type = AV_PICTURE_TYPE_I;
++        c->pic->key_frame = 1;
++              copy_frame_default(c->pic, c->decomp_buf,
                                   c->linelen, c->height);
 -        }
      } else {
-         c->pic.pict_type = AV_PICTURE_TYPE_P;
-         c->pic.key_frame = 0;
-               add_frame_default(&c->pic, c->decomp_buf,
 -        picture->pict_type = AV_PICTURE_TYPE_P;
 -        picture->key_frame = 0;
 -        switch (c->bpp) {
 -          case 16:
 -              add_frame_16(picture, c->decomp_buf, c->linelen, c->height);
 -              break;
 -          case 32:
 -              add_frame_32(picture, c->decomp_buf, c->linelen, c->height);
 -              break;
 -          default:
 -              add_frame_default(picture, c->decomp_buf, FFALIGN(c->linelen, 4),
++        c->pic->pict_type = AV_PICTURE_TYPE_P;
++        c->pic->key_frame = 0;
++              add_frame_default(c->pic, c->decomp_buf,
                                  c->linelen, c->height);
 -        }
      }
  
-     *picture = c->pic;
      *got_frame = 1;
++    if ((ret = av_frame_ref(data, c->pic)) < 0)
++        return ret;
++
      return buf_size;
  }
  
@@@ -139,25 -227,23 +137,25 @@@ static av_cold int decode_init(AVCodecC
              return AVERROR_INVALIDDATA;
      }
      c->bpp = avctx->bits_per_coded_sample;
-     avcodec_get_frame_defaults(&c->pic);
-     c->pic.data[0] = NULL;
      c->linelen = avctx->width * avctx->bits_per_coded_sample / 8;
      c->height = avctx->height;
 -    stride = c->linelen;
 -    if (avctx->bits_per_coded_sample == 24)
 -        stride = FFALIGN(stride, 4);
 +    stride = FFALIGN(c->linelen, 4);
      c->decomp_size = c->height * stride;
      c->decomp_buf = av_malloc(c->decomp_size + AV_LZO_OUTPUT_PADDING);
      if (!c->decomp_buf) {
          av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
          return AVERROR(ENOMEM);
      }
++    c->pic = av_frame_alloc();
++    if (!c->pic)
++        return AVERROR(ENOMEM);
      return 0;
  }
  
  static av_cold int decode_end(AVCodecContext *avctx) {
      CamStudioContext *c = avctx->priv_data;
      av_freep(&c->decomp_buf);
-     if (c->pic.data[0])
-         avctx->release_buffer(avctx, &c->pic);
++    av_frame_free(&c->pic);
      return 0;
  }
  
@@@ -53,7 -52,7 +52,6 @@@ static av_cold int cyuv_decode_init(AVC
      if (s->width & 0x3)
          return AVERROR_INVALIDDATA;
      s->height = avctx->height;
-     avcodec_get_frame_defaults(&s->frame);
 -    avctx->pix_fmt = AV_PIX_FMT_YUV411P;
  
      return 0;
  }
@@@ -116,25 -106,16 +110,25 @@@ static int cyuv_decode_frame(AVCodecCon
          return ret;
      }
  
-     y_plane = s->frame.data[0];
-     u_plane = s->frame.data[1];
-     v_plane = s->frame.data[2];
+     y_plane = frame->data[0];
+     u_plane = frame->data[1];
+     v_plane = frame->data[2];
  
-         y_plane += s->frame.linesize[0] * s->height;
 +    if (buf_size == rawsize) {
 +        int linesize = FFALIGN(s->width,2) * 2;
-             y_plane -= s->frame.linesize[0];
++        y_plane += frame->linesize[0] * s->height;
 +        for (stream_ptr = 0; stream_ptr < rawsize; stream_ptr += linesize) {
++            y_plane -= frame->linesize[0];
 +            memcpy(y_plane, buf+stream_ptr, linesize);
 +        }
 +    } else {
 +
      /* iterate through each line in the height */
      for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
-          y_ptr < (s->height * s->frame.linesize[0]);
-          y_ptr += s->frame.linesize[0] - s->width,
-          u_ptr += s->frame.linesize[1] - s->width / 4,
-          v_ptr += s->frame.linesize[2] - s->width / 4) {
+          y_ptr < (s->height * frame->linesize[0]);
+          y_ptr += frame->linesize[0] - s->width,
+          u_ptr += frame->linesize[1] - s->width / 4,
+          v_ptr += frame->linesize[2] - s->width / 4) {
  
          /* reset predictors */
          cur_byte = buf[stream_ptr++];
  
          }
      }
 +    }
  
      *got_frame = 1;
-     *(AVFrame*)data= s->frame;
  
      return buf_size;
  }
Simple merge
@@@ -344,9 -334,9 +340,9 @@@ static int dfa_decode_frame(AVCodecCont
              pal_elems = FFMIN(chunk_size / 3, 256);
              for (i = 0; i < pal_elems; i++) {
                  s->pal[i] = bytestream2_get_be24(&gb) << 2;
 -                s->pal[i] |= (s->pal[i] >> 6) & 0x333;
 +                s->pal[i] |= 0xFFU << 24 | (s->pal[i] >> 6) & 0x30303;
              }
-             s->pic.palette_has_changed = 1;
+             frame->palette_has_changed = 1;
          } else if (chunk_type <= 9) {
              if (decoder[chunk_type - 2](&gb, s->frame_buf, avctx->width, avctx->height)) {
                  av_log(avctx, AV_LOG_ERROR, "Error decoding %s chunk\n",
index a791e88,0000000..aa158bf
mode 100644,000000..100644
--- /dev/null
@@@ -1,1935 -1,0 +1,1940 @@@
-             s->avctx->release_buffer(s->avctx, &s->all_frames[i].avframe);
 +/*
 + * Copyright (C) 2007 Marco Gerards <marco@gnu.org>
 + * Copyright (C) 2009 David Conrad
 + * Copyright (C) 2011 Jordi Ortiz
 + *
 + * 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
 + * Dirac Decoder
 + * @author Marco Gerards <marco@gnu.org>, David Conrad, Jordi Ortiz <nenjordi@gmail.com>
 + */
 +
 +#include "avcodec.h"
 +#include "dsputil.h"
 +#include "get_bits.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "golomb.h"
 +#include "dirac_arith.h"
 +#include "mpeg12data.h"
 +#include "dirac_dwt.h"
 +#include "dirac.h"
 +#include "diracdsp.h"
 +#include "videodsp.h" // for ff_emulated_edge_mc_8
 +
 +/**
 + * The spec limits the number of wavelet decompositions to 4 for both
 + * level 1 (VC-2) and 128 (long-gop default).
 + * 5 decompositions is the maximum before >16-bit buffers are needed.
 + * Schroedinger allows this for DD 9,7 and 13,7 wavelets only, limiting
 + * the others to 4 decompositions (or 3 for the fidelity filter).
 + *
 + * We use this instead of MAX_DECOMPOSITIONS to save some memory.
 + */
 +#define MAX_DWT_LEVELS 5
 +
 +/**
 + * The spec limits this to 3 for frame coding, but in practice can be as high as 6
 + */
 +#define MAX_REFERENCE_FRAMES 8
 +#define MAX_DELAY 5         /* limit for main profile for frame coding (TODO: field coding) */
 +#define MAX_FRAMES (MAX_REFERENCE_FRAMES + MAX_DELAY + 1)
 +#define MAX_QUANT 68        /* max quant for VC-2 */
 +#define MAX_BLOCKSIZE 32    /* maximum xblen/yblen we support */
 +
 +/**
 + * DiracBlock->ref flags, if set then the block does MC from the given ref
 + */
 +#define DIRAC_REF_MASK_REF1   1
 +#define DIRAC_REF_MASK_REF2   2
 +#define DIRAC_REF_MASK_GLOBAL 4
 +
 +/**
 + * Value of Picture.reference when Picture is not a reference picture, but
 + * is held for delayed output.
 + */
 +#define DELAYED_PIC_REF 4
 +
 +#define ff_emulated_edge_mc ff_emulated_edge_mc_8 /* Fix: change the calls to this function regarding bit depth */
 +
 +#define CALC_PADDING(size, depth)                       \
 +    (((size + (1 << depth) - 1) >> depth) << depth)
 +
 +#define DIVRNDUP(a, b) (((a) + (b) - 1) / (b))
 +
 +typedef struct {
 +    AVFrame avframe;
 +    int interpolated[3];    /* 1 if hpel[] is valid */
 +    uint8_t *hpel[3][4];
 +    uint8_t *hpel_base[3][4];
 +} DiracFrame;
 +
 +typedef struct {
 +    union {
 +        int16_t mv[2][2];
 +        int16_t dc[3];
 +    } u; /* anonymous unions aren't in C99 :( */
 +    uint8_t ref;
 +} DiracBlock;
 +
 +typedef struct SubBand {
 +    int level;
 +    int orientation;
 +    int stride;
 +    int width;
 +    int height;
 +    int quant;
 +    IDWTELEM *ibuf;
 +    struct SubBand *parent;
 +
 +    /* for low delay */
 +    unsigned length;
 +    const uint8_t *coeff_data;
 +} SubBand;
 +
 +typedef struct Plane {
 +    int width;
 +    int height;
 +    int stride;
 +
 +    int idwt_width;
 +    int idwt_height;
 +    int idwt_stride;
 +    IDWTELEM *idwt_buf;
 +    IDWTELEM *idwt_buf_base;
 +    IDWTELEM *idwt_tmp;
 +
 +    /* block length */
 +    uint8_t xblen;
 +    uint8_t yblen;
 +    /* block separation (block n+1 starts after this many pixels in block n) */
 +    uint8_t xbsep;
 +    uint8_t ybsep;
 +    /* amount of overspill on each edge (half of the overlap between blocks) */
 +    uint8_t xoffset;
 +    uint8_t yoffset;
 +
 +    SubBand band[MAX_DWT_LEVELS][4];
 +} Plane;
 +
 +typedef struct DiracContext {
 +    AVCodecContext *avctx;
 +    DSPContext dsp;
 +    DiracDSPContext diracdsp;
 +    GetBitContext gb;
 +    dirac_source_params source;
 +    int seen_sequence_header;
 +    int frame_number;           /* number of the next frame to display       */
 +    Plane plane[3];
 +    int chroma_x_shift;
 +    int chroma_y_shift;
 +
 +    int zero_res;               /* zero residue flag                         */
 +    int is_arith;               /* whether coeffs use arith or golomb coding */
 +    int low_delay;              /* use the low delay syntax                  */
 +    int globalmc_flag;          /* use global motion compensation            */
 +    int num_refs;               /* number of reference pictures              */
 +
 +    /* wavelet decoding */
 +    unsigned wavelet_depth;     /* depth of the IDWT                         */
 +    unsigned wavelet_idx;
 +
 +    /**
 +     * schroedinger older than 1.0.8 doesn't store
 +     * quant delta if only one codebook exists in a band
 +     */
 +    unsigned old_delta_quant;
 +    unsigned codeblock_mode;
 +
 +    struct {
 +        unsigned width;
 +        unsigned height;
 +    } codeblock[MAX_DWT_LEVELS+1];
 +
 +    struct {
 +        unsigned num_x;         /* number of horizontal slices               */
 +        unsigned num_y;         /* number of vertical slices                 */
 +        AVRational bytes;       /* average bytes per slice                   */
 +        uint8_t quant[MAX_DWT_LEVELS][4]; /* [DIRAC_STD] E.1 */
 +    } lowdelay;
 +
 +    struct {
 +        int pan_tilt[2];        /* pan/tilt vector                           */
 +        int zrs[2][2];          /* zoom/rotate/shear matrix                  */
 +        int perspective[2];     /* perspective vector                        */
 +        unsigned zrs_exp;
 +        unsigned perspective_exp;
 +    } globalmc[2];
 +
 +    /* motion compensation */
 +    uint8_t mv_precision;       /* [DIRAC_STD] REFS_WT_PRECISION             */
 +    int16_t weight[2];          /* [DIRAC_STD] REF1_WT and REF2_WT           */
 +    unsigned weight_log2denom;  /* [DIRAC_STD] REFS_WT_PRECISION             */
 +
 +    int blwidth;                /* number of blocks (horizontally)           */
 +    int blheight;               /* number of blocks (vertically)             */
 +    int sbwidth;                /* number of superblocks (horizontally)      */
 +    int sbheight;               /* number of superblocks (vertically)        */
 +
 +    uint8_t *sbsplit;
 +    DiracBlock *blmotion;
 +
 +    uint8_t *edge_emu_buffer[4];
 +    uint8_t *edge_emu_buffer_base;
 +
 +    uint16_t *mctmp;            /* buffer holding the MC data multipled by OBMC weights */
 +    uint8_t *mcscratch;
 +
 +    DECLARE_ALIGNED(16, uint8_t, obmc_weight)[3][MAX_BLOCKSIZE*MAX_BLOCKSIZE];
 +
 +    void (*put_pixels_tab[4])(uint8_t *dst, const uint8_t *src[5], int stride, int h);
 +    void (*avg_pixels_tab[4])(uint8_t *dst, const uint8_t *src[5], int stride, int h);
 +    void (*add_obmc)(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen);
 +    dirac_weight_func weight_func;
 +    dirac_biweight_func biweight_func;
 +
 +    DiracFrame *current_picture;
 +    DiracFrame *ref_pics[2];
 +
 +    DiracFrame *ref_frames[MAX_REFERENCE_FRAMES+1];
 +    DiracFrame *delay_frames[MAX_DELAY+1];
 +    DiracFrame all_frames[MAX_FRAMES];
 +} DiracContext;
 +
 +/**
 + * Dirac Specification ->
 + * Parse code values. 9.6.1 Table 9.1
 + */
 +enum dirac_parse_code {
 +    pc_seq_header         = 0x00,
 +    pc_eos                = 0x10,
 +    pc_aux_data           = 0x20,
 +    pc_padding            = 0x30,
 +};
 +
 +enum dirac_subband {
 +    subband_ll = 0,
 +    subband_hl = 1,
 +    subband_lh = 2,
 +    subband_hh = 3
 +};
 +
 +static const uint8_t default_qmat[][4][4] = {
 +    { { 5,  3,  3,  0}, { 0,  4,  4,  1}, { 0,  5,  5,  2}, { 0,  6,  6,  3} },
 +    { { 4,  2,  2,  0}, { 0,  4,  4,  2}, { 0,  5,  5,  3}, { 0,  7,  7,  5} },
 +    { { 5,  3,  3,  0}, { 0,  4,  4,  1}, { 0,  5,  5,  2}, { 0,  6,  6,  3} },
 +    { { 8,  4,  4,  0}, { 0,  4,  4,  0}, { 0,  4,  4,  0}, { 0,  4,  4,  0} },
 +    { { 8,  4,  4,  0}, { 0,  4,  4,  0}, { 0,  4,  4,  0}, { 0,  4,  4,  0} },
 +    { { 0,  4,  4,  8}, { 0,  8,  8, 12}, { 0, 13, 13, 17}, { 0, 17, 17, 21} },
 +    { { 3,  1,  1,  0}, { 0,  4,  4,  2}, { 0,  6,  6,  5}, { 0,  9,  9,  7} },
 +};
 +
 +static const int qscale_tab[MAX_QUANT+1] = {
 +    4,     5,     6,     7,     8,    10,    11,    13,
 +    16,    19,    23,    27,    32,    38,    45,    54,
 +    64,    76,    91,   108,   128,   152,   181,   215,
 +    256,   304,   362,   431,   512,   609,   724,   861,
 +    1024,  1218,  1448,  1722,  2048,  2435,  2896,  3444,
 +    4096,  4871,  5793,  6889,  8192,  9742, 11585, 13777,
 +    16384, 19484, 23170, 27554, 32768, 38968, 46341, 55109,
 +    65536, 77936
 +};
 +
 +static const int qoffset_intra_tab[MAX_QUANT+1] = {
 +    1,     2,     3,     4,     4,     5,     6,     7,
 +    8,    10,    12,    14,    16,    19,    23,    27,
 +    32,    38,    46,    54,    64,    76,    91,   108,
 +    128,   152,   181,   216,   256,   305,   362,   431,
 +    512,   609,   724,   861,  1024,  1218,  1448,  1722,
 +    2048,  2436,  2897,  3445,  4096,  4871,  5793,  6889,
 +    8192,  9742, 11585, 13777, 16384, 19484, 23171, 27555,
 +    32768, 38968
 +};
 +
 +static const int qoffset_inter_tab[MAX_QUANT+1] = {
 +    1,     2,     2,     3,     3,     4,     4,     5,
 +    6,     7,     9,    10,    12,    14,    17,    20,
 +    24,    29,    34,    41,    48,    57,    68,    81,
 +    96,   114,   136,   162,   192,   228,   272,   323,
 +    384,   457,   543,   646,   768,   913,  1086,  1292,
 +    1536,  1827,  2172,  2583,  3072,  3653,  4344,  5166,
 +    6144,  7307,  8689, 10333, 12288, 14613, 17378, 20666,
 +    24576, 29226
 +};
 +
 +/* magic number division by 3 from schroedinger */
 +static inline int divide3(int x)
 +{
 +    return ((x+1)*21845 + 10922) >> 16;
 +}
 +
 +static DiracFrame *remove_frame(DiracFrame *framelist[], int picnum)
 +{
 +    DiracFrame *remove_pic = NULL;
 +    int i, remove_idx = -1;
 +
 +    for (i = 0; framelist[i]; i++)
 +        if (framelist[i]->avframe.display_picture_number == picnum) {
 +            remove_pic = framelist[i];
 +            remove_idx = i;
 +        }
 +
 +    if (remove_pic)
 +        for (i = remove_idx; framelist[i]; i++)
 +            framelist[i] = framelist[i+1];
 +
 +    return remove_pic;
 +}
 +
 +static int add_frame(DiracFrame *framelist[], int maxframes, DiracFrame *frame)
 +{
 +    int i;
 +    for (i = 0; i < maxframes; i++)
 +        if (!framelist[i]) {
 +            framelist[i] = frame;
 +            return 0;
 +        }
 +    return -1;
 +}
 +
 +static int alloc_sequence_buffers(DiracContext *s)
 +{
 +    int sbwidth  = DIVRNDUP(s->source.width,  4);
 +    int sbheight = DIVRNDUP(s->source.height, 4);
 +    int i, w, h, top_padding;
 +
 +    /* todo: think more about this / use or set Plane here */
 +    for (i = 0; i < 3; i++) {
 +        int max_xblen = MAX_BLOCKSIZE >> (i ? s->chroma_x_shift : 0);
 +        int max_yblen = MAX_BLOCKSIZE >> (i ? s->chroma_y_shift : 0);
 +        w = s->source.width  >> (i ? s->chroma_x_shift : 0);
 +        h = s->source.height >> (i ? s->chroma_y_shift : 0);
 +
 +        /* we allocate the max we support here since num decompositions can
 +         * change from frame to frame. Stride is aligned to 16 for SIMD, and
 +         * 1<<MAX_DWT_LEVELS top padding to avoid if(y>0) in arith decoding
 +         * MAX_BLOCKSIZE padding for MC: blocks can spill up to half of that
 +         * on each side */
 +        top_padding = FFMAX(1<<MAX_DWT_LEVELS, max_yblen/2);
 +        w = FFALIGN(CALC_PADDING(w, MAX_DWT_LEVELS), 8); /* FIXME: Should this be 16 for SSE??? */
 +        h = top_padding + CALC_PADDING(h, MAX_DWT_LEVELS) + max_yblen/2;
 +
 +        s->plane[i].idwt_buf_base = av_mallocz((w+max_xblen)*h * sizeof(IDWTELEM));
 +        s->plane[i].idwt_tmp      = av_malloc((w+16) * sizeof(IDWTELEM));
 +        s->plane[i].idwt_buf      = s->plane[i].idwt_buf_base + top_padding*w;
 +        if (!s->plane[i].idwt_buf_base || !s->plane[i].idwt_tmp)
 +            return AVERROR(ENOMEM);
 +    }
 +
 +    w = s->source.width;
 +    h = s->source.height;
 +
 +    /* fixme: allocate using real stride here */
 +    s->sbsplit  = av_malloc(sbwidth * sbheight);
 +    s->blmotion = av_malloc(sbwidth * sbheight * 16 * sizeof(*s->blmotion));
 +    s->edge_emu_buffer_base = av_malloc((w+64)*MAX_BLOCKSIZE);
 +
 +    s->mctmp     = av_malloc((w+64+MAX_BLOCKSIZE) * (h+MAX_BLOCKSIZE) * sizeof(*s->mctmp));
 +    s->mcscratch = av_malloc((w+64)*MAX_BLOCKSIZE);
 +
 +    if (!s->sbsplit || !s->blmotion || !s->mctmp || !s->mcscratch)
 +        return AVERROR(ENOMEM);
 +    return 0;
 +}
 +
 +static void free_sequence_buffers(DiracContext *s)
 +{
 +    int i, j, k;
 +
 +    for (i = 0; i < MAX_FRAMES; i++) {
 +        if (s->all_frames[i].avframe.data[0]) {
-                     ff_get_buffer(s->avctx, &s->ref_pics[i]->avframe);
++            av_frame_unref(&s->all_frames[i].avframe);
 +            memset(s->all_frames[i].interpolated, 0, sizeof(s->all_frames[i].interpolated));
 +        }
 +
 +        for (j = 0; j < 3; j++)
 +            for (k = 1; k < 4; k++)
 +                av_freep(&s->all_frames[i].hpel_base[j][k]);
 +    }
 +
 +    memset(s->ref_frames, 0, sizeof(s->ref_frames));
 +    memset(s->delay_frames, 0, sizeof(s->delay_frames));
 +
 +    for (i = 0; i < 3; i++) {
 +        av_freep(&s->plane[i].idwt_buf_base);
 +        av_freep(&s->plane[i].idwt_tmp);
 +    }
 +
 +    av_freep(&s->sbsplit);
 +    av_freep(&s->blmotion);
 +    av_freep(&s->edge_emu_buffer_base);
 +
 +    av_freep(&s->mctmp);
 +    av_freep(&s->mcscratch);
 +}
 +
 +static av_cold int dirac_decode_init(AVCodecContext *avctx)
 +{
 +    DiracContext *s = avctx->priv_data;
 +    s->avctx = avctx;
 +    s->frame_number = -1;
 +
 +    if (avctx->flags&CODEC_FLAG_EMU_EDGE) {
 +        av_log(avctx, AV_LOG_ERROR, "Edge emulation not supported!\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    ff_dsputil_init(&s->dsp, avctx);
 +    ff_diracdsp_init(&s->diracdsp);
 +
 +    return 0;
 +}
 +
 +static void dirac_decode_flush(AVCodecContext *avctx)
 +{
 +    DiracContext *s = avctx->priv_data;
 +    free_sequence_buffers(s);
 +    s->seen_sequence_header = 0;
 +    s->frame_number = -1;
 +}
 +
 +static av_cold int dirac_decode_end(AVCodecContext *avctx)
 +{
 +    dirac_decode_flush(avctx);
 +    return 0;
 +}
 +
 +#define SIGN_CTX(x) (CTX_SIGN_ZERO + ((x) > 0) - ((x) < 0))
 +
 +static inline void coeff_unpack_arith(DiracArith *c, int qfactor, int qoffset,
 +                                      SubBand *b, IDWTELEM *buf, int x, int y)
 +{
 +    int coeff, sign;
 +    int sign_pred = 0;
 +    int pred_ctx = CTX_ZPZN_F1;
 +
 +    /* Check if the parent subband has a 0 in the corresponding position */
 +    if (b->parent)
 +        pred_ctx += !!b->parent->ibuf[b->parent->stride * (y>>1) + (x>>1)] << 1;
 +
 +    if (b->orientation == subband_hl)
 +        sign_pred = buf[-b->stride];
 +
 +    /* Determine if the pixel has only zeros in its neighbourhood */
 +    if (x) {
 +        pred_ctx += !(buf[-1] | buf[-b->stride] | buf[-1-b->stride]);
 +        if (b->orientation == subband_lh)
 +            sign_pred = buf[-1];
 +    } else {
 +        pred_ctx += !buf[-b->stride];
 +    }
 +
 +    coeff = dirac_get_arith_uint(c, pred_ctx, CTX_COEFF_DATA);
 +    if (coeff) {
 +        coeff = (coeff * qfactor + qoffset + 2) >> 2;
 +        sign  = dirac_get_arith_bit(c, SIGN_CTX(sign_pred));
 +        coeff = (coeff ^ -sign) + sign;
 +    }
 +    *buf = coeff;
 +}
 +
 +static inline int coeff_unpack_golomb(GetBitContext *gb, int qfactor, int qoffset)
 +{
 +    int sign, coeff;
 +
 +    coeff = svq3_get_ue_golomb(gb);
 +    if (coeff) {
 +        coeff = (coeff * qfactor + qoffset + 2) >> 2;
 +        sign  = get_bits1(gb);
 +        coeff = (coeff ^ -sign) + sign;
 +    }
 +    return coeff;
 +}
 +
 +/**
 + * Decode the coeffs in the rectangle defined by left, right, top, bottom
 + * [DIRAC_STD] 13.4.3.2 Codeblock unpacking loop. codeblock()
 + */
 +static inline void codeblock(DiracContext *s, SubBand *b,
 +                             GetBitContext *gb, DiracArith *c,
 +                             int left, int right, int top, int bottom,
 +                             int blockcnt_one, int is_arith)
 +{
 +    int x, y, zero_block;
 +    int qoffset, qfactor;
 +    IDWTELEM *buf;
 +
 +    /* check for any coded coefficients in this codeblock */
 +    if (!blockcnt_one) {
 +        if (is_arith)
 +            zero_block = dirac_get_arith_bit(c, CTX_ZERO_BLOCK);
 +        else
 +            zero_block = get_bits1(gb);
 +
 +        if (zero_block)
 +            return;
 +    }
 +
 +    if (s->codeblock_mode && !(s->old_delta_quant && blockcnt_one)) {
 +        int quant = b->quant;
 +        if (is_arith)
 +            quant += dirac_get_arith_int(c, CTX_DELTA_Q_F, CTX_DELTA_Q_DATA);
 +        else
 +            quant += dirac_get_se_golomb(gb);
 +        if (quant < 0) {
 +            av_log(s->avctx, AV_LOG_ERROR, "Invalid quant\n");
 +            return;
 +        }
 +        b->quant = quant;
 +    }
 +
 +    b->quant = FFMIN(b->quant, MAX_QUANT);
 +
 +    qfactor = qscale_tab[b->quant];
 +    /* TODO: context pointer? */
 +    if (!s->num_refs)
 +        qoffset = qoffset_intra_tab[b->quant];
 +    else
 +        qoffset = qoffset_inter_tab[b->quant];
 +
 +    buf = b->ibuf + top * b->stride;
 +    for (y = top; y < bottom; y++) {
 +        for (x = left; x < right; x++) {
 +            /* [DIRAC_STD] 13.4.4 Subband coefficients. coeff_unpack() */
 +            if (is_arith)
 +                coeff_unpack_arith(c, qfactor, qoffset, b, buf+x, x, y);
 +            else
 +                buf[x] = coeff_unpack_golomb(gb, qfactor, qoffset);
 +        }
 +        buf += b->stride;
 +    }
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 13.3 intra_dc_prediction(band)
 + */
 +static inline void intra_dc_prediction(SubBand *b)
 +{
 +    IDWTELEM *buf = b->ibuf;
 +    int x, y;
 +
 +    for (x = 1; x < b->width; x++)
 +        buf[x] += buf[x-1];
 +    buf += b->stride;
 +
 +    for (y = 1; y < b->height; y++) {
 +        buf[0] += buf[-b->stride];
 +
 +        for (x = 1; x < b->width; x++) {
 +            int pred = buf[x - 1] + buf[x - b->stride] + buf[x - b->stride-1];
 +            buf[x]  += divide3(pred);
 +        }
 +        buf += b->stride;
 +    }
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 13.4.2 Non-skipped subbands.  subband_coeffs()
 + */
 +static av_always_inline void decode_subband_internal(DiracContext *s, SubBand *b, int is_arith)
 +{
 +    int cb_x, cb_y, left, right, top, bottom;
 +    DiracArith c;
 +    GetBitContext gb;
 +    int cb_width  = s->codeblock[b->level + (b->orientation != subband_ll)].width;
 +    int cb_height = s->codeblock[b->level + (b->orientation != subband_ll)].height;
 +    int blockcnt_one = (cb_width + cb_height) == 2;
 +
 +    if (!b->length)
 +        return;
 +
 +    init_get_bits(&gb, b->coeff_data, b->length*8);
 +
 +    if (is_arith)
 +        ff_dirac_init_arith_decoder(&c, &gb, b->length);
 +
 +    top = 0;
 +    for (cb_y = 0; cb_y < cb_height; cb_y++) {
 +        bottom = (b->height * (cb_y+1)) / cb_height;
 +        left = 0;
 +        for (cb_x = 0; cb_x < cb_width; cb_x++) {
 +            right = (b->width * (cb_x+1)) / cb_width;
 +            codeblock(s, b, &gb, &c, left, right, top, bottom, blockcnt_one, is_arith);
 +            left = right;
 +        }
 +        top = bottom;
 +    }
 +
 +    if (b->orientation == subband_ll && s->num_refs == 0)
 +        intra_dc_prediction(b);
 +}
 +
 +static int decode_subband_arith(AVCodecContext *avctx, void *b)
 +{
 +    DiracContext *s = avctx->priv_data;
 +    decode_subband_internal(s, b, 1);
 +    return 0;
 +}
 +
 +static int decode_subband_golomb(AVCodecContext *avctx, void *arg)
 +{
 +    DiracContext *s = avctx->priv_data;
 +    SubBand **b     = arg;
 +    decode_subband_internal(s, *b, 0);
 +    return 0;
 +}
 +
 +/**
 + * Dirac Specification ->
 + * [DIRAC_STD] 13.4.1 core_transform_data()
 + */
 +static void decode_component(DiracContext *s, int comp)
 +{
 +    AVCodecContext *avctx = s->avctx;
 +    SubBand *bands[3*MAX_DWT_LEVELS+1];
 +    enum dirac_subband orientation;
 +    int level, num_bands = 0;
 +
 +    /* Unpack all subbands at all levels. */
 +    for (level = 0; level < s->wavelet_depth; level++) {
 +        for (orientation = !!level; orientation < 4; orientation++) {
 +            SubBand *b = &s->plane[comp].band[level][orientation];
 +            bands[num_bands++] = b;
 +
 +            align_get_bits(&s->gb);
 +            /* [DIRAC_STD] 13.4.2 subband() */
 +            b->length = svq3_get_ue_golomb(&s->gb);
 +            if (b->length) {
 +                b->quant = svq3_get_ue_golomb(&s->gb);
 +                align_get_bits(&s->gb);
 +                b->coeff_data = s->gb.buffer + get_bits_count(&s->gb)/8;
 +                b->length = FFMIN(b->length, FFMAX(get_bits_left(&s->gb)/8, 0));
 +                skip_bits_long(&s->gb, b->length*8);
 +            }
 +        }
 +        /* arithmetic coding has inter-level dependencies, so we can only execute one level at a time */
 +        if (s->is_arith)
 +            avctx->execute(avctx, decode_subband_arith, &s->plane[comp].band[level][!!level],
 +                           NULL, 4-!!level, sizeof(SubBand));
 +    }
 +    /* golomb coding has no inter-level dependencies, so we can execute all subbands in parallel */
 +    if (!s->is_arith)
 +        avctx->execute(avctx, decode_subband_golomb, bands, NULL, num_bands, sizeof(SubBand*));
 +}
 +
 +/* [DIRAC_STD] 13.5.5.2 Luma slice subband data. luma_slice_band(level,orient,sx,sy) --> if b2 == NULL */
 +/* [DIRAC_STD] 13.5.5.3 Chroma slice subband data. chroma_slice_band(level,orient,sx,sy) --> if b2 != NULL */
 +static void lowdelay_subband(DiracContext *s, GetBitContext *gb, int quant,
 +                             int slice_x, int slice_y, int bits_end,
 +                             SubBand *b1, SubBand *b2)
 +{
 +    int left   = b1->width  * slice_x    / s->lowdelay.num_x;
 +    int right  = b1->width  *(slice_x+1) / s->lowdelay.num_x;
 +    int top    = b1->height * slice_y    / s->lowdelay.num_y;
 +    int bottom = b1->height *(slice_y+1) / s->lowdelay.num_y;
 +
 +    int qfactor = qscale_tab[FFMIN(quant, MAX_QUANT)];
 +    int qoffset = qoffset_intra_tab[FFMIN(quant, MAX_QUANT)];
 +
 +    IDWTELEM *buf1 =      b1->ibuf + top * b1->stride;
 +    IDWTELEM *buf2 = b2 ? b2->ibuf + top * b2->stride : NULL;
 +    int x, y;
 +    /* we have to constantly check for overread since the spec explictly
 +       requires this, with the meaning that all remaining coeffs are set to 0 */
 +    if (get_bits_count(gb) >= bits_end)
 +        return;
 +
 +    for (y = top; y < bottom; y++) {
 +        for (x = left; x < right; x++) {
 +            buf1[x] = coeff_unpack_golomb(gb, qfactor, qoffset);
 +            if (get_bits_count(gb) >= bits_end)
 +                return;
 +            if (buf2) {
 +                buf2[x] = coeff_unpack_golomb(gb, qfactor, qoffset);
 +                if (get_bits_count(gb) >= bits_end)
 +                    return;
 +            }
 +        }
 +        buf1 += b1->stride;
 +        if (buf2)
 +            buf2 += b2->stride;
 +    }
 +}
 +
 +struct lowdelay_slice {
 +    GetBitContext gb;
 +    int slice_x;
 +    int slice_y;
 +    int bytes;
 +};
 +
 +
 +/**
 + * Dirac Specification ->
 + * 13.5.2 Slices. slice(sx,sy)
 + */
 +static int decode_lowdelay_slice(AVCodecContext *avctx, void *arg)
 +{
 +    DiracContext *s = avctx->priv_data;
 +    struct lowdelay_slice *slice = arg;
 +    GetBitContext *gb = &slice->gb;
 +    enum dirac_subband orientation;
 +    int level, quant, chroma_bits, chroma_end;
 +
 +    int quant_base  = get_bits(gb, 7); /*[DIRAC_STD] qindex */
 +    int length_bits = av_log2(8 * slice->bytes)+1;
 +    int luma_bits   = get_bits_long(gb, length_bits);
 +    int luma_end    = get_bits_count(gb) + FFMIN(luma_bits, get_bits_left(gb));
 +
 +    /* [DIRAC_STD] 13.5.5.2 luma_slice_band */
 +    for (level = 0; level < s->wavelet_depth; level++)
 +        for (orientation = !!level; orientation < 4; orientation++) {
 +            quant = FFMAX(quant_base - s->lowdelay.quant[level][orientation], 0);
 +            lowdelay_subband(s, gb, quant, slice->slice_x, slice->slice_y, luma_end,
 +                             &s->plane[0].band[level][orientation], NULL);
 +        }
 +
 +    /* consume any unused bits from luma */
 +    skip_bits_long(gb, get_bits_count(gb) - luma_end);
 +
 +    chroma_bits = 8*slice->bytes - 7 - length_bits - luma_bits;
 +    chroma_end  = get_bits_count(gb) + FFMIN(chroma_bits, get_bits_left(gb));
 +    /* [DIRAC_STD] 13.5.5.3 chroma_slice_band */
 +    for (level = 0; level < s->wavelet_depth; level++)
 +        for (orientation = !!level; orientation < 4; orientation++) {
 +            quant = FFMAX(quant_base - s->lowdelay.quant[level][orientation], 0);
 +            lowdelay_subband(s, gb, quant, slice->slice_x, slice->slice_y, chroma_end,
 +                             &s->plane[1].band[level][orientation],
 +                             &s->plane[2].band[level][orientation]);
 +        }
 +
 +    return 0;
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 13.5.1 low_delay_transform_data()
 + */
 +static void decode_lowdelay(DiracContext *s)
 +{
 +    AVCodecContext *avctx = s->avctx;
 +    int slice_x, slice_y, bytes, bufsize;
 +    const uint8_t *buf;
 +    struct lowdelay_slice *slices;
 +    int slice_num = 0;
 +
 +    slices = av_mallocz(s->lowdelay.num_x * s->lowdelay.num_y * sizeof(struct lowdelay_slice));
 +
 +    align_get_bits(&s->gb);
 +    /*[DIRAC_STD] 13.5.2 Slices. slice(sx,sy) */
 +    buf = s->gb.buffer + get_bits_count(&s->gb)/8;
 +    bufsize = get_bits_left(&s->gb);
 +
 +    for (slice_y = 0; bufsize > 0 && slice_y < s->lowdelay.num_y; slice_y++)
 +        for (slice_x = 0; bufsize > 0 && slice_x < s->lowdelay.num_x; slice_x++) {
 +            bytes = (slice_num+1) * s->lowdelay.bytes.num / s->lowdelay.bytes.den
 +                - slice_num    * s->lowdelay.bytes.num / s->lowdelay.bytes.den;
 +
 +            slices[slice_num].bytes   = bytes;
 +            slices[slice_num].slice_x = slice_x;
 +            slices[slice_num].slice_y = slice_y;
 +            init_get_bits(&slices[slice_num].gb, buf, bufsize);
 +            slice_num++;
 +
 +            buf     += bytes;
 +            bufsize -= bytes*8;
 +        }
 +
 +    avctx->execute(avctx, decode_lowdelay_slice, slices, NULL, slice_num,
 +                   sizeof(struct lowdelay_slice)); /* [DIRAC_STD] 13.5.2 Slices */
 +    intra_dc_prediction(&s->plane[0].band[0][0]);  /* [DIRAC_STD] 13.3 intra_dc_prediction() */
 +    intra_dc_prediction(&s->plane[1].band[0][0]);  /* [DIRAC_STD] 13.3 intra_dc_prediction() */
 +    intra_dc_prediction(&s->plane[2].band[0][0]);  /* [DIRAC_STD] 13.3 intra_dc_prediction() */
 +    av_free(slices);
 +}
 +
 +static void init_planes(DiracContext *s)
 +{
 +    int i, w, h, level, orientation;
 +
 +    for (i = 0; i < 3; i++) {
 +        Plane *p = &s->plane[i];
 +
 +        p->width       = s->source.width  >> (i ? s->chroma_x_shift : 0);
 +        p->height      = s->source.height >> (i ? s->chroma_y_shift : 0);
 +        p->idwt_width  = w = CALC_PADDING(p->width , s->wavelet_depth);
 +        p->idwt_height = h = CALC_PADDING(p->height, s->wavelet_depth);
 +        p->idwt_stride = FFALIGN(p->idwt_width, 8);
 +
 +        for (level = s->wavelet_depth-1; level >= 0; level--) {
 +            w = w>>1;
 +            h = h>>1;
 +            for (orientation = !!level; orientation < 4; orientation++) {
 +                SubBand *b = &p->band[level][orientation];
 +
 +                b->ibuf   = p->idwt_buf;
 +                b->level  = level;
 +                b->stride = p->idwt_stride << (s->wavelet_depth - level);
 +                b->width  = w;
 +                b->height = h;
 +                b->orientation = orientation;
 +
 +                if (orientation & 1)
 +                    b->ibuf += w;
 +                if (orientation > 1)
 +                    b->ibuf += b->stride>>1;
 +
 +                if (level)
 +                    b->parent = &p->band[level-1][orientation];
 +            }
 +        }
 +
 +        if (i > 0) {
 +            p->xblen = s->plane[0].xblen >> s->chroma_x_shift;
 +            p->yblen = s->plane[0].yblen >> s->chroma_y_shift;
 +            p->xbsep = s->plane[0].xbsep >> s->chroma_x_shift;
 +            p->ybsep = s->plane[0].ybsep >> s->chroma_y_shift;
 +        }
 +
 +        p->xoffset = (p->xblen - p->xbsep)/2;
 +        p->yoffset = (p->yblen - p->ybsep)/2;
 +    }
 +}
 +
 +/**
 + * Unpack the motion compensation parameters
 + * Dirac Specification ->
 + * 11.2 Picture prediction data. picture_prediction()
 + */
 +static int dirac_unpack_prediction_parameters(DiracContext *s)
 +{
 +    static const uint8_t default_blen[] = { 4, 12, 16, 24 };
 +    static const uint8_t default_bsep[] = { 4,  8, 12, 16 };
 +
 +    GetBitContext *gb = &s->gb;
 +    unsigned idx, ref;
 +
 +    align_get_bits(gb);
 +    /* [DIRAC_STD] 11.2.2 Block parameters. block_parameters() */
 +    /* Luma and Chroma are equal. 11.2.3 */
 +    idx = svq3_get_ue_golomb(gb); /* [DIRAC_STD] index */
 +
 +    if (idx > 4) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Block prediction index too high\n");
 +        return -1;
 +    }
 +
 +    if (idx == 0) {
 +        s->plane[0].xblen = svq3_get_ue_golomb(gb);
 +        s->plane[0].yblen = svq3_get_ue_golomb(gb);
 +        s->plane[0].xbsep = svq3_get_ue_golomb(gb);
 +        s->plane[0].ybsep = svq3_get_ue_golomb(gb);
 +    } else {
 +        /*[DIRAC_STD] preset_block_params(index). Table 11.1 */
 +        s->plane[0].xblen = default_blen[idx-1];
 +        s->plane[0].yblen = default_blen[idx-1];
 +        s->plane[0].xbsep = default_bsep[idx-1];
 +        s->plane[0].ybsep = default_bsep[idx-1];
 +    }
 +    /*[DIRAC_STD] 11.2.4 motion_data_dimensions()
 +      Calculated in function dirac_unpack_block_motion_data */
 +
 +    if (!s->plane[0].xbsep || !s->plane[0].ybsep || s->plane[0].xbsep < s->plane[0].xblen/2 || s->plane[0].ybsep < s->plane[0].yblen/2) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Block separation too small\n");
 +        return -1;
 +    }
 +    if (s->plane[0].xbsep > s->plane[0].xblen || s->plane[0].ybsep > s->plane[0].yblen) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Block separation greater than size\n");
 +        return -1;
 +    }
 +    if (FFMAX(s->plane[0].xblen, s->plane[0].yblen) > MAX_BLOCKSIZE) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Unsupported large block size\n");
 +        return -1;
 +    }
 +
 +    /*[DIRAC_STD] 11.2.5 Motion vector precision. motion_vector_precision()
 +      Read motion vector precision */
 +    s->mv_precision = svq3_get_ue_golomb(gb);
 +    if (s->mv_precision > 3) {
 +        av_log(s->avctx, AV_LOG_ERROR, "MV precision finer than eighth-pel\n");
 +        return -1;
 +    }
 +
 +    /*[DIRAC_STD] 11.2.6 Global motion. global_motion()
 +      Read the global motion compensation parameters */
 +    s->globalmc_flag = get_bits1(gb);
 +    if (s->globalmc_flag) {
 +        memset(s->globalmc, 0, sizeof(s->globalmc));
 +        /* [DIRAC_STD] pan_tilt(gparams) */
 +        for (ref = 0; ref < s->num_refs; ref++) {
 +            if (get_bits1(gb)) {
 +                s->globalmc[ref].pan_tilt[0] = dirac_get_se_golomb(gb);
 +                s->globalmc[ref].pan_tilt[1] = dirac_get_se_golomb(gb);
 +            }
 +            /* [DIRAC_STD] zoom_rotate_shear(gparams)
 +               zoom/rotation/shear parameters */
 +            if (get_bits1(gb)) {
 +                s->globalmc[ref].zrs_exp   = svq3_get_ue_golomb(gb);
 +                s->globalmc[ref].zrs[0][0] = dirac_get_se_golomb(gb);
 +                s->globalmc[ref].zrs[0][1] = dirac_get_se_golomb(gb);
 +                s->globalmc[ref].zrs[1][0] = dirac_get_se_golomb(gb);
 +                s->globalmc[ref].zrs[1][1] = dirac_get_se_golomb(gb);
 +            } else {
 +                s->globalmc[ref].zrs[0][0] = 1;
 +                s->globalmc[ref].zrs[1][1] = 1;
 +            }
 +            /* [DIRAC_STD] perspective(gparams) */
 +            if (get_bits1(gb)) {
 +                s->globalmc[ref].perspective_exp = svq3_get_ue_golomb(gb);
 +                s->globalmc[ref].perspective[0]  = dirac_get_se_golomb(gb);
 +                s->globalmc[ref].perspective[1]  = dirac_get_se_golomb(gb);
 +            }
 +        }
 +    }
 +
 +    /*[DIRAC_STD] 11.2.7 Picture prediction mode. prediction_mode()
 +      Picture prediction mode, not currently used. */
 +    if (svq3_get_ue_golomb(gb)) {
 +        av_log(s->avctx, AV_LOG_ERROR, "Unknown picture prediction mode\n");
 +        return -1;
 +    }
 +
 +    /* [DIRAC_STD] 11.2.8 Reference picture weight. reference_picture_weights()
 +       just data read, weight calculation will be done later on. */
 +    s->weight_log2denom = 1;
 +    s->weight[0]        = 1;
 +    s->weight[1]        = 1;
 +
 +    if (get_bits1(gb)) {
 +        s->weight_log2denom = svq3_get_ue_golomb(gb);
 +        s->weight[0] = dirac_get_se_golomb(gb);
 +        if (s->num_refs == 2)
 +            s->weight[1] = dirac_get_se_golomb(gb);
 +    }
 +    return 0;
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 11.3 Wavelet transform data. wavelet_transform()
 + */
 +static int dirac_unpack_idwt_params(DiracContext *s)
 +{
 +    GetBitContext *gb = &s->gb;
 +    int i, level;
 +    unsigned tmp;
 +
 +#define CHECKEDREAD(dst, cond, errmsg) \
 +    tmp = svq3_get_ue_golomb(gb); \
 +    if (cond) { \
 +        av_log(s->avctx, AV_LOG_ERROR, errmsg); \
 +        return -1; \
 +    }\
 +    dst = tmp;
 +
 +    align_get_bits(gb);
 +
 +    s->zero_res = s->num_refs ? get_bits1(gb) : 0;
 +    if (s->zero_res)
 +        return 0;
 +
 +    /*[DIRAC_STD] 11.3.1 Transform parameters. transform_parameters() */
 +    CHECKEDREAD(s->wavelet_idx, tmp > 6, "wavelet_idx is too big\n")
 +
 +    CHECKEDREAD(s->wavelet_depth, tmp > MAX_DWT_LEVELS || tmp < 1, "invalid number of DWT decompositions\n")
 +
 +    if (!s->low_delay) {
 +        /* Codeblock parameters (core syntax only) */
 +        if (get_bits1(gb)) {
 +            for (i = 0; i <= s->wavelet_depth; i++) {
 +                CHECKEDREAD(s->codeblock[i].width , tmp < 1, "codeblock width invalid\n")
 +                CHECKEDREAD(s->codeblock[i].height, tmp < 1, "codeblock height invalid\n")
 +            }
 +
 +            CHECKEDREAD(s->codeblock_mode, tmp > 1, "unknown codeblock mode\n")
 +        } else
 +            for (i = 0; i <= s->wavelet_depth; i++)
 +                s->codeblock[i].width = s->codeblock[i].height = 1;
 +    } else {
 +        /* Slice parameters + quantization matrix*/
 +        /*[DIRAC_STD] 11.3.4 Slice coding Parameters (low delay syntax only). slice_parameters() */
 +        s->lowdelay.num_x     = svq3_get_ue_golomb(gb);
 +        s->lowdelay.num_y     = svq3_get_ue_golomb(gb);
 +        s->lowdelay.bytes.num = svq3_get_ue_golomb(gb);
 +        s->lowdelay.bytes.den = svq3_get_ue_golomb(gb);
 +
 +        if (s->lowdelay.bytes.den <= 0) {
 +            av_log(s->avctx,AV_LOG_ERROR,"Invalid lowdelay.bytes.den\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        /* [DIRAC_STD] 11.3.5 Quantisation matrices (low-delay syntax). quant_matrix() */
 +        if (get_bits1(gb)) {
 +            av_log(s->avctx,AV_LOG_DEBUG,"Low Delay: Has Custom Quantization Matrix!\n");
 +            /* custom quantization matrix */
 +            s->lowdelay.quant[0][0] = svq3_get_ue_golomb(gb);
 +            for (level = 0; level < s->wavelet_depth; level++) {
 +                s->lowdelay.quant[level][1] = svq3_get_ue_golomb(gb);
 +                s->lowdelay.quant[level][2] = svq3_get_ue_golomb(gb);
 +                s->lowdelay.quant[level][3] = svq3_get_ue_golomb(gb);
 +            }
 +        } else {
 +            if (s->wavelet_depth > 4) {
 +                av_log(s->avctx,AV_LOG_ERROR,"Mandatory custom low delay matrix missing for depth %d\n", s->wavelet_depth);
 +                return AVERROR_INVALIDDATA;
 +            }
 +            /* default quantization matrix */
 +            for (level = 0; level < s->wavelet_depth; level++)
 +                for (i = 0; i < 4; i++) {
 +                    s->lowdelay.quant[level][i] = default_qmat[s->wavelet_idx][level][i];
 +                    /* haar with no shift differs for different depths */
 +                    if (s->wavelet_idx == 3)
 +                        s->lowdelay.quant[level][i] += 4*(s->wavelet_depth-1 - level);
 +                }
 +        }
 +    }
 +    return 0;
 +}
 +
 +static inline int pred_sbsplit(uint8_t *sbsplit, int stride, int x, int y)
 +{
 +    static const uint8_t avgsplit[7] = { 0, 0, 1, 1, 1, 2, 2 };
 +
 +    if (!(x|y))
 +        return 0;
 +    else if (!y)
 +        return sbsplit[-1];
 +    else if (!x)
 +        return sbsplit[-stride];
 +
 +    return avgsplit[sbsplit[-1] + sbsplit[-stride] + sbsplit[-stride-1]];
 +}
 +
 +static inline int pred_block_mode(DiracBlock *block, int stride, int x, int y, int refmask)
 +{
 +    int pred;
 +
 +    if (!(x|y))
 +        return 0;
 +    else if (!y)
 +        return block[-1].ref & refmask;
 +    else if (!x)
 +        return block[-stride].ref & refmask;
 +
 +    /* return the majority */
 +    pred = (block[-1].ref & refmask) + (block[-stride].ref & refmask) + (block[-stride-1].ref & refmask);
 +    return (pred >> 1) & refmask;
 +}
 +
 +static inline void pred_block_dc(DiracBlock *block, int stride, int x, int y)
 +{
 +    int i, n = 0;
 +
 +    memset(block->u.dc, 0, sizeof(block->u.dc));
 +
 +    if (x && !(block[-1].ref & 3)) {
 +        for (i = 0; i < 3; i++)
 +            block->u.dc[i] += block[-1].u.dc[i];
 +        n++;
 +    }
 +
 +    if (y && !(block[-stride].ref & 3)) {
 +        for (i = 0; i < 3; i++)
 +            block->u.dc[i] += block[-stride].u.dc[i];
 +        n++;
 +    }
 +
 +    if (x && y && !(block[-1-stride].ref & 3)) {
 +        for (i = 0; i < 3; i++)
 +            block->u.dc[i] += block[-1-stride].u.dc[i];
 +        n++;
 +    }
 +
 +    if (n == 2) {
 +        for (i = 0; i < 3; i++)
 +            block->u.dc[i] = (block->u.dc[i]+1)>>1;
 +    } else if (n == 3) {
 +        for (i = 0; i < 3; i++)
 +            block->u.dc[i] = divide3(block->u.dc[i]);
 +    }
 +}
 +
 +static inline void pred_mv(DiracBlock *block, int stride, int x, int y, int ref)
 +{
 +    int16_t *pred[3];
 +    int refmask = ref+1;
 +    int mask = refmask | DIRAC_REF_MASK_GLOBAL; /*  exclude gmc blocks */
 +    int n = 0;
 +
 +    if (x && (block[-1].ref & mask) == refmask)
 +        pred[n++] = block[-1].u.mv[ref];
 +
 +    if (y && (block[-stride].ref & mask) == refmask)
 +        pred[n++] = block[-stride].u.mv[ref];
 +
 +    if (x && y && (block[-stride-1].ref & mask) == refmask)
 +        pred[n++] = block[-stride-1].u.mv[ref];
 +
 +    switch (n) {
 +    case 0:
 +        block->u.mv[ref][0] = 0;
 +        block->u.mv[ref][1] = 0;
 +        break;
 +    case 1:
 +        block->u.mv[ref][0] = pred[0][0];
 +        block->u.mv[ref][1] = pred[0][1];
 +        break;
 +    case 2:
 +        block->u.mv[ref][0] = (pred[0][0] + pred[1][0] + 1) >> 1;
 +        block->u.mv[ref][1] = (pred[0][1] + pred[1][1] + 1) >> 1;
 +        break;
 +    case 3:
 +        block->u.mv[ref][0] = mid_pred(pred[0][0], pred[1][0], pred[2][0]);
 +        block->u.mv[ref][1] = mid_pred(pred[0][1], pred[1][1], pred[2][1]);
 +        break;
 +    }
 +}
 +
 +static void global_mv(DiracContext *s, DiracBlock *block, int x, int y, int ref)
 +{
 +    int ez      = s->globalmc[ref].zrs_exp;
 +    int ep      = s->globalmc[ref].perspective_exp;
 +    int (*A)[2] = s->globalmc[ref].zrs;
 +    int *b      = s->globalmc[ref].pan_tilt;
 +    int *c      = s->globalmc[ref].perspective;
 +
 +    int m       = (1<<ep) - (c[0]*x + c[1]*y);
 +    int mx      = m * ((A[0][0] * x + A[0][1]*y) + (1<<ez) * b[0]);
 +    int my      = m * ((A[1][0] * x + A[1][1]*y) + (1<<ez) * b[1]);
 +
 +    block->u.mv[ref][0] = (mx + (1<<(ez+ep))) >> (ez+ep);
 +    block->u.mv[ref][1] = (my + (1<<(ez+ep))) >> (ez+ep);
 +}
 +
 +static void decode_block_params(DiracContext *s, DiracArith arith[8], DiracBlock *block,
 +                                int stride, int x, int y)
 +{
 +    int i;
 +
 +    block->ref  = pred_block_mode(block, stride, x, y, DIRAC_REF_MASK_REF1);
 +    block->ref ^= dirac_get_arith_bit(arith, CTX_PMODE_REF1);
 +
 +    if (s->num_refs == 2) {
 +        block->ref |= pred_block_mode(block, stride, x, y, DIRAC_REF_MASK_REF2);
 +        block->ref ^= dirac_get_arith_bit(arith, CTX_PMODE_REF2) << 1;
 +    }
 +
 +    if (!block->ref) {
 +        pred_block_dc(block, stride, x, y);
 +        for (i = 0; i < 3; i++)
 +            block->u.dc[i] += dirac_get_arith_int(arith+1+i, CTX_DC_F1, CTX_DC_DATA);
 +        return;
 +    }
 +
 +    if (s->globalmc_flag) {
 +        block->ref |= pred_block_mode(block, stride, x, y, DIRAC_REF_MASK_GLOBAL);
 +        block->ref ^= dirac_get_arith_bit(arith, CTX_GLOBAL_BLOCK) << 2;
 +    }
 +
 +    for (i = 0; i < s->num_refs; i++)
 +        if (block->ref & (i+1)) {
 +            if (block->ref & DIRAC_REF_MASK_GLOBAL) {
 +                global_mv(s, block, x, y, i);
 +            } else {
 +                pred_mv(block, stride, x, y, i);
 +                block->u.mv[i][0] += dirac_get_arith_int(arith + 4 + 2 * i, CTX_MV_F1, CTX_MV_DATA);
 +                block->u.mv[i][1] += dirac_get_arith_int(arith + 5 + 2 * i, CTX_MV_F1, CTX_MV_DATA);
 +            }
 +        }
 +}
 +
 +/**
 + * Copies the current block to the other blocks covered by the current superblock split mode
 + */
 +static void propagate_block_data(DiracBlock *block, int stride, int size)
 +{
 +    int x, y;
 +    DiracBlock *dst = block;
 +
 +    for (x = 1; x < size; x++)
 +        dst[x] = *block;
 +
 +    for (y = 1; y < size; y++) {
 +        dst += stride;
 +        for (x = 0; x < size; x++)
 +            dst[x] = *block;
 +    }
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 12. Block motion data syntax
 + */
 +static int dirac_unpack_block_motion_data(DiracContext *s)
 +{
 +    GetBitContext *gb = &s->gb;
 +    uint8_t *sbsplit = s->sbsplit;
 +    int i, x, y, q, p;
 +    DiracArith arith[8];
 +
 +    align_get_bits(gb);
 +
 +    /* [DIRAC_STD] 11.2.4 and 12.2.1 Number of blocks and superblocks */
 +    s->sbwidth  = DIVRNDUP(s->source.width,  4*s->plane[0].xbsep);
 +    s->sbheight = DIVRNDUP(s->source.height, 4*s->plane[0].ybsep);
 +    s->blwidth  = 4 * s->sbwidth;
 +    s->blheight = 4 * s->sbheight;
 +
 +    /* [DIRAC_STD] 12.3.1 Superblock splitting modes. superblock_split_modes()
 +       decode superblock split modes */
 +    ff_dirac_init_arith_decoder(arith, gb, svq3_get_ue_golomb(gb));     /* svq3_get_ue_golomb(gb) is the length */
 +    for (y = 0; y < s->sbheight; y++) {
 +        for (x = 0; x < s->sbwidth; x++) {
 +            unsigned int split  = dirac_get_arith_uint(arith, CTX_SB_F1, CTX_SB_DATA);
 +            if (split > 2)
 +                return -1;
 +            sbsplit[x] = (split + pred_sbsplit(sbsplit+x, s->sbwidth, x, y)) % 3;
 +        }
 +        sbsplit += s->sbwidth;
 +    }
 +
 +    /* setup arith decoding */
 +    ff_dirac_init_arith_decoder(arith, gb, svq3_get_ue_golomb(gb));
 +    for (i = 0; i < s->num_refs; i++) {
 +        ff_dirac_init_arith_decoder(arith + 4 + 2 * i, gb, svq3_get_ue_golomb(gb));
 +        ff_dirac_init_arith_decoder(arith + 5 + 2 * i, gb, svq3_get_ue_golomb(gb));
 +    }
 +    for (i = 0; i < 3; i++)
 +        ff_dirac_init_arith_decoder(arith+1+i, gb, svq3_get_ue_golomb(gb));
 +
 +    for (y = 0; y < s->sbheight; y++)
 +        for (x = 0; x < s->sbwidth; x++) {
 +            int blkcnt = 1 << s->sbsplit[y * s->sbwidth + x];
 +            int step   = 4 >> s->sbsplit[y * s->sbwidth + x];
 +
 +            for (q = 0; q < blkcnt; q++)
 +                for (p = 0; p < blkcnt; p++) {
 +                    int bx = 4 * x + p*step;
 +                    int by = 4 * y + q*step;
 +                    DiracBlock *block = &s->blmotion[by*s->blwidth + bx];
 +                    decode_block_params(s, arith, block, s->blwidth, bx, by);
 +                    propagate_block_data(block, s->blwidth, step);
 +                }
 +        }
 +
 +    return 0;
 +}
 +
 +static int weight(int i, int blen, int offset)
 +{
 +#define ROLLOFF(i) offset == 1 ? ((i) ? 5 : 3) :        \
 +    (1 + (6*(i) + offset - 1) / (2*offset - 1))
 +
 +    if (i < 2*offset)
 +        return ROLLOFF(i);
 +    else if (i > blen-1 - 2*offset)
 +        return ROLLOFF(blen-1 - i);
 +    return 8;
 +}
 +
 +static void init_obmc_weight_row(Plane *p, uint8_t *obmc_weight, int stride,
 +                                 int left, int right, int wy)
 +{
 +    int x;
 +    for (x = 0; left && x < p->xblen >> 1; x++)
 +        obmc_weight[x] = wy*8;
 +    for (; x < p->xblen >> right; x++)
 +        obmc_weight[x] = wy*weight(x, p->xblen, p->xoffset);
 +    for (; x < p->xblen; x++)
 +        obmc_weight[x] = wy*8;
 +    for (; x < stride; x++)
 +        obmc_weight[x] = 0;
 +}
 +
 +static void init_obmc_weight(Plane *p, uint8_t *obmc_weight, int stride,
 +                             int left, int right, int top, int bottom)
 +{
 +    int y;
 +    for (y = 0; top && y < p->yblen >> 1; y++) {
 +        init_obmc_weight_row(p, obmc_weight, stride, left, right, 8);
 +        obmc_weight += stride;
 +    }
 +    for (; y < p->yblen >> bottom; y++) {
 +        int wy = weight(y, p->yblen, p->yoffset);
 +        init_obmc_weight_row(p, obmc_weight, stride, left, right, wy);
 +        obmc_weight += stride;
 +    }
 +    for (; y < p->yblen; y++) {
 +        init_obmc_weight_row(p, obmc_weight, stride, left, right, 8);
 +        obmc_weight += stride;
 +    }
 +}
 +
 +static void init_obmc_weights(DiracContext *s, Plane *p, int by)
 +{
 +    int top = !by;
 +    int bottom = by == s->blheight-1;
 +
 +    /* don't bother re-initing for rows 2 to blheight-2, the weights don't change */
 +    if (top || bottom || by == 1) {
 +        init_obmc_weight(p, s->obmc_weight[0], MAX_BLOCKSIZE, 1, 0, top, bottom);
 +        init_obmc_weight(p, s->obmc_weight[1], MAX_BLOCKSIZE, 0, 0, top, bottom);
 +        init_obmc_weight(p, s->obmc_weight[2], MAX_BLOCKSIZE, 0, 1, top, bottom);
 +    }
 +}
 +
 +static const uint8_t epel_weights[4][4][4] = {
 +    {{ 16,  0,  0,  0 },
 +     { 12,  4,  0,  0 },
 +     {  8,  8,  0,  0 },
 +     {  4, 12,  0,  0 }},
 +    {{ 12,  0,  4,  0 },
 +     {  9,  3,  3,  1 },
 +     {  6,  6,  2,  2 },
 +     {  3,  9,  1,  3 }},
 +    {{  8,  0,  8,  0 },
 +     {  6,  2,  6,  2 },
 +     {  4,  4,  4,  4 },
 +     {  2,  6,  2,  6 }},
 +    {{  4,  0, 12,  0 },
 +     {  3,  1,  9,  3 },
 +     {  2,  2,  6,  6 },
 +     {  1,  3,  3,  9 }}
 +};
 +
 +/**
 + * For block x,y, determine which of the hpel planes to do bilinear
 + * interpolation from and set src[] to the location in each hpel plane
 + * to MC from.
 + *
 + * @return the index of the put_dirac_pixels_tab function to use
 + *  0 for 1 plane (fpel,hpel), 1 for 2 planes (qpel), 2 for 4 planes (qpel), and 3 for epel
 + */
 +static int mc_subpel(DiracContext *s, DiracBlock *block, const uint8_t *src[5],
 +                     int x, int y, int ref, int plane)
 +{
 +    Plane *p = &s->plane[plane];
 +    uint8_t **ref_hpel = s->ref_pics[ref]->hpel[plane];
 +    int motion_x = block->u.mv[ref][0];
 +    int motion_y = block->u.mv[ref][1];
 +    int mx, my, i, epel, nplanes = 0;
 +
 +    if (plane) {
 +        motion_x >>= s->chroma_x_shift;
 +        motion_y >>= s->chroma_y_shift;
 +    }
 +
 +    mx         = motion_x & ~(-1 << s->mv_precision);
 +    my         = motion_y & ~(-1 << s->mv_precision);
 +    motion_x >>= s->mv_precision;
 +    motion_y >>= s->mv_precision;
 +    /* normalize subpel coordinates to epel */
 +    /* TODO: template this function? */
 +    mx      <<= 3 - s->mv_precision;
 +    my      <<= 3 - s->mv_precision;
 +
 +    x += motion_x;
 +    y += motion_y;
 +    epel = (mx|my)&1;
 +
 +    /* hpel position */
 +    if (!((mx|my)&3)) {
 +        nplanes = 1;
 +        src[0] = ref_hpel[(my>>1)+(mx>>2)] + y*p->stride + x;
 +    } else {
 +        /* qpel or epel */
 +        nplanes = 4;
 +        for (i = 0; i < 4; i++)
 +            src[i] = ref_hpel[i] + y*p->stride + x;
 +
 +        /* if we're interpolating in the right/bottom halves, adjust the planes as needed
 +           we increment x/y because the edge changes for half of the pixels */
 +        if (mx > 4) {
 +            src[0] += 1;
 +            src[2] += 1;
 +            x++;
 +        }
 +        if (my > 4) {
 +            src[0] += p->stride;
 +            src[1] += p->stride;
 +            y++;
 +        }
 +
 +        /* hpel planes are:
 +           [0]: F  [1]: H
 +           [2]: V  [3]: C */
 +        if (!epel) {
 +            /* check if we really only need 2 planes since either mx or my is
 +               a hpel position. (epel weights of 0 handle this there) */
 +            if (!(mx&3)) {
 +                /* mx == 0: average [0] and [2]
 +                   mx == 4: average [1] and [3] */
 +                src[!mx] = src[2 + !!mx];
 +                nplanes = 2;
 +            } else if (!(my&3)) {
 +                src[0] = src[(my>>1)  ];
 +                src[1] = src[(my>>1)+1];
 +                nplanes = 2;
 +            }
 +        } else {
 +            /* adjust the ordering if needed so the weights work */
 +            if (mx > 4) {
 +                FFSWAP(const uint8_t *, src[0], src[1]);
 +                FFSWAP(const uint8_t *, src[2], src[3]);
 +            }
 +            if (my > 4) {
 +                FFSWAP(const uint8_t *, src[0], src[2]);
 +                FFSWAP(const uint8_t *, src[1], src[3]);
 +            }
 +            src[4] = epel_weights[my&3][mx&3];
 +        }
 +    }
 +
 +    /* fixme: v/h _edge_pos */
 +    if (x + p->xblen > p->width +EDGE_WIDTH/2 ||
 +        y + p->yblen > p->height+EDGE_WIDTH/2 ||
 +        x < 0 || y < 0) {
 +        for (i = 0; i < nplanes; i++) {
 +            ff_emulated_edge_mc(s->edge_emu_buffer[i], src[i], p->stride,
 +                                p->xblen, p->yblen, x, y,
 +                                p->width+EDGE_WIDTH/2, p->height+EDGE_WIDTH/2);
 +            src[i] = s->edge_emu_buffer[i];
 +        }
 +    }
 +    return (nplanes>>1) + epel;
 +}
 +
 +static void add_dc(uint16_t *dst, int dc, int stride,
 +                   uint8_t *obmc_weight, int xblen, int yblen)
 +{
 +    int x, y;
 +    dc += 128;
 +
 +    for (y = 0; y < yblen; y++) {
 +        for (x = 0; x < xblen; x += 2) {
 +            dst[x  ] += dc * obmc_weight[x  ];
 +            dst[x+1] += dc * obmc_weight[x+1];
 +        }
 +        dst          += stride;
 +        obmc_weight  += MAX_BLOCKSIZE;
 +    }
 +}
 +
 +static void block_mc(DiracContext *s, DiracBlock *block,
 +                     uint16_t *mctmp, uint8_t *obmc_weight,
 +                     int plane, int dstx, int dsty)
 +{
 +    Plane *p = &s->plane[plane];
 +    const uint8_t *src[5];
 +    int idx;
 +
 +    switch (block->ref&3) {
 +    case 0: /* DC */
 +        add_dc(mctmp, block->u.dc[plane], p->stride, obmc_weight, p->xblen, p->yblen);
 +        return;
 +    case 1:
 +    case 2:
 +        idx = mc_subpel(s, block, src, dstx, dsty, (block->ref&3)-1, plane);
 +        s->put_pixels_tab[idx](s->mcscratch, src, p->stride, p->yblen);
 +        if (s->weight_func)
 +            s->weight_func(s->mcscratch, p->stride, s->weight_log2denom,
 +                           s->weight[0] + s->weight[1], p->yblen);
 +        break;
 +    case 3:
 +        idx = mc_subpel(s, block, src, dstx, dsty, 0, plane);
 +        s->put_pixels_tab[idx](s->mcscratch, src, p->stride, p->yblen);
 +        idx = mc_subpel(s, block, src, dstx, dsty, 1, plane);
 +        if (s->biweight_func) {
 +            /* fixme: +32 is a quick hack */
 +            s->put_pixels_tab[idx](s->mcscratch + 32, src, p->stride, p->yblen);
 +            s->biweight_func(s->mcscratch, s->mcscratch+32, p->stride, s->weight_log2denom,
 +                             s->weight[0], s->weight[1], p->yblen);
 +        } else
 +            s->avg_pixels_tab[idx](s->mcscratch, src, p->stride, p->yblen);
 +        break;
 +    }
 +    s->add_obmc(mctmp, s->mcscratch, p->stride, obmc_weight, p->yblen);
 +}
 +
 +static void mc_row(DiracContext *s, DiracBlock *block, uint16_t *mctmp, int plane, int dsty)
 +{
 +    Plane *p = &s->plane[plane];
 +    int x, dstx = p->xbsep - p->xoffset;
 +
 +    block_mc(s, block, mctmp, s->obmc_weight[0], plane, -p->xoffset, dsty);
 +    mctmp += p->xbsep;
 +
 +    for (x = 1; x < s->blwidth-1; x++) {
 +        block_mc(s, block+x, mctmp, s->obmc_weight[1], plane, dstx, dsty);
 +        dstx  += p->xbsep;
 +        mctmp += p->xbsep;
 +    }
 +    block_mc(s, block+x, mctmp, s->obmc_weight[2], plane, dstx, dsty);
 +}
 +
 +static void select_dsp_funcs(DiracContext *s, int width, int height, int xblen, int yblen)
 +{
 +    int idx = 0;
 +    if (xblen > 8)
 +        idx = 1;
 +    if (xblen > 16)
 +        idx = 2;
 +
 +    memcpy(s->put_pixels_tab, s->diracdsp.put_dirac_pixels_tab[idx], sizeof(s->put_pixels_tab));
 +    memcpy(s->avg_pixels_tab, s->diracdsp.avg_dirac_pixels_tab[idx], sizeof(s->avg_pixels_tab));
 +    s->add_obmc = s->diracdsp.add_dirac_obmc[idx];
 +    if (s->weight_log2denom > 1 || s->weight[0] != 1 || s->weight[1] != 1) {
 +        s->weight_func   = s->diracdsp.weight_dirac_pixels_tab[idx];
 +        s->biweight_func = s->diracdsp.biweight_dirac_pixels_tab[idx];
 +    } else {
 +        s->weight_func   = NULL;
 +        s->biweight_func = NULL;
 +    }
 +}
 +
 +static void interpolate_refplane(DiracContext *s, DiracFrame *ref, int plane, int width, int height)
 +{
 +    /* chroma allocates an edge of 8 when subsampled
 +       which for 4:2:2 means an h edge of 16 and v edge of 8
 +       just use 8 for everything for the moment */
 +    int i, edge = EDGE_WIDTH/2;
 +
 +    ref->hpel[plane][0] = ref->avframe.data[plane];
 +    s->dsp.draw_edges(ref->hpel[plane][0], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM); /* EDGE_TOP | EDGE_BOTTOM values just copied to make it build, this needs to be ensured */
 +
 +    /* no need for hpel if we only have fpel vectors */
 +    if (!s->mv_precision)
 +        return;
 +
 +    for (i = 1; i < 4; i++) {
 +        if (!ref->hpel_base[plane][i])
 +            ref->hpel_base[plane][i] = av_malloc((height+2*edge) * ref->avframe.linesize[plane] + 32);
 +        /* we need to be 16-byte aligned even for chroma */
 +        ref->hpel[plane][i] = ref->hpel_base[plane][i] + edge*ref->avframe.linesize[plane] + 16;
 +    }
 +
 +    if (!ref->interpolated[plane]) {
 +        s->diracdsp.dirac_hpel_filter(ref->hpel[plane][1], ref->hpel[plane][2],
 +                                      ref->hpel[plane][3], ref->hpel[plane][0],
 +                                      ref->avframe.linesize[plane], width, height);
 +        s->dsp.draw_edges(ref->hpel[plane][1], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM);
 +        s->dsp.draw_edges(ref->hpel[plane][2], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM);
 +        s->dsp.draw_edges(ref->hpel[plane][3], ref->avframe.linesize[plane], width, height, edge, edge, EDGE_TOP | EDGE_BOTTOM);
 +    }
 +    ref->interpolated[plane] = 1;
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 13.0 Transform data syntax. transform_data()
 + */
 +static int dirac_decode_frame_internal(DiracContext *s)
 +{
 +    DWTContext d;
 +    int y, i, comp, dsty;
 +
 +    if (s->low_delay) {
 +        /* [DIRAC_STD] 13.5.1 low_delay_transform_data() */
 +        for (comp = 0; comp < 3; comp++) {
 +            Plane *p = &s->plane[comp];
 +            memset(p->idwt_buf, 0, p->idwt_stride * p->idwt_height * sizeof(IDWTELEM));
 +        }
 +        if (!s->zero_res)
 +            decode_lowdelay(s);
 +    }
 +
 +    for (comp = 0; comp < 3; comp++) {
 +        Plane *p       = &s->plane[comp];
 +        uint8_t *frame = s->current_picture->avframe.data[comp];
 +
 +        /* FIXME: small resolutions */
 +        for (i = 0; i < 4; i++)
 +            s->edge_emu_buffer[i] = s->edge_emu_buffer_base + i*FFALIGN(p->width, 16);
 +
 +        if (!s->zero_res && !s->low_delay)
 +        {
 +            memset(p->idwt_buf, 0, p->idwt_stride * p->idwt_height * sizeof(IDWTELEM));
 +            decode_component(s, comp); /* [DIRAC_STD] 13.4.1 core_transform_data() */
 +        }
 +        if (ff_spatial_idwt_init2(&d, p->idwt_buf, p->idwt_width, p->idwt_height, p->idwt_stride,
 +                                  s->wavelet_idx+2, s->wavelet_depth, p->idwt_tmp))
 +            return -1;
 +
 +        if (!s->num_refs) { /* intra */
 +            for (y = 0; y < p->height; y += 16) {
 +                ff_spatial_idwt_slice2(&d, y+16); /* decode */
 +                s->diracdsp.put_signed_rect_clamped(frame + y*p->stride, p->stride,
 +                                                    p->idwt_buf + y*p->idwt_stride, p->idwt_stride, p->width, 16);
 +            }
 +        } else { /* inter */
 +            int rowheight = p->ybsep*p->stride;
 +
 +            select_dsp_funcs(s, p->width, p->height, p->xblen, p->yblen);
 +
 +            for (i = 0; i < s->num_refs; i++)
 +                interpolate_refplane(s, s->ref_pics[i], comp, p->width, p->height);
 +
 +            memset(s->mctmp, 0, 4*p->yoffset*p->stride);
 +
 +            dsty = -p->yoffset;
 +            for (y = 0; y < s->blheight; y++) {
 +                int h     = 0,
 +                    start = FFMAX(dsty, 0);
 +                uint16_t *mctmp    = s->mctmp + y*rowheight;
 +                DiracBlock *blocks = s->blmotion + y*s->blwidth;
 +
 +                init_obmc_weights(s, p, y);
 +
 +                if (y == s->blheight-1 || start+p->ybsep > p->height)
 +                    h = p->height - start;
 +                else
 +                    h = p->ybsep - (start - dsty);
 +                if (h < 0)
 +                    break;
 +
 +                memset(mctmp+2*p->yoffset*p->stride, 0, 2*rowheight);
 +                mc_row(s, blocks, mctmp, comp, dsty);
 +
 +                mctmp += (start - dsty)*p->stride + p->xoffset;
 +                ff_spatial_idwt_slice2(&d, start + h); /* decode */
 +                s->diracdsp.add_rect_clamped(frame + start*p->stride, mctmp, p->stride,
 +                                             p->idwt_buf + start*p->idwt_stride, p->idwt_stride, p->width, h);
 +
 +                dsty += p->ybsep;
 +            }
 +        }
 +    }
 +
 +
 +    return 0;
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 11.1.1 Picture Header. picture_header()
 + */
 +static int dirac_decode_picture_header(DiracContext *s)
 +{
 +    int retire, picnum;
 +    int i, j, refnum, refdist;
 +    GetBitContext *gb = &s->gb;
 +
 +    /* [DIRAC_STD] 11.1.1 Picture Header. picture_header() PICTURE_NUM */
 +    picnum = s->current_picture->avframe.display_picture_number = get_bits_long(gb, 32);
 +
 +
 +    av_log(s->avctx,AV_LOG_DEBUG,"PICTURE_NUM: %d\n",picnum);
 +
 +    /* if this is the first keyframe after a sequence header, start our
 +       reordering from here */
 +    if (s->frame_number < 0)
 +        s->frame_number = picnum;
 +
 +    s->ref_pics[0] = s->ref_pics[1] = NULL;
 +    for (i = 0; i < s->num_refs; i++) {
 +        refnum = picnum + dirac_get_se_golomb(gb);
 +        refdist = INT_MAX;
 +
 +        /* find the closest reference to the one we want */
 +        /* Jordi: this is needed if the referenced picture hasn't yet arrived */
 +        for (j = 0; j < MAX_REFERENCE_FRAMES && refdist; j++)
 +            if (s->ref_frames[j]
 +                && FFABS(s->ref_frames[j]->avframe.display_picture_number - refnum) < refdist) {
 +                s->ref_pics[i] = s->ref_frames[j];
 +                refdist = FFABS(s->ref_frames[j]->avframe.display_picture_number - refnum);
 +            }
 +
 +        if (!s->ref_pics[i] || refdist)
 +            av_log(s->avctx, AV_LOG_DEBUG, "Reference not found\n");
 +
 +        /* if there were no references at all, allocate one */
 +        if (!s->ref_pics[i])
 +            for (j = 0; j < MAX_FRAMES; j++)
 +                if (!s->all_frames[j].avframe.data[0]) {
 +                    s->ref_pics[i] = &s->all_frames[j];
-         *(AVFrame *)picture = out->avframe;
++                    ff_get_buffer(s->avctx, &s->ref_pics[i]->avframe, AV_GET_BUFFER_FLAG_REF);
 +                    break;
 +                }
 +    }
 +
 +    /* retire the reference frames that are not used anymore */
 +    if (s->current_picture->avframe.reference) {
 +        retire = picnum + dirac_get_se_golomb(gb);
 +        if (retire != picnum) {
 +            DiracFrame *retire_pic = remove_frame(s->ref_frames, retire);
 +
 +            if (retire_pic)
 +                retire_pic->avframe.reference &= DELAYED_PIC_REF;
 +            else
 +                av_log(s->avctx, AV_LOG_DEBUG, "Frame to retire not found\n");
 +        }
 +
 +        /* if reference array is full, remove the oldest as per the spec */
 +        while (add_frame(s->ref_frames, MAX_REFERENCE_FRAMES, s->current_picture)) {
 +            av_log(s->avctx, AV_LOG_ERROR, "Reference frame overflow\n");
 +            remove_frame(s->ref_frames, s->ref_frames[0]->avframe.display_picture_number)->avframe.reference &= DELAYED_PIC_REF;
 +        }
 +    }
 +
 +    if (s->num_refs) {
 +        if (dirac_unpack_prediction_parameters(s))  /* [DIRAC_STD] 11.2 Picture Prediction Data. picture_prediction() */
 +            return -1;
 +        if (dirac_unpack_block_motion_data(s))      /* [DIRAC_STD] 12. Block motion data syntax                       */
 +            return -1;
 +    }
 +    if (dirac_unpack_idwt_params(s))                /* [DIRAC_STD] 11.3 Wavelet transform data                        */
 +        return -1;
 +
 +    init_planes(s);
 +    return 0;
 +}
 +
 +static int get_delayed_pic(DiracContext *s, AVFrame *picture, int *got_frame)
 +{
 +    DiracFrame *out = s->delay_frames[0];
 +    int i, out_idx  = 0;
++    int ret;
 +
 +    /* find frame with lowest picture number */
 +    for (i = 1; s->delay_frames[i]; i++)
 +        if (s->delay_frames[i]->avframe.display_picture_number < out->avframe.display_picture_number) {
 +            out     = s->delay_frames[i];
 +            out_idx = i;
 +        }
 +
 +    for (i = out_idx; s->delay_frames[i]; i++)
 +        s->delay_frames[i] = s->delay_frames[i+1];
 +
 +    if (out) {
 +        out->avframe.reference ^= DELAYED_PIC_REF;
 +        *got_frame = 1;
-         if (ff_get_buffer(avctx, &pic->avframe) < 0) {
++        if((ret = av_frame_ref(picture, &out->avframe)) < 0)
++            return ret;
 +    }
 +
 +    return 0;
 +}
 +
 +/**
 + * Dirac Specification ->
 + * 9.6 Parse Info Header Syntax. parse_info()
 + * 4 byte start code + byte parse code + 4 byte size + 4 byte previous size
 + */
 +#define DATA_UNIT_HEADER_SIZE 13
 +
 +/* [DIRAC_STD] dirac_decode_data_unit makes reference to the while defined in 9.3
 +   inside the function parse_sequence() */
 +static int dirac_decode_data_unit(AVCodecContext *avctx, const uint8_t *buf, int size)
 +{
 +    DiracContext *s   = avctx->priv_data;
 +    DiracFrame *pic   = NULL;
 +    int i, parse_code = buf[4];
 +    unsigned tmp;
 +
 +    if (size < DATA_UNIT_HEADER_SIZE)
 +        return -1;
 +
 +    init_get_bits(&s->gb, &buf[13], 8*(size - DATA_UNIT_HEADER_SIZE));
 +
 +    if (parse_code == pc_seq_header) {
 +        if (s->seen_sequence_header)
 +            return 0;
 +
 +        /* [DIRAC_STD] 10. Sequence header */
 +        if (avpriv_dirac_parse_sequence_header(avctx, &s->gb, &s->source))
 +            return -1;
 +
 +        avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift);
 +
 +        if (alloc_sequence_buffers(s))
 +            return -1;
 +
 +        s->seen_sequence_header = 1;
 +    } else if (parse_code == pc_eos) { /* [DIRAC_STD] End of Sequence */
 +        free_sequence_buffers(s);
 +        s->seen_sequence_header = 0;
 +    } else if (parse_code == pc_aux_data) {
 +        if (buf[13] == 1) {     /* encoder implementation/version */
 +            int ver[3];
 +            /* versions older than 1.0.8 don't store quant delta for
 +               subbands with only one codeblock */
 +            if (sscanf(buf+14, "Schroedinger %d.%d.%d", ver, ver+1, ver+2) == 3)
 +                if (ver[0] == 1 && ver[1] == 0 && ver[2] <= 7)
 +                    s->old_delta_quant = 1;
 +        }
 +    } else if (parse_code & 0x8) {  /* picture data unit */
 +        if (!s->seen_sequence_header) {
 +            av_log(avctx, AV_LOG_DEBUG, "Dropping frame without sequence header\n");
 +            return -1;
 +        }
 +
 +        /* find an unused frame */
 +        for (i = 0; i < MAX_FRAMES; i++)
 +            if (s->all_frames[i].avframe.data[0] == NULL)
 +                pic = &s->all_frames[i];
 +        if (!pic) {
 +            av_log(avctx, AV_LOG_ERROR, "framelist full\n");
 +            return -1;
 +        }
 +
 +        avcodec_get_frame_defaults(&pic->avframe);
 +
 +        /* [DIRAC_STD] Defined in 9.6.1 ... */
 +        tmp            =  parse_code & 0x03;                   /* [DIRAC_STD] num_refs()      */
 +        if (tmp > 2) {
 +            av_log(avctx, AV_LOG_ERROR, "num_refs of 3\n");
 +            return -1;
 +        }
 +        s->num_refs    = tmp;
 +        s->is_arith    = (parse_code & 0x48) == 0x08;          /* [DIRAC_STD] using_ac()      */
 +        s->low_delay   = (parse_code & 0x88) == 0x88;          /* [DIRAC_STD] is_low_delay()  */
 +        pic->avframe.reference = (parse_code & 0x0C) == 0x0C;  /* [DIRAC_STD]  is_reference() */
 +        pic->avframe.key_frame = s->num_refs == 0;             /* [DIRAC_STD] is_intra()      */
 +        pic->avframe.pict_type = s->num_refs + 1;              /* Definition of AVPictureType in avutil.h */
 +
-             avctx->release_buffer(avctx, &s->all_frames[i].avframe);
++        if (ff_get_buffer(avctx, &pic->avframe, (parse_code & 0x0C) == 0x0C ? AV_GET_BUFFER_FLAG_REF : 0) < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +            return -1;
 +        }
 +        s->current_picture = pic;
 +        s->plane[0].stride = pic->avframe.linesize[0];
 +        s->plane[1].stride = pic->avframe.linesize[1];
 +        s->plane[2].stride = pic->avframe.linesize[2];
 +
 +        /* [DIRAC_STD] 11.1 Picture parse. picture_parse() */
 +        if (dirac_decode_picture_header(s))
 +            return -1;
 +
 +        /* [DIRAC_STD] 13.0 Transform data syntax. transform_data() */
 +        if (dirac_decode_frame_internal(s))
 +            return -1;
 +    }
 +    return 0;
 +}
 +
 +static int dirac_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt)
 +{
 +    DiracContext *s     = avctx->priv_data;
 +    DiracFrame *picture = data;
 +    uint8_t *buf        = pkt->data;
 +    int buf_size        = pkt->size;
 +    int i, data_unit_size, buf_idx = 0;
++    int ret;
 +
 +    /* release unused frames */
 +    for (i = 0; i < MAX_FRAMES; i++)
 +        if (s->all_frames[i].avframe.data[0] && !s->all_frames[i].avframe.reference) {
-             *(AVFrame*)data = delayed_frame->avframe;
++            av_frame_unref(&s->all_frames[i].avframe);
 +            memset(s->all_frames[i].interpolated, 0, sizeof(s->all_frames[i].interpolated));
 +        }
 +
 +    s->current_picture = NULL;
 +    *got_frame = 0;
 +
 +    /* end of stream, so flush delayed pics */
 +    if (buf_size == 0)
 +        return get_delayed_pic(s, (AVFrame *)data, got_frame);
 +
 +    for (;;) {
 +        /*[DIRAC_STD] Here starts the code from parse_info() defined in 9.6
 +          [DIRAC_STD] PARSE_INFO_PREFIX = "BBCD" as defined in ISO/IEC 646
 +          BBCD start code search */
 +        for (; buf_idx + DATA_UNIT_HEADER_SIZE < buf_size; buf_idx++) {
 +            if (buf[buf_idx  ] == 'B' && buf[buf_idx+1] == 'B' &&
 +                buf[buf_idx+2] == 'C' && buf[buf_idx+3] == 'D')
 +                break;
 +        }
 +        /* BBCD found or end of data */
 +        if (buf_idx + DATA_UNIT_HEADER_SIZE >= buf_size)
 +            break;
 +
 +        data_unit_size = AV_RB32(buf+buf_idx+5);
 +        if (buf_idx + data_unit_size > buf_size || !data_unit_size) {
 +            if(buf_idx + data_unit_size > buf_size)
 +            av_log(s->avctx, AV_LOG_ERROR,
 +                   "Data unit with size %d is larger than input buffer, discarding\n",
 +                   data_unit_size);
 +            buf_idx += 4;
 +            continue;
 +        }
 +        /* [DIRAC_STD] dirac_decode_data_unit makes reference to the while defined in 9.3 inside the function parse_sequence() */
 +        if (dirac_decode_data_unit(avctx, buf+buf_idx, data_unit_size))
 +        {
 +            av_log(s->avctx, AV_LOG_ERROR,"Error in dirac_decode_data_unit\n");
 +            return -1;
 +        }
 +        buf_idx += data_unit_size;
 +    }
 +
 +    if (!s->current_picture)
 +        return buf_size;
 +
 +    if (s->current_picture->avframe.display_picture_number > s->frame_number) {
 +        DiracFrame *delayed_frame = remove_frame(s->delay_frames, s->frame_number);
 +
 +        s->current_picture->avframe.reference |= DELAYED_PIC_REF;
 +
 +        if (add_frame(s->delay_frames, MAX_DELAY, s->current_picture)) {
 +            int min_num = s->delay_frames[0]->avframe.display_picture_number;
 +            /* Too many delayed frames, so we display the frame with the lowest pts */
 +            av_log(avctx, AV_LOG_ERROR, "Delay frame overflow\n");
 +            delayed_frame = s->delay_frames[0];
 +
 +            for (i = 1; s->delay_frames[i]; i++)
 +                if (s->delay_frames[i]->avframe.display_picture_number < min_num)
 +                    min_num = s->delay_frames[i]->avframe.display_picture_number;
 +
 +            delayed_frame = remove_frame(s->delay_frames, min_num);
 +            add_frame(s->delay_frames, MAX_DELAY, s->current_picture);
 +        }
 +
 +        if (delayed_frame) {
 +            delayed_frame->avframe.reference ^= DELAYED_PIC_REF;
-         *(AVFrame*)data = s->current_picture->avframe;
++            if((ret=av_frame_ref(data, &delayed_frame->avframe)) < 0)
++                return ret;
 +            *got_frame = 1;
 +        }
 +    } else if (s->current_picture->avframe.display_picture_number == s->frame_number) {
 +        /* The right frame at the right time :-) */
++        if((ret=av_frame_ref(data, &s->current_picture->avframe)) < 0)
++            return ret;
 +        *got_frame = 1;
 +    }
 +
 +    if (*got_frame)
 +        s->frame_number = picture->avframe.display_picture_number + 1;
 +
 +    return buf_idx;
 +}
 +
 +AVCodec ff_dirac_decoder = {
 +    .name           = "dirac",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_DIRAC,
 +    .priv_data_size = sizeof(DiracContext),
 +    .init           = dirac_decode_init,
 +    .close          = dirac_decode_end,
 +    .decode         = dirac_decode_frame,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .flush          = dirac_decode_flush,
 +    .long_name      = NULL_IF_CONFIG_SMALL("BBC Dirac VC-2"),
 +};
@@@ -35,9 -34,8 +35,8 @@@
  
  typedef struct DNXHDContext {
      AVCodecContext *avctx;
-     AVFrame picture;
      GetBitContext gb;
 -    int cid;                            ///< compression id
 +    int64_t cid;                        ///< compression id
      unsigned int width, height;
      unsigned int mb_width, mb_height;
      uint32_t mb_scan_index[68];         /* max for 1080p */
@@@ -67,11 -62,6 +66,7 @@@ static av_cold int dnxhd_decode_init(AV
      DNXHDContext *ctx = avctx->priv_data;
  
      ctx->avctx = avctx;
-     avctx->coded_frame = &ctx->picture;
-     avcodec_get_frame_defaults(&ctx->picture);
-     ctx->picture.type = AV_PICTURE_TYPE_I;
-     ctx->picture.key_frame = 1;
 +    ctx->cid = -1;
      return 0;
  }
  
@@@ -365,6 -333,6 +362,7 @@@ static int dnxhd_decode_frame(AVCodecCo
      const uint8_t *buf = avpkt->data;
      int buf_size = avpkt->size;
      DNXHDContext *ctx = avctx->priv_data;
++    ThreadFrame frame = { .f = data };
      AVFrame *picture = data;
      int first_field = 1;
      int ret;
      avcodec_set_dimensions(avctx, ctx->width, ctx->height);
  
      if (first_field) {
-         if (ctx->picture.data[0])
-             ff_thread_release_buffer(avctx, &ctx->picture);
-         if ((ret = ff_thread_get_buffer(avctx, &ctx->picture)) < 0) {
 -        if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) {
++        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
              av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
              return ret;
          }
          goto decode_coding_unit;
      }
  
-     *picture = ctx->picture;
      *got_frame = 1;
 -    return buf_size;
 +    return avpkt->size;
  }
  
  static av_cold int dnxhd_decode_close(AVCodecContext *avctx)
@@@ -205,13 -205,10 +205,13 @@@ static int dpcm_decode_frame(AVCodecCon
          av_log(avctx, AV_LOG_ERROR, "packet is too small\n");
          return AVERROR(EINVAL);
      }
 +    if (out % avctx->channels) {
 +        av_log(avctx, AV_LOG_WARNING, "channels have differing number of samples\n");
 +    }
  
      /* get output buffer */
 -    frame->nb_samples = out / avctx->channels;
 +    frame->nb_samples = (out + avctx->channels - 1) / avctx->channels;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
@@@ -63,11 -51,10 +58,9 @@@ static int decode_frame(AVCodecContext 
                          AVPacket *avpkt)
  {
      const uint8_t *buf = avpkt->data;
 -    const uint8_t *buf_end = avpkt->data + avpkt->size;
      int buf_size       = avpkt->size;
-     DPXContext *const s = avctx->priv_data;
-     AVFrame *picture  = data;
-     AVFrame *const p = &s->picture;
+     AVFrame *const p = data;
 -    uint8_t *ptr;
 +    uint8_t *ptr[AV_NUM_DATA_POINTERS];
  
      unsigned int offset;
      int magic_num, endian;
              return AVERROR_INVALIDDATA;
      }
  
-     if (s->picture.data[0])
-         avctx->release_buffer(avctx, &s->picture);
-     if ((ret = ff_get_buffer(avctx, p)) < 0) {
 -    if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
 -        return ret;
 -    if (w != avctx->width || h != avctx->height)
 -        avcodec_set_dimensions(avctx, w, h);
+     if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
          return AVERROR_INVALIDDATA;
      }
      switch (bits_per_color) {
 -        case 10:
 -            for (x = 0; x < avctx->height; x++) {
 -               uint16_t *dst = (uint16_t*)ptr;
 -               for (y = 0; y < avctx->width; y++) {
 -                   rgbBuffer = read32(&buf, endian);
 -                   // Read out the 10-bit colors and convert to 16-bit
 -                   *dst++ = make_16bit(rgbBuffer >> 16);
 -                   *dst++ = make_16bit(rgbBuffer >>  6);
 -                   *dst++ = make_16bit(rgbBuffer <<  4);
 -               }
 -               ptr += stride;
 +    case 10:
 +        for (x = 0; x < avctx->height; x++) {
 +            uint16_t *dst[3] = {(uint16_t*)ptr[0],
 +                                (uint16_t*)ptr[1],
 +                                (uint16_t*)ptr[2]};
 +            for (y = 0; y < avctx->width; y++) {
 +                *dst[2]++ = read10in32(&buf, &rgbBuffer,
 +                                       &n_datum, endian);
 +                *dst[0]++ = read10in32(&buf, &rgbBuffer,
 +                                       &n_datum, endian);
 +                *dst[1]++ = read10in32(&buf, &rgbBuffer,
 +                                       &n_datum, endian);
 +                // For 10 bit, ignore alpha
 +                if (elements == 4)
 +                    read10in32(&buf, &rgbBuffer,
 +                               &n_datum, endian);
              }
 -            break;
 -        case 8:
 -        case 12: // Treat 12-bit as 16-bit
 -        case 16:
 -            if (source_packet_size == target_packet_size) {
 -                for (x = 0; x < avctx->height; x++) {
 -                    memcpy(ptr, buf, target_packet_size*avctx->width);
 -                    ptr += stride;
 -                    buf += source_packet_size*avctx->width;
 -                }
 -            } else {
 -                for (x = 0; x < avctx->height; x++) {
 -                    uint8_t *dst = ptr;
 -                    for (y = 0; y < avctx->width; y++) {
 -                        memcpy(dst, buf, target_packet_size);
 -                        dst += target_packet_size;
 -                        buf += source_packet_size;
 -                    }
 -                    ptr += stride;
 -                }
 +            for (i = 0; i < 3; i++)
 +                ptr[i] += p->linesize[i];
 +        }
 +        break;
 +    case 12:
 +        for (x = 0; x < avctx->height; x++) {
 +            uint16_t *dst[3] = {(uint16_t*)ptr[0],
 +                                (uint16_t*)ptr[1],
 +                                (uint16_t*)ptr[2]};
 +            for (y = 0; y < avctx->width; y++) {
 +                *dst[2] = *((uint16_t*)buf);
 +                *dst[2] = (*dst[2] >> 4) | (*dst[2] << 12);
 +                dst[2]++;
 +                buf += 2;
 +                *dst[0] = *((uint16_t*)buf);
 +                *dst[0] = (*dst[0] >> 4) | (*dst[0] << 12);
 +                dst[0]++;
 +                buf += 2;
 +                *dst[1] = *((uint16_t*)buf);
 +                *dst[1] = (*dst[1] >> 4) | (*dst[1] << 12);
 +                dst[1]++;
 +                buf += 2;
 +                // For 12 bit, ignore alpha
 +                if (elements == 4)
 +                    buf += 2;
              }
 -            break;
 +            for (i = 0; i < 3; i++)
 +                ptr[i] += p->linesize[i];
 +        }
 +        break;
 +    case 16:
 +        elements *= 2;
 +    case 8:
 +        for (x = 0; x < avctx->height; x++) {
 +            memcpy(ptr[0], buf, elements*avctx->width);
 +            ptr[0] += p->linesize[0];
 +            buf += elements*avctx->width;
 +        }
 +        break;
      }
  
-     *picture   = s->picture;
      *got_frame = 1;
  
      return buf_size;
@@@ -305,9 -281,8 +305,8 @@@ static int cinvideo_decode_frame(AVCode
          break;
      }
  
-     cin->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     if ((res = avctx->reget_buffer(avctx, &cin->frame))) {
+     if ((res = ff_reget_buffer(avctx, &cin->frame)) < 0) {
 -        av_log(cin->avctx, AV_LOG_ERROR, "delphinecinvideo: reget_buffer() failed to allocate a frame\n");
 +        av_log(cin->avctx, AV_LOG_ERROR, "failed to allocate a frame\n");
          return res;
      }
  
  static av_cold int cinvideo_decode_end(AVCodecContext *avctx)
  {
      CinVideoContext *cin = avctx->priv_data;
 -    int i;
  
-     if (cin->frame.data[0])
-         avctx->release_buffer(avctx, &cin->frame);
+     av_frame_unref(&cin->frame);
  
 -    for (i = 0; i < 3; ++i)
 -        av_free(cin->bitmap_table[i]);
 +    destroy_buffers(cin);
  
      return 0;
  }
@@@ -361,8 -346,16 +356,8 @@@ static int dvvideo_decode_frame(AVCodec
  
      /* return image */
      *got_frame = 1;
-     *(AVFrame*)data = s->picture;
+     av_frame_move_ref(data, &s->picture);
  
 -    /* Determine the codec's sample_aspect ratio from the packet */
 -    vsc_pack = buf + 80*5 + 48 + 5;
 -    if ( *vsc_pack == dv_video_control ) {
 -        apt = buf[4] & 0x07;
 -        is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07)));
 -        avctx->sample_aspect_ratio = s->sys->sar[is16_9];
 -    }
 -
      return s->sys->frame_size;
  }
  
@@@ -192,50 -191,53 +192,51 @@@ static int decode_13(AVCodecContext *av
  
  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
  {
 -    const uint8_t *buf = avpkt->data;
 -    int buf_size = avpkt->size;
+     AVFrame *frame = data;
      DxaDecContext * const c = avctx->priv_data;
      uint8_t *outptr, *srcptr, *tmpptr;
      unsigned long dsize;
      int i, j, compr, ret;
      int stride;
 -    int orig_buf_size = buf_size;
      int pc = 0;
 +    GetByteContext gb;
  
 -    /* make the palette available on the way out */
 -    if(buf[0]=='C' && buf[1]=='M' && buf[2]=='A' && buf[3]=='P'){
 -        int r, g, b;
 +    bytestream2_init(&gb, avpkt->data, avpkt->size);
  
 -        buf += 4;
 +    /* make the palette available on the way out */
 +    if (bytestream2_peek_le32(&gb) == MKTAG('C','M','A','P')) {
 +        bytestream2_skip(&gb, 4);
          for(i = 0; i < 256; i++){
 -            r = *buf++;
 -            g = *buf++;
 -            b = *buf++;
 -            c->pal[i] = (r << 16) | (g << 8) | b;
 +            c->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&gb);
          }
          pc = 1;
 -        buf_size -= 768+4;
      }
  
-     if ((ret = ff_get_buffer(avctx, &c->pic)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
-     memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE);
-     c->pic.palette_has_changed = pc;
+     memcpy(frame->data[1], c->pal, AVPALETTE_SIZE);
+     frame->palette_has_changed = pc;
  
-     outptr = c->pic.data[0];
+     outptr = frame->data[0];
      srcptr = c->decomp_buf;
      tmpptr = c->prev.data[0];
-     stride = c->pic.linesize[0];
+     stride = frame->linesize[0];
  
 -    if(buf[0]=='N' && buf[1]=='U' && buf[2]=='L' && buf[3]=='L')
 +    if (bytestream2_get_le32(&gb) == MKTAG('N','U','L','L'))
          compr = -1;
      else
 -        compr = buf[4];
 +        compr = bytestream2_get_byte(&gb);
  
      dsize = c->dsize;
 -    if((compr != 4 && compr != -1) && uncompress(c->decomp_buf, &dsize, buf + 9, buf_size - 9) != Z_OK){
 -        av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n");
 -        return AVERROR_UNKNOWN;
 +    if (compr != 4 && compr != -1) {
 +        bytestream2_skip(&gb, 4);
 +        if (uncompress(c->decomp_buf, &dsize, avpkt->data + bytestream2_tell(&gb),
 +                       bytestream2_get_bytes_left(&gb)) != Z_OK) {
 +            av_log(avctx, AV_LOG_ERROR, "Uncompress failed!\n");
 +            return AVERROR_UNKNOWN;
 +        }
      }
      switch(compr){
      case -1:
      case 3:
      case 4:
      case 5:
-         c->pic.key_frame = !(compr & 1);
-         c->pic.pict_type = (compr & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
+         frame->key_frame = !(compr & 1);
+         frame->pict_type = (compr & 1) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
          for(j = 0; j < avctx->height; j++){
 -            if(compr & 1){
 +            if((compr & 1) && tmpptr){
                  for(i = 0; i < avctx->width; i++)
                      outptr[i] = srcptr[i] ^ tmpptr[i];
                  tmpptr += stride;
          break;
      case 12: // ScummVM coding
      case 13:
-         c->pic.key_frame = 0;
-         c->pic.pict_type = AV_PICTURE_TYPE_P;
+         frame->key_frame = 0;
+         frame->pict_type = AV_PICTURE_TYPE_P;
 +        if (!c->prev.data[0]) {
 +            av_log(avctx, AV_LOG_ERROR, "Missing reference frame\n");
 +            return AVERROR_INVALIDDATA;
 +        }
-         decode_13(avctx, c, c->pic.data[0], srcptr, c->prev.data[0]);
+         decode_13(avctx, c, frame->data[0], frame->linesize[0], srcptr, c->prev.data[0]);
          break;
      default:
 -        av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", buf[4]);
 +        av_log(avctx, AV_LOG_ERROR, "Unknown/unsupported compression type %d\n", compr);
          return AVERROR_INVALIDDATA;
      }
  
-     FFSWAP(AVFrame, c->pic, c->prev);
-     if(c->pic.data[0])
-         avctx->release_buffer(avctx, &c->pic);
+     av_frame_unref(&c->prev);
+     if ((ret = av_frame_ref(&c->prev, frame)) < 0)
+         return ret;
  
      *got_frame = 1;
-     *(AVFrame*)data = c->prev;
  
      /* always report that the buffer was completely consumed */
 -    return orig_buf_size;
 +    return avpkt->size;
  }
  
  static av_cold int decode_init(AVCodecContext *avctx)
  
      avctx->pix_fmt = AV_PIX_FMT_PAL8;
  
-     avcodec_get_frame_defaults(&c->pic);
 +    avcodec_get_frame_defaults(&c->prev);
 +
      c->dsize = avctx->width * avctx->height * 2;
 -    if((c->decomp_buf = av_malloc(c->dsize)) == NULL) {
 +    c->decomp_buf = av_malloc(c->dsize);
 +    if (!c->decomp_buf) {
          av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
          return AVERROR(ENOMEM);
      }
Simple merge
@@@ -45,12 -44,17 +44,18 @@@ typedef struct CmvContext 
  
  static av_cold int cmv_decode_init(AVCodecContext *avctx){
      CmvContext *s = avctx->priv_data;
-     avcodec_get_frame_defaults(&s->frame);
-     avcodec_get_frame_defaults(&s->last_frame);
-     avcodec_get_frame_defaults(&s->last2_frame);
 +
      s->avctx = avctx;
      avctx->pix_fmt = AV_PIX_FMT_PAL8;
+     s->last_frame  = av_frame_alloc();
+     s->last2_frame = av_frame_alloc();
+     if (!s->last_frame || !s->last2_frame) {
+         av_frame_free(&s->last_frame);
+         av_frame_free(&s->last2_frame);
+         return AVERROR(ENOMEM);
+     }
      return 0;
  }
  
@@@ -112,10 -120,9 +121,10 @@@ static void cmv_decode_inter(CmvContex
          }else{  /* inter using last frame as reference */
              int xoffset = (buf[i] & 0xF) - 7;
              int yoffset = ((buf[i] >> 4)) - 7;
-             if (s->last_frame.data[0])
-                 cmv_motcomp(s->frame.data[0], s->frame.linesize[0],
-                           s->last_frame.data[0], s->last_frame.linesize[0],
 -            cmv_motcomp(frame->data[0], frame->linesize[0],
 -                      s->last_frame->data[0], s->last_frame->linesize[0],
 -                      x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height);
++            if (s->last_frame->data[0])
++                cmv_motcomp(frame->data[0], frame->linesize[0],
++                          s->last_frame->data[0], s->last_frame->linesize[0],
 +                          x*4, y*4, xoffset, yoffset, s->avctx->width, s->avctx->height);
          }
          i++;
      }
@@@ -132,13 -139,8 +141,11 @@@ static void cmv_process_header(CmvConte
  
      s->width  = AV_RL16(&buf[4]);
      s->height = AV_RL16(&buf[6]);
 -    if (s->avctx->width!=s->width || s->avctx->height!=s->height)
 +    if (s->avctx->width!=s->width || s->avctx->height!=s->height) {
          avcodec_set_dimensions(s->avctx, s->width, s->height);
-         if (s->frame.data[0])
-             s->avctx->release_buffer(s->avctx, &s->frame);
-         if (s->last_frame.data[0])
-             s->avctx->release_buffer(s->avctx, &s->last_frame);
++        av_frame_unref(s->last_frame);
++        av_frame_unref(s->last2_frame);
 +    }
  
      s->avctx->time_base.num = 1;
      s->avctx->time_base.den = AV_RL16(&buf[10]);
@@@ -82,21 -82,15 +82,21 @@@ static inline void comp_block(MadContex
                                int j, int mv_x, int mv_y, int add)
  {
      if (j < 4) {
-         comp(t->frame.data[0] + (mb_y*16 + ((j&2)<<2))*t->frame.linesize[0] + mb_x*16 + ((j&1)<<3),
-              t->frame.linesize[0],
 +        unsigned offset = (mb_y*16 + ((j&2)<<2) + mv_y)*t->last_frame.linesize[0] + mb_x*16 + ((j&1)<<3) + mv_x;
 +        if (offset >= (t->avctx->height - 7) * t->last_frame.linesize[0] - 7)
 +            return;
 -             t->last_frame.data[0] + (mb_y*16 + ((j&2)<<2) + mv_y)*t->last_frame.linesize[0] + mb_x*16 + ((j&1)<<3) + mv_x,
+         comp(frame->data[0] + (mb_y*16 + ((j&2)<<2))*frame->linesize[0] + mb_x*16 + ((j&1)<<3),
+              frame->linesize[0],
 +             t->last_frame.data[0] + offset,
               t->last_frame.linesize[0], add);
      } else if (!(t->avctx->flags & CODEC_FLAG_GRAY)) {
          int index = j - 3;
-         comp(t->frame.data[index] + (mb_y*8)*t->frame.linesize[index] + mb_x * 8,
-              t->frame.linesize[index],
 +        unsigned offset = (mb_y * 8 + (mv_y/2))*t->last_frame.linesize[index] + mb_x * 8 + (mv_x/2);
 +        if (offset >= (t->avctx->height/2 - 7) * t->last_frame.linesize[index] - 7)
 +            return;
 -             t->last_frame.data[index] + (mb_y * 8 + (mv_y/2))*t->last_frame.linesize[index] + mb_x * 8 + (mv_x/2),
+         comp(frame->data[index] + (mb_y*8)*frame->linesize[index] + mb_x * 8,
+              frame->linesize[index],
 +             t->last_frame.data[index] + offset,
               t->last_frame.linesize[index], add);
      }
  }
@@@ -186,7 -180,7 +187,7 @@@ static int decode_motion(GetBitContext 
      return value;
  }
  
- static int decode_mb(MadContext *s, int inter)
 -static void decode_mb(MadContext *s, AVFrame *frame, int inter)
++static int decode_mb(MadContext *s, AVFrame *frame, int inter)
  {
      int mv_map = 0;
      int mv_x, mv_y;
      for (j=0; j<6; j++) {
          if (mv_map & (1<<j)) {  // mv_x and mv_y are guarded by mv_map
              int add = 2*decode_motion(&s->gb);
 -            comp_block(s, frame, s->mb_x, s->mb_y, j, mv_x, mv_y, add);
 +            if (s->last_frame.data[0])
-                 comp_block(s, s->mb_x, s->mb_y, j, mv_x, mv_y, add);
++                comp_block(s, frame, s->mb_x, s->mb_y, j, mv_x, mv_y, add);
          } else {
              s->dsp.clear_block(s->block);
 -            decode_block_intra(s, s->block);
 +            if(decode_block_intra(s, s->block) < 0)
 +                return -1;
-             idct_put(s, s->block, s->mb_x, s->mb_y, j);
+             idct_put(s, frame, s->block, s->mb_x, s->mb_y, j);
          }
      }
 +    return 0;
  }
  
  static void calc_quant_matrix(MadContext *s, int qscale)
@@@ -233,14 -226,15 +234,15 @@@ static int decode_frame(AVCodecContext 
      int buf_size       = avpkt->size;
      const uint8_t *buf_end = buf+buf_size;
      MadContext *s     = avctx->priv_data;
-     int width, height, ret;
+     AVFrame *frame    = data;
+     int width, height;
      int chunk_type;
-     int inter;
+     int inter, ret;
  
 -    if (buf_size < 17) {
 +    if (buf_size < 26) {
          av_log(avctx, AV_LOG_ERROR, "Input buffer too small\n");
          *got_frame = 0;
 -        return -1;
 +        return AVERROR_INVALIDDATA;
      }
  
      chunk_type = AV_RL32(&buf[0]);
      buf += 16;
  
      if (avctx->width != width || avctx->height != height) {
 -        if (av_image_check_size(width, height, 0, avctx) < 0)
 -            return -1;
 +        if((width * height)/2048*7 > buf_end-buf)
 +            return AVERROR_INVALIDDATA;
 +        if ((ret = av_image_check_size(width, height, 0, avctx)) < 0)
 +            return ret;
          avcodec_set_dimensions(avctx, width, height);
-         if (s->frame.data[0])
-             avctx->release_buffer(avctx, &s->frame);
-         if (s->last_frame.data[0])
-             avctx->release_buffer(avctx, &s->last_frame);
+         av_frame_unref(&s->last_frame);
      }
  
-     s->frame.reference = 3;
-     if (!s->frame.data[0]) {
-         if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
-             av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-             return ret;
-         }
+     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
+         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+         return ret;
      }
  
      av_fast_padded_malloc(&s->bitstream_buf, &s->bitstream_buf_size,
  
      for (s->mb_y=0; s->mb_y < (avctx->height+15)/16; s->mb_y++)
          for (s->mb_x=0; s->mb_x < (avctx->width +15)/16; s->mb_x++)
-             if(decode_mb(s, inter) < 0)
 -            decode_mb(s, frame, inter);
++            if(decode_mb(s, frame, inter) < 0)
 +                return AVERROR_INVALIDDATA;
  
      *got_frame = 1;
-     *(AVFrame*)data = s->frame;
  
-     if (chunk_type != MADe_TAG)
-         FFSWAP(AVFrame, s->frame, s->last_frame);
+     if (chunk_type != MADe_TAG) {
+         av_frame_unref(&s->last_frame);
+         if ((ret = av_frame_ref(&s->last_frame, frame)) < 0)
+             return ret;
+     }
  
      return buf_size;
  }
@@@ -148,7 -148,7 +148,7 @@@ static void tgq_idct_put_mb_dconly(TgqC
      }
  }
  
- static int tgq_decode_mb(TgqContext *s, int mb_y, int mb_x)
 -static void tgq_decode_mb(TgqContext *s, AVFrame *frame, int mb_y, int mb_x)
++static int tgq_decode_mb(TgqContext *s, AVFrame *frame, int mb_y, int mb_x)
  {
      int mode;
      int i;
      mode = bytestream2_get_byte(&s->gb);
      if (mode > 12) {
          GetBitContext gb;
 -        init_get_bits(&gb, s->gb.buffer, FFMIN(s->gb.buffer_end - s->gb.buffer, mode) * 8);
 +        init_get_bits(&gb, s->gb.buffer, FFMIN(bytestream2_get_bytes_left(&s->gb), mode) * 8);
          for (i = 0; i < 6; i++)
              tgq_decode_block(s, s->block[i], &gb);
-         tgq_idct_put_mb(s, s->block, mb_x, mb_y);
+         tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
          bytestream2_skip(&s->gb, mode);
      } else {
          if (mode == 3) {
              }
          } else {
              av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode);
 +            return -1;
          }
-         tgq_idct_put_mb_dconly(s, mb_x, mb_y, dc);
+         tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc);
      }
 +    return 0;
  }
  
  static void tgq_calculate_qtable(TgqContext *s, int quant)
@@@ -201,8 -199,9 +201,9 @@@ static int tgq_decode_frame(AVCodecCont
      const uint8_t *buf = avpkt->data;
      int buf_size       = avpkt->size;
      TgqContext *s      = avctx->priv_data;
+     AVFrame *frame     = data;
      int x, y, ret;
 -    int big_endian = AV_RL32(&buf[4]) > 0x000FFFFF;
 +    int big_endian;
  
      if (buf_size < 16) {
          av_log(avctx, AV_LOG_WARNING, "truncated header\n");
  
      for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++)
          for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++)
-             if (tgq_decode_mb(s, y, x) < 0)
 -            tgq_decode_mb(s, frame, y, x);
++            if (tgq_decode_mb(s, frame, y, x) < 0)
 +                return AVERROR_INVALIDDATA;
  
      *got_frame = 1;
-     *(AVFrame*)data = s->frame;
  
      return avpkt->size;
  }
@@@ -56,8 -57,6 +57,7 @@@ static av_cold int tgv_decode_init(AVCo
      s->avctx         = avctx;
      avctx->time_base = (AVRational){1, 15};
      avctx->pix_fmt   = AV_PIX_FMT_PAL8;
-     avcodec_get_frame_defaults(&s->frame);
 +    avcodec_get_frame_defaults(&s->last_frame);
      return 0;
  }
  
@@@ -265,11 -253,9 +256,12 @@@ static int tgv_decode_frame(AVCodecCont
      int buf_size           = avpkt->size;
      TgvContext *s          = avctx->priv_data;
      const uint8_t *buf_end = buf + buf_size;
+     AVFrame *frame         = data;
      int chunk_type, ret;
  
 +    if (buf_end - buf < EA_PREAMBLE_SIZE)
 +        return AVERROR_INVALIDDATA;
 +
      chunk_type = AV_RL32(&buf[0]);
      buf       += EA_PREAMBLE_SIZE;
  
@@@ -133,13 -131,11 +131,12 @@@ static int tqi_decode_frame(AVCodecCont
      for (s->mb_x=0; s->mb_x<(avctx->width+15)/16; s->mb_x++)
      {
          if (tqi_decode_mb(s, t->block) < 0)
 -            break;
 +            goto end;
-         tqi_idct_put(t, t->block);
+         tqi_idct_put(t, frame, t->block);
      }
 +    end:
  
      *got_frame = 1;
-     *(AVFrame*)data = t->frame;
      return buf_size;
  }
  
@@@ -133,70 -133,6 +133,70 @@@ static void guess_dc(ERContext *s, int1
                       int h, int stride, int is_luma)
  {
      int b_x, b_y;
-             int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
 +    int16_t  (*col )[4] = av_malloc(stride*h*sizeof( int16_t)*4);
 +    uint32_t (*dist)[4] = av_malloc(stride*h*sizeof(uint32_t)*4);
 +
 +    if(!col || !dist) {
 +        av_log(s->avctx, AV_LOG_ERROR, "guess_dc() is out of memory\n");
 +        goto fail;
 +    }
 +
 +    for(b_y=0; b_y<h; b_y++){
 +        int color= 1024;
 +        int distance= -1;
 +        for(b_x=0; b_x<w; b_x++){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
-             int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
++            int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_x;
 +            }
 +            col [b_x + b_y*stride][1]= color;
 +            dist[b_x + b_y*stride][1]= distance >= 0 ? b_x-distance : 9999;
 +        }
 +        color= 1024;
 +        distance= -1;
 +        for(b_x=w-1; b_x>=0; b_x--){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
-             int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
++            int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_x;
 +            }
 +            col [b_x + b_y*stride][0]= color;
 +            dist[b_x + b_y*stride][0]= distance >= 0 ? distance-b_x : 9999;
 +        }
 +    }
 +    for(b_x=0; b_x<w; b_x++){
 +        int color= 1024;
 +        int distance= -1;
 +        for(b_y=0; b_y<h; b_y++){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
-             int intra_j = IS_INTRA(s->cur_pic->f.mb_type[mb_index_j]);
++            int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_y;
 +            }
 +            col [b_x + b_y*stride][3]= color;
 +            dist[b_x + b_y*stride][3]= distance >= 0 ? b_y-distance : 9999;
 +        }
 +        color= 1024;
 +        distance= -1;
 +        for(b_y=h-1; b_y>=0; b_y--){
 +            int mb_index_j= (b_x>>is_luma) + (b_y>>is_luma)*s->mb_stride;
 +            int error_j= s->error_status_table[mb_index_j];
++            int intra_j = IS_INTRA(s->cur_pic->mb_type[mb_index_j]);
 +            if(intra_j==0 || !(error_j&ER_DC_ERROR)){
 +                color= dc[b_x + b_y*stride];
 +                distance= b_y;
 +            }
 +            col [b_x + b_y*stride][2]= color;
 +            dist[b_x + b_y*stride][2]= distance >= 0 ? distance-b_y : 9999;
 +        }
 +    }
  
      for (b_y = 0; b_y < h; b_y++) {
          for (b_x = 0; b_x < w; b_x++) {
@@@ -394,14 -377,6 +394,14 @@@ static void guess_mv(ERContext *s
          fixed[mb_xy] = f;
          if (f == MV_FROZEN)
              num_avail++;
-         else if(s->last_pic->f.data[0] && s->last_pic->f.motion_val[0]){
++        else if(s->last_pic->f.data[0] && s->last_pic->motion_val[0]){
 +            const int mb_y= mb_xy / s->mb_stride;
 +            const int mb_x= mb_xy % s->mb_stride;
 +            const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
-             s->cur_pic->f.motion_val[0][mot_index][0]= s->last_pic->f.motion_val[0][mot_index][0];
-             s->cur_pic->f.motion_val[0][mot_index][1]= s->last_pic->f.motion_val[0][mot_index][1];
-             s->cur_pic->f.ref_index[0][4*mb_xy]      = s->last_pic->f.ref_index[0][4*mb_xy];
++            s->cur_pic->motion_val[0][mot_index][0]= s->last_pic->motion_val[0][mot_index][0];
++            s->cur_pic->motion_val[0][mot_index][1]= s->last_pic->motion_val[0][mot_index][1];
++            s->cur_pic->ref_index[0][4*mb_xy]      = s->last_pic->ref_index[0][4*mb_xy];
 +        }
      }
  
      if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) ||
  
                      if (fixed[mb_xy] == MV_FROZEN)
                          continue;
-                     av_assert1(!IS_INTRA(s->cur_pic->f.mb_type[mb_xy]));
 -                    assert(!IS_INTRA(s->cur_pic->mb_type[mb_xy]));
 -                    assert(s->last_pic && s->last_pic->f.data[0]);
++                    av_assert1(!IS_INTRA(s->cur_pic->mb_type[mb_xy]));
 +                    av_assert1(s->last_pic && s->last_pic->f.data[0]);
  
                      j = 0;
                      if (mb_x > 0             && fixed[mb_xy - 1]         == MV_FROZEN)
@@@ -857,25 -829,9 +857,25 @@@ void ff_er_frame_end(ERContext *s
          s->error_count == 3 * s->mb_width *
                            (s->avctx->skip_top + s->avctx->skip_bottom)) {
          return;
 -    };
 +    }
 +    if (s->last_pic) {
 +        if (s->last_pic->f.width  != s->cur_pic->f.width  ||
 +            s->last_pic->f.height != s->cur_pic->f.height ||
 +            s->last_pic->f.format != s->cur_pic->f.format) {
 +            av_log(s->avctx, AV_LOG_WARNING, "Cannot use previous picture in error concealment\n");
 +            s->last_pic = NULL;
 +        }
 +    }
 +    if (s->next_pic) {
 +        if (s->next_pic->f.width  != s->cur_pic->f.width  ||
 +            s->next_pic->f.height != s->cur_pic->f.height ||
 +            s->next_pic->f.format != s->cur_pic->f.format) {
 +            av_log(s->avctx, AV_LOG_WARNING, "Cannot use next picture in error concealment\n");
 +            s->next_pic = NULL;
 +        }
 +    }
  
-     if (s->cur_pic->f.motion_val[0] == NULL) {
+     if (s->cur_pic->motion_val[0] == NULL) {
          av_log(s->avctx, AV_LOG_ERROR, "Warning MVs not available\n");
  
          for (i = 0; i < 2; i++) {
                      int time_pp = s->pp_time;
                      int time_pb = s->pb_time;
  
-                     ff_thread_await_progress(&s->next_pic->f, mb_y, 0);
 +                    av_assert0(s->avctx->codec_id != AV_CODEC_ID_H264);
+                     ff_thread_await_progress(&s->next_pic->tf, mb_y, 0);
  
-                     s->mv[0][0][0] = s->next_pic->f.motion_val[0][xy][0] *  time_pb            / time_pp;
-                     s->mv[0][0][1] = s->next_pic->f.motion_val[0][xy][1] *  time_pb            / time_pp;
-                     s->mv[1][0][0] = s->next_pic->f.motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
-                     s->mv[1][0][1] = s->next_pic->f.motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
+                     s->mv[0][0][0] = s->next_pic->motion_val[0][xy][0] *  time_pb            / time_pp;
+                     s->mv[0][0][1] = s->next_pic->motion_val[0][xy][1] *  time_pb            / time_pp;
+                     s->mv[1][0][0] = s->next_pic->motion_val[0][xy][0] * (time_pb - time_pp) / time_pp;
+                     s->mv[1][0][1] = s->next_pic->motion_val[0][xy][1] * (time_pb - time_pp) / time_pp;
                  } else {
                      s->mv[0][0][0] = 0;
                      s->mv[0][0][1] = 0;
@@@ -215,9 -214,7 +215,8 @@@ static int escape124_decode_frame(AVCod
  
      uint16_t* old_frame_data, *new_frame_data;
      unsigned old_stride, new_stride;
-     AVFrame new_frame;
-     avcodec_get_frame_defaults(&new_frame);
 +
+     int ret;
  
      init_get_bits(&gb, buf, buf_size * 8);
  
index ca6a253,0000000..64d2383
mode 100644,000000..100644
--- /dev/null
@@@ -1,321 -1,0 +1,321 @@@
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
 +/*
 + * Escape 130 Video Decoder
 + * Copyright (C) 2008 Eli Friedman (eli.friedman <at> gmail.com)
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +
 +#define BITSTREAM_READER_LE
 +#include "get_bits.h"
 +#include "internal.h"
 +
 +
 +typedef struct Escape130Context {
 +    AVFrame frame;
 +    uint8_t *bases;
 +} Escape130Context;
 +
 +/**
 + * Initialize the decoder
 + * @param avctx decoder context
 + * @return 0 success, negative on error
 + */
 +static av_cold int escape130_decode_init(AVCodecContext *avctx)
 +{
 +    Escape130Context *s = avctx->priv_data;
 +    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
++    avcodec_get_frame_defaults(&s->frame);
 +
 +    if((avctx->width&1) || (avctx->height&1)){
 +        av_log(avctx, AV_LOG_ERROR, "Dimensions are not a multiple of the block size\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    s->bases= av_malloc(avctx->width * avctx->height /4);
 +
 +    return 0;
 +}
 +
 +static av_cold int escape130_decode_close(AVCodecContext *avctx)
 +{
 +    Escape130Context *s = avctx->priv_data;
 +
-     AVFrame new_frame = { { 0 } };
++    av_frame_unref(&s->frame);
 +
 +    av_freep(&s->bases);
 +
 +    return 0;
 +}
 +
 +static unsigned decode_skip_count(GetBitContext* gb) {
 +    unsigned value;
 +    // This function reads a maximum of 27 bits,
 +    // which is within the padding space
 +    if (get_bits_left(gb) < 1+3)
 +        return -1;
 +
 +    value = get_bits1(gb);
 +    if (value)
 +        return 0;
 +
 +    value = get_bits(gb, 3);
 +    if (value)
 +        return value;
 +
 +    value = get_bits(gb, 8);
 +    if (value)
 +        return value + 7;
 +
 +    value = get_bits(gb, 15);
 +    if (value)
 +        return value + 262;
 +
 +    return -1;
 +}
 +
 +/**
 + * Decode a single frame
 + * @param avctx decoder context
 + * @param data decoded frame
 + * @param got_frame have decoded frame
 + * @param buf input buffer
 + * @param buf_size input buffer size
 + * @return 0 success, -1 on error
 + */
 +static int escape130_decode_frame(AVCodecContext *avctx,
 +                                  void *data, int *got_frame,
 +                                  AVPacket *avpkt)
 +{
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    Escape130Context *s = avctx->priv_data;
 +
 +    GetBitContext gb;
 +    unsigned i;
++    int ret;
 +
 +    uint8_t *old_y, *old_cb, *old_cr,
 +            *new_y, *new_cb, *new_cr;
 +    unsigned old_y_stride, old_cb_stride, old_cr_stride,
 +             new_y_stride, new_cb_stride, new_cr_stride;
 +    unsigned total_blocks = avctx->width * avctx->height / 4,
 +             block_index, row_index = 0;
 +    unsigned y[4] = {0}, cb = 16, cr = 16;
 +    unsigned skip = -1;
 +    unsigned y_base = 0;
 +    uint8_t *yb= s->bases;
 +
-     new_frame.reference = 3;
-     if (ff_get_buffer(avctx, &new_frame)) {
++    AVFrame *frame = data;
 +
 +    init_get_bits(&gb, buf, buf_size * 8);
 +
 +    if (get_bits_left(&gb) < 128)
 +        return -1;
 +
 +    // Header; no useful information in here
 +    skip_bits_long(&gb, 128);
 +
-     new_y = new_frame.data[0];
-     new_cb = new_frame.data[1];
-     new_cr = new_frame.data[2];
-     new_y_stride = new_frame.linesize[0];
-     new_cb_stride = new_frame.linesize[1];
-     new_cr_stride = new_frame.linesize[2];
++    if (ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return -1;
 +    }
 +
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
++    new_y = frame->data[0];
++    new_cb = frame->data[1];
++    new_cr = frame->data[2];
++    new_y_stride = frame->linesize[0];
++    new_cb_stride = frame->linesize[1];
++    new_cr_stride = frame->linesize[2];
 +    old_y = s->frame.data[0];
 +    old_cb = s->frame.data[1];
 +    old_cr = s->frame.data[2];
 +    old_y_stride = s->frame.linesize[0];
 +    old_cb_stride = s->frame.linesize[1];
 +    old_cr_stride = s->frame.linesize[2];
 +
 +    av_log(avctx, AV_LOG_DEBUG,
 +           "Strides: %i, %i\n",
 +           new_y_stride, new_cb_stride);
 +
 +    for (block_index = 0; block_index < total_blocks; block_index++) {
 +        // Note that this call will make us skip the rest of the blocks
 +        // if the frame prematurely ends
 +        if (skip == -1)
 +            skip = decode_skip_count(&gb);
 +
 +        if (skip) {
 +            if (old_y) {
 +                y[0] = old_y[0] / 4;
 +                y[1] = old_y[1] / 4;
 +                y[2] = old_y[old_y_stride] / 4;
 +                y[3] = old_y[old_y_stride+1] / 4;
 +                y_base= yb[0];
 +                cb = old_cb[0] / 8;
 +                cr = old_cr[0] / 8;
 +            } else {
 +                y_base=y[0] = y[1] = y[2] = y[3] = 0;
 +                cb = cr = 16;
 +            }
 +        } else {
 +            if (get_bits1(&gb)) {
 +                static const uint8_t offset_table[] = {2, 4, 10, 20};
 +                static const int8_t sign_table[64][4] =
 +                    { {0, 0, 0, 0},
 +                      {-1, 1, 0, 0},
 +                      {1, -1, 0, 0},
 +                      {-1, 0, 1, 0},
 +                      {-1, 1, 1, 0},
 +                      {0, -1, 1, 0},
 +                      {1, -1, 1, 0},
 +                      {-1, -1, 1, 0},
 +                      {1, 0, -1, 0},
 +                      {0, 1, -1, 0},
 +                      {1, 1, -1, 0},
 +                      {-1, 1, -1, 0},
 +                      {1, -1, -1, 0},
 +                      {-1, 0, 0, 1},
 +                      {-1, 1, 0, 1},
 +                      {0, -1, 0, 1},
 +
 +                      {0, 0, 0, 0},
 +                      {1, -1, 0, 1},
 +                      {-1, -1, 0, 1},
 +                      {-1, 0, 1, 1},
 +                      {-1, 1, 1, 1},
 +                      {0, -1, 1, 1},
 +                      {1, -1, 1, 1},
 +                      {-1, -1, 1, 1},
 +                      {0, 0, -1, 1},
 +                      {1, 0, -1, 1},
 +                      {-1, 0, -1, 1},
 +                      {0, 1, -1, 1},
 +                      {1, 1, -1, 1},
 +                      {-1, 1, -1, 1},
 +                      {0, -1, -1, 1},
 +                      {1, -1, -1, 1},
 +
 +                      {0, 0, 0, 0},
 +                      {-1, -1, -1, 1},
 +                      {1, 0, 0, -1},
 +                      {0, 1, 0, -1},
 +                      {1, 1, 0, -1},
 +                      {-1, 1, 0, -1},
 +                      {1, -1, 0, -1},
 +                      {0, 0, 1, -1},
 +                      {1, 0, 1, -1},
 +                      {-1, 0, 1, -1},
 +                      {0, 1, 1, -1},
 +                      {1, 1, 1, -1},
 +                      {-1, 1, 1, -1},
 +                      {0, -1, 1, -1},
 +                      {1, -1, 1, -1},
 +                      {-1, -1, 1, -1},
 +
 +                      {0, 0, 0, 0},
 +                      {1, 0, -1, -1},
 +                      {0, 1, -1, -1},
 +                      {1, 1, -1, -1},
 +                      {-1, 1, -1, -1},
 +                      {1, -1, -1, -1} };
 +                unsigned sign_selector = get_bits(&gb, 6);
 +                unsigned difference_selector = get_bits(&gb, 2);
 +                y_base = 2 * get_bits(&gb, 5);
 +                for (i = 0; i < 4; i++) {
 +                    y[i] = av_clip((int)y_base + offset_table[difference_selector] *
 +                                            sign_table[sign_selector][i], 0, 63);
 +                }
 +            } else if (get_bits1(&gb)) {
 +                if (get_bits1(&gb)) {
 +                    y_base = get_bits(&gb, 6);
 +                } else {
 +                    unsigned adjust_index = get_bits(&gb, 3);
 +                    static const int8_t adjust[] = {-4, -3, -2, -1, 1, 2, 3, 4};
 +                    y_base = (y_base + adjust[adjust_index]) & 63;
 +                }
 +                for (i = 0; i < 4; i++)
 +                    y[i] = y_base;
 +            }
 +
 +            if (get_bits1(&gb)) {
 +                if (get_bits1(&gb)) {
 +                    cb = get_bits(&gb, 5);
 +                    cr = get_bits(&gb, 5);
 +                } else {
 +                    unsigned adjust_index = get_bits(&gb, 3);
 +                    static const int8_t adjust[2][8] =
 +                        {  { 1, 1, 0, -1, -1, -1,  0,  1 },
 +                           { 0, 1, 1,  1,  0, -1, -1, -1 } };
 +                    cb = (cb + adjust[0][adjust_index]) & 31;
 +                    cr = (cr + adjust[1][adjust_index]) & 31;
 +                }
 +            }
 +        }
 +        *yb++= y_base;
 +
 +        new_y[0] = y[0] * 4;
 +        new_y[1] = y[1] * 4;
 +        new_y[new_y_stride] = y[2] * 4;
 +        new_y[new_y_stride + 1] = y[3] * 4;
 +        *new_cb = cb * 8;
 +        *new_cr = cr * 8;
 +
 +        if (old_y)
 +            old_y += 2, old_cb++, old_cr++;
 +        new_y += 2, new_cb++, new_cr++;
 +        row_index++;
 +        if (avctx->width / 2 == row_index) {
 +            row_index = 0;
 +            if (old_y) {
 +                old_y  += old_y_stride * 2  - avctx->width;
 +                old_cb += old_cb_stride - avctx->width / 2;
 +                old_cr += old_cr_stride - avctx->width / 2;
 +            }
 +            new_y  += new_y_stride * 2  - avctx->width;
 +            new_cb += new_cb_stride - avctx->width / 2;
 +            new_cr += new_cr_stride - avctx->width / 2;
 +        }
 +
 +        skip--;
 +    }
 +
 +    av_log(avctx, AV_LOG_DEBUG,
 +           "Escape sizes: %i, %i\n",
 +           buf_size, get_bits_count(&gb) / 8);
 +
-     *(AVFrame*)data = s->frame = new_frame;
++    av_frame_unref(&s->frame);
++    if ((ret = av_frame_ref(&s->frame, frame)) < 0)
++        return ret;
 +
 +    *got_frame = 1;
 +
 +    return buf_size;
 +}
 +
 +
 +AVCodec ff_escape130_decoder = {
 +    .name           = "escape130",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_ESCAPE130,
 +    .priv_data_size = sizeof(Escape130Context),
 +    .init           = escape130_decode_init,
 +    .close          = escape130_decode_close,
 +    .decode         = escape130_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Escape 130"),
 +};
index 5569ca2,0000000..7691455
mode 100644,000000..100644
--- /dev/null
@@@ -1,917 -1,0 +1,917 @@@
-     if ((ret = ff_get_buffer(avctx, frame)) < 0)
 +/*
 + * Enhanced Variable Rate Codec, Service Option 3 decoder
 + * Copyright (c) 2013 Paul B Mahol
 + *
 + * 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
 + * Enhanced Variable Rate Codec, Service Option 3 decoder
 + * @author Paul B Mahol
 + */
 +
 +#include "libavutil/mathematics.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "get_bits.h"
 +#include "evrcdata.h"
 +#include "acelp_vectors.h"
 +#include "lsp.h"
 +
 +#define MIN_LSP_SEP (0.05 / (2.0 * M_PI))
 +#define MIN_DELAY      20
 +#define MAX_DELAY     120
 +#define NB_SUBFRAMES    3
 +#define SUBFRAME_SIZE  54
 +#define FILTER_ORDER   10
 +#define ACB_SIZE      128
 +
 +typedef enum {
 +    RATE_ERRS = -1,
 +    SILENCE,
 +    RATE_QUANT,
 +    RATE_QUARTER,
 +    RATE_HALF,
 +    RATE_FULL,
 +} evrc_packet_rate;
 +
 +/**
 + * EVRC-A unpacked data frame
 + */
 +typedef struct EVRCAFrame {
 +    uint8_t  lpc_flag;        ///< spectral change indicator
 +    uint16_t lsp[4];          ///< index into LSP codebook
 +    uint8_t  pitch_delay;     ///< pitch delay for entire frame
 +    uint8_t  delay_diff;      ///< delay difference for entire frame
 +    uint8_t  acb_gain[3];     ///< adaptive codebook gain
 +    uint16_t fcb_shape[3][4]; ///< fixed codebook shape
 +    uint8_t  fcb_gain[3];     ///< fixed codebook gain index
 +    uint8_t  energy_gain;     ///< frame energy gain index
 +    uint8_t  tty;             ///< tty baud rate bit
 +} EVRCAFrame;
 +
 +typedef struct EVRCContext {
 +    GetBitContext    gb;
 +    evrc_packet_rate bitrate;
 +    evrc_packet_rate last_valid_bitrate;
 +    EVRCAFrame       frame;
 +
 +    float            lspf[FILTER_ORDER];
 +    float            prev_lspf[FILTER_ORDER];
 +    float            synthesis[FILTER_ORDER];
 +    float            postfilter_fir[FILTER_ORDER];
 +    float            postfilter_iir[FILTER_ORDER];
 +    float            postfilter_residual[ACB_SIZE + SUBFRAME_SIZE];
 +    float            pitch_delay;
 +    float            prev_pitch_delay;
 +    float            avg_acb_gain;  ///< average adaptive codebook gain
 +    float            avg_fcb_gain;  ///< average fixed codebook gain
 +    float            pitch[ACB_SIZE + FILTER_ORDER + SUBFRAME_SIZE];
 +    float            pitch_back[ACB_SIZE];
 +    float            interpolation_coeffs[136];
 +    float            energy_vector[NB_SUBFRAMES];
 +    float            fade_scale;
 +    float            last;
 +
 +    uint8_t          prev_energy_gain;
 +    uint8_t          prev_error_flag;
 +    uint8_t          warned_buf_mismatch_bitrate;
 +} EVRCContext;
 +
 +/**
 + * Frame unpacking for RATE_FULL, RATE_HALF and RATE_QUANT
 + *
 + * @param e the context
 + *
 + * TIA/IS-127 Table 4.21-1
 + */
 +static void unpack_frame(EVRCContext *e)
 +{
 +    EVRCAFrame *frame = &e->frame;
 +    GetBitContext *gb = &e->gb;
 +
 +    switch (e->bitrate) {
 +    case RATE_FULL:
 +        frame->lpc_flag        = get_bits1(gb);
 +        frame->lsp[0]          = get_bits(gb,  6);
 +        frame->lsp[1]          = get_bits(gb,  6);
 +        frame->lsp[2]          = get_bits(gb,  9);
 +        frame->lsp[3]          = get_bits(gb,  7);
 +        frame->pitch_delay     = get_bits(gb,  7);
 +        frame->delay_diff      = get_bits(gb,  5);
 +        frame->acb_gain[0]     = get_bits(gb,  3);
 +        frame->fcb_shape[0][0] = get_bits(gb,  8);
 +        frame->fcb_shape[0][1] = get_bits(gb,  8);
 +        frame->fcb_shape[0][2] = get_bits(gb,  8);
 +        frame->fcb_shape[0][3] = get_bits(gb, 11);
 +        frame->fcb_gain[0]     = get_bits(gb,  5);
 +        frame->acb_gain[1]     = get_bits(gb,  3);
 +        frame->fcb_shape[1][0] = get_bits(gb,  8);
 +        frame->fcb_shape[1][1] = get_bits(gb,  8);
 +        frame->fcb_shape[1][2] = get_bits(gb,  8);
 +        frame->fcb_shape[1][3] = get_bits(gb, 11);
 +        frame->fcb_gain    [1] = get_bits(gb,  5);
 +        frame->acb_gain    [2] = get_bits(gb,  3);
 +        frame->fcb_shape[2][0] = get_bits(gb,  8);
 +        frame->fcb_shape[2][1] = get_bits(gb,  8);
 +        frame->fcb_shape[2][2] = get_bits(gb,  8);
 +        frame->fcb_shape[2][3] = get_bits(gb, 11);
 +        frame->fcb_gain    [2] = get_bits(gb,  5);
 +        frame->tty             = get_bits1(gb);
 +        break;
 +    case RATE_HALF:
 +        frame->lsp         [0] = get_bits(gb,  7);
 +        frame->lsp         [1] = get_bits(gb,  7);
 +        frame->lsp         [2] = get_bits(gb,  8);
 +        frame->pitch_delay     = get_bits(gb,  7);
 +        frame->acb_gain    [0] = get_bits(gb,  3);
 +        frame->fcb_shape[0][0] = get_bits(gb, 10);
 +        frame->fcb_gain    [0] = get_bits(gb,  4);
 +        frame->acb_gain    [1] = get_bits(gb,  3);
 +        frame->fcb_shape[1][0] = get_bits(gb, 10);
 +        frame->fcb_gain    [1] = get_bits(gb,  4);
 +        frame->acb_gain    [2] = get_bits(gb,  3);
 +        frame->fcb_shape[2][0] = get_bits(gb, 10);
 +        frame->fcb_gain    [2] = get_bits(gb,  4);
 +        break;
 +    case RATE_QUANT:
 +        frame->lsp         [0] = get_bits(gb, 4);
 +        frame->lsp         [1] = get_bits(gb, 4);
 +        frame->energy_gain     = get_bits(gb, 8);
 +        break;
 +    }
 +}
 +
 +static evrc_packet_rate buf_size2bitrate(const int buf_size)
 +{
 +    switch (buf_size) {
 +    case 23: return RATE_FULL;
 +    case 11: return RATE_HALF;
 +    case  6: return RATE_QUARTER;
 +    case  3: return RATE_QUANT;
 +    case  1: return SILENCE;
 +    }
 +
 +    return RATE_ERRS;
 +}
 +
 +/**
 + * Determine the bitrate from the frame size and/or the first byte of the frame.
 + *
 + * @param avctx the AV codec context
 + * @param buf_size length of the buffer
 + * @param buf the bufffer
 + *
 + * @return the bitrate on success,
 + *         RATE_ERRS  if the bitrate cannot be satisfactorily determined
 + */
 +static evrc_packet_rate determine_bitrate(AVCodecContext *avctx,
 +                                          int *buf_size,
 +                                          const uint8_t **buf)
 +{
 +    evrc_packet_rate bitrate;
 +
 +    if ((bitrate = buf_size2bitrate(*buf_size)) >= 0) {
 +        if (bitrate > **buf) {
 +            EVRCContext *e = avctx->priv_data;
 +            if (!e->warned_buf_mismatch_bitrate) {
 +                av_log(avctx, AV_LOG_WARNING,
 +                       "Claimed bitrate and buffer size mismatch.\n");
 +                e->warned_buf_mismatch_bitrate = 1;
 +            }
 +            bitrate = **buf;
 +        } else if (bitrate < **buf) {
 +            av_log(avctx, AV_LOG_ERROR,
 +                   "Buffer is too small for the claimed bitrate.\n");
 +            return RATE_ERRS;
 +        }
 +        (*buf)++;
 +        *buf_size -= 1;
 +    } else if ((bitrate = buf_size2bitrate(*buf_size + 1)) >= 0) {
 +        av_log(avctx, AV_LOG_DEBUG,
 +               "Bitrate byte is missing, guessing the bitrate from packet size.\n");
 +    } else
 +        return RATE_ERRS;
 +
 +    return bitrate;
 +}
 +
 +static void warn_insufficient_frame_quality(AVCodecContext *avctx,
 +                                            const char *message)
 +{
 +    av_log(avctx, AV_LOG_WARNING, "Frame #%d, %s\n",
 +           avctx->frame_number, message);
 +}
 +
 +/**
 + * Initialize the speech codec according to the specification.
 + *
 + * TIA/IS-127 5.2
 + */
 +static av_cold int evrc_decode_init(AVCodecContext *avctx)
 +{
 +    EVRCContext *e = avctx->priv_data;
 +    int i, n, idx = 0;
 +    float denom = 2.0 / (2.0 * 8.0 + 1.0);
 +
 +    avctx->channels       = 1;
 +    avctx->channel_layout = AV_CH_LAYOUT_MONO;
 +    avctx->sample_fmt     = AV_SAMPLE_FMT_FLT;
 +
 +    for (i = 0; i < FILTER_ORDER; i++) {
 +        e->prev_lspf[i] = (i + 1) * 0.048;
 +        e->synthesis[i] = 0.0;
 +    }
 +
 +    for (i = 0; i < ACB_SIZE; i++)
 +        e->pitch[i] = e->pitch_back[i] = 0.0;
 +
 +    e->last_valid_bitrate = RATE_QUANT;
 +    e->prev_pitch_delay   = 40.0;
 +    e->fade_scale         = 1.0;
 +    e->prev_error_flag    = 0;
 +    e->avg_acb_gain = e->avg_fcb_gain = 0.0;
 +
 +    for (i = 0; i < 8; i++) {
 +        float tt = ((float)i - 8.0 / 2.0) / 8.0;
 +
 +        for (n = -8; n <= 8; n++, idx++) {
 +            float arg1 = M_PI * 0.9 * (tt - n);
 +            float arg2 = M_PI * (tt - n);
 +
 +            e->interpolation_coeffs[idx] = 0.9;
 +            if (arg1)
 +                e->interpolation_coeffs[idx] *= (0.54 + 0.46 * cos(arg2 * denom)) *
 +                                                 sin(arg1) / arg1;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +/**
 + * Decode the 10 vector quantized line spectral pair frequencies from the LSP
 + * transmission codes of any bitrate and check for badly received packets.
 + *
 + * @param e the context
 + *
 + * @return 0 on success, -1 if the packet is badly received
 + *
 + * TIA/IS-127 5.2.1, 5.7.1
 + */
 +static int decode_lspf(EVRCContext *e)
 +{
 +    const float **codebooks = evrc_lspq_codebooks[e->bitrate];
 +    int i, j, k = 0;
 +
 +    for (i = 0; i < evrc_lspq_nb_codebooks[e->bitrate]; i++) {
 +        int row_size = evrc_lspq_codebooks_row_sizes[e->bitrate][i];
 +        const float *codebook = codebooks[i];
 +
 +        for (j = 0; j < row_size; j++)
 +            e->lspf[k++] = codebook[e->frame.lsp[i] * row_size + j];
 +    }
 +
 +    // check for monotonic LSPs
 +    for (i = 1; i < FILTER_ORDER; i++)
 +        if (e->lspf[i] <= e->lspf[i - 1])
 +            return -1;
 +
 +    // check for minimum separation of LSPs at the splits
 +    for (i = 0, k = 0; i < evrc_lspq_nb_codebooks[e->bitrate] - 1; i++) {
 +        k += evrc_lspq_codebooks_row_sizes[e->bitrate][i];
 +        if (e->lspf[k] - e->lspf[k - 1] <= MIN_LSP_SEP)
 +            return -1;
 +    }
 +
 +    return 0;
 +}
 +
 +/*
 + * Interpolation of LSP parameters.
 + *
 + * TIA/IS-127 5.2.3.1, 5.7.3.2
 + */
 +static void interpolate_lsp(float *ilsp, const float *lsp,
 +                            const float *prev, int index)
 +{
 +    static const float lsp_interpolation_factors[] = { 0.1667, 0.5, 0.8333 };
 +    ff_weighted_vector_sumf(ilsp, prev, lsp,
 +                            1.0 - lsp_interpolation_factors[index],
 +                            lsp_interpolation_factors[index], FILTER_ORDER);
 +}
 +
 +/*
 + * Reconstruction of the delay contour.
 + *
 + * TIA/IS-127 5.2.2.3.2
 + */
 +static void interpolate_delay(float *dst, float current, float prev, int index)
 +{
 +    static const float d_interpolation_factors[] = { 0, 0.3313, 0.6625, 1, 1 };
 +    dst[0] = (1.0 - d_interpolation_factors[index    ]) * prev
 +                  + d_interpolation_factors[index    ]  * current;
 +    dst[1] = (1.0 - d_interpolation_factors[index + 1]) * prev
 +                  + d_interpolation_factors[index + 1]  * current;
 +    dst[2] = (1.0 - d_interpolation_factors[index + 2]) * prev
 +                  + d_interpolation_factors[index + 2]  * current;
 +}
 +
 +/*
 + * Convert the quantized, interpolated line spectral frequencies,
 + * to prediction coefficients.
 + *
 + * TIA/IS-127 5.2.3.2, 4.7.2.2
 + */
 +static void decode_predictor_coeffs(const float *ilspf, float *ilpc)
 +{
 +    double lsp[FILTER_ORDER];
 +    float a[FILTER_ORDER / 2 + 1], b[FILTER_ORDER / 2 + 1];
 +    float a1[FILTER_ORDER / 2] = { 0 };
 +    float a2[FILTER_ORDER / 2] = { 0 };
 +    float b1[FILTER_ORDER / 2] = { 0 };
 +    float b2[FILTER_ORDER / 2] = { 0 };
 +    int i, k;
 +
 +    ff_acelp_lsf2lspd(lsp, ilspf, FILTER_ORDER);
 +
 +    for (k = 0; k <= FILTER_ORDER; k++) {
 +        a[0] = k < 2 ? 0.25 : 0;
 +        b[0] = k < 2 ? k < 1 ? 0.25 : -0.25 : 0;
 +
 +        for (i = 0; i < FILTER_ORDER / 2; i++) {
 +            a[i + 1] = a[i] - 2 * lsp[i * 2    ] * a1[i] + a2[i];
 +            b[i + 1] = b[i] - 2 * lsp[i * 2 + 1] * b1[i] + b2[i];
 +            a2[i] = a1[i];
 +            a1[i] = a[i];
 +            b2[i] = b1[i];
 +            b1[i] = b[i];
 +        }
 +
 +        if (k)
 +            ilpc[k - 1] = 2.0 * (a[FILTER_ORDER / 2] + b[FILTER_ORDER / 2]);
 +    }
 +}
 +
 +static void bl_intrp(EVRCContext *e, float *ex, float delay)
 +{
 +    float *f;
 +    int offset, i, coef_idx;
 +    int16_t t;
 +
 +    offset = lrintf(fabs(delay));
 +
 +    t = (offset - delay + 0.5) * 8.0 + 0.5;
 +    if (t == 8) {
 +        t = 0;
 +        offset--;
 +    }
 +
 +    f = ex - offset - 8;
 +
 +    coef_idx = t * (2 * 8 + 1);
 +
 +    ex[0] = 0.0;
 +    for (i = 0; i < 2 * 8 + 1; i++)
 +        ex[0] += e->interpolation_coeffs[coef_idx + i] * f[i];
 +}
 +
 +/*
 + * Adaptive codebook excitation.
 + *
 + * TIA/IS-127 5.2.2.3.3, 4.12.5.2
 + */
 +static void acb_excitation(EVRCContext *e, float *excitation, float gain,
 +                           const float delay[3], int length)
 +{
 +    float denom, locdelay, dpr, invl;
 +    int i;
 +
 +    invl = 1.0 / ((float) length);
 +    dpr = length;
 +
 +    /* first at-most extra samples */
 +    denom = (delay[1] - delay[0]) * invl;
 +    for (i = 0; i < dpr; i++) {
 +        locdelay = delay[0] + i * denom;
 +        bl_intrp(e, excitation + i, locdelay);
 +    }
 +
 +    denom = (delay[2] - delay[1]) * invl;
 +    /* interpolation */
 +    for (i = dpr; i < dpr + 10; i++) {
 +        locdelay = delay[1] + (i - dpr) * denom;
 +        bl_intrp(e, excitation + i, locdelay);
 +    }
 +
 +    for (i = 0; i < length; i++)
 +        excitation[i] *= gain;
 +}
 +
 +static void decode_8_pulses_35bits(const uint16_t *fixed_index, float *cod)
 +{
 +    int i, pos1, pos2, offset;
 +
 +    offset = (fixed_index[3] >> 9) & 3;
 +
 +    for (i = 0; i < 3; i++) {
 +        pos1 = ((fixed_index[i] & 0x7f) / 11) * 5 + ((i + offset) % 5);
 +        pos2 = ((fixed_index[i] & 0x7f) % 11) * 5 + ((i + offset) % 5);
 +
 +        cod[pos1] = (fixed_index[i] & 0x80) ? -1.0 : 1.0;
 +
 +        if (pos2 < pos1)
 +            cod[pos2]  = -cod[pos1];
 +        else
 +            cod[pos2] +=  cod[pos1];
 +    }
 +
 +    pos1 = ((fixed_index[3] & 0x7f) / 11) * 5 + ((3 + offset) % 5);
 +    pos2 = ((fixed_index[3] & 0x7f) % 11) * 5 + ((4 + offset) % 5);
 +
 +    cod[pos1] = (fixed_index[3] & 0x100) ? -1.0 : 1.0;
 +    cod[pos2] = (fixed_index[3] & 0x80 ) ? -1.0 : 1.0;
 +}
 +
 +static void decode_3_pulses_10bits(uint16_t fixed_index, float *cod)
 +{
 +    float sign;
 +    int pos;
 +
 +    sign = (fixed_index & 0x200) ? -1.0 : 1.0;
 +
 +    pos = ((fixed_index        & 0x7) * 7) + 4;
 +    cod[pos] += sign;
 +    pos = (((fixed_index >> 3) & 0x7) * 7) + 2;
 +    cod[pos] -= sign;
 +    pos = (((fixed_index >> 6) & 0x7) * 7);
 +    cod[pos] += sign;
 +}
 +
 +/*
 + * Reconstruction of ACELP fixed codebook excitation for full and half rate.
 + *
 + * TIA/IS-127 5.2.3.7
 + */
 +static void fcb_excitation(EVRCContext *e, const uint16_t *codebook,
 +                           float *excitation, float pitch_gain,
 +                           int pitch_lag, int subframe_size)
 +{
 +    int i;
 +
 +    if (e->bitrate == RATE_FULL)
 +        decode_8_pulses_35bits(codebook, excitation);
 +    else
 +        decode_3_pulses_10bits(*codebook, excitation);
 +
 +    pitch_gain = av_clipf(pitch_gain, 0.2, 0.9);
 +
 +    for (i = pitch_lag; i < subframe_size; i++)
 +        excitation[i] += pitch_gain * excitation[i - pitch_lag];
 +}
 +
 +/**
 + * Synthesis of the decoder output signal.
 + *
 + * param[in]     in              input signal
 + * param[in]     filter_coeffs   LPC coefficients
 + * param[in/out] memory          synthesis filter memory
 + * param         buffer_length   amount of data to process
 + * param[out]    samples         output samples
 + *
 + * TIA/IS-127 5.2.3.15, 5.7.3.4
 + */
 +static void synthesis_filter(const float *in, const float *filter_coeffs,
 +                             float *memory, int buffer_length, float *samples)
 +{
 +    int i, j;
 +
 +    for (i = 0; i < buffer_length; i++) {
 +        samples[i] = in[i];
 +        for (j = FILTER_ORDER - 1; j > 0; j--) {
 +            samples[i] -= filter_coeffs[j] * memory[j];
 +            memory[j]   = memory[j - 1];
 +        }
 +        samples[i] -= filter_coeffs[0] * memory[0];
 +        memory[0]   = samples[i];
 +    }
 +}
 +
 +static void bandwidth_expansion(float *coeff, const float *inbuf, float gamma)
 +{
 +    double fac = gamma;
 +    int i;
 +
 +    for (i = 0; i < FILTER_ORDER; i++) {
 +        coeff[i] = inbuf[i] * fac;
 +        fac *= gamma;
 +    }
 +}
 +
 +static void residual_filter(float *output, const float *input,
 +                            const float *coef, float *memory, int length)
 +{
 +    float sum;
 +    int i, j;
 +
 +    for (i = 0; i < length; i++) {
 +        sum = input[i];
 +
 +        for (j = FILTER_ORDER - 1; j > 0; j--) {
 +            sum      += coef[j] * memory[j];
 +            memory[j] = memory[j - 1];
 +        }
 +        sum += coef[0] * memory[0];
 +        memory[0] = input[i];
 +        output[i] = sum;
 +    }
 +}
 +
 +/*
 + * TIA/IS-127 Table 5.9.1-1.
 + */
 +static const struct PfCoeff {
 +    float tilt;
 +    float ltgain;
 +    float p1;
 +    float p2;
 +} postfilter_coeffs[5] = {
 +    { 0.0 , 0.0 , 0.0 , 0.0  },
 +    { 0.0 , 0.0 , 0.57, 0.57 },
 +    { 0.0 , 0.0 , 0.0 , 0.0  },
 +    { 0.35, 0.50, 0.50, 0.75 },
 +    { 0.20, 0.50, 0.57, 0.75 },
 +};
 +
 +/*
 + * Adaptive postfilter.
 + *
 + * TIA/IS-127 5.9
 + */
 +static void postfilter(EVRCContext *e, float *in, const float *coeff,
 +                       float *out, int idx, const struct PfCoeff *pfc,
 +                       int length)
 +{
 +    float wcoef1[FILTER_ORDER], wcoef2[FILTER_ORDER],
 +          scratch[SUBFRAME_SIZE], temp[SUBFRAME_SIZE],
 +          mem[SUBFRAME_SIZE];
 +    float sum1 = 0.0, sum2 = 0.0, gamma, gain;
 +    float tilt = pfc->tilt;
 +    int i, n, best;
 +
 +    bandwidth_expansion(wcoef1, coeff, pfc->p1);
 +    bandwidth_expansion(wcoef2, coeff, pfc->p2);
 +
 +    /* Tilt compensation filter, TIA/IS-127 5.9.1 */
 +    for (i = 0; i < length - 1; i++)
 +        sum2 += in[i] * in[i + 1];
 +    if (sum2 < 0.0)
 +        tilt = 0.0;
 +
 +    for (i = 0; i < length; i++) {
 +        scratch[i] = in[i] - tilt * e->last;
 +        e->last = in[i];
 +    }
 +
 +    /* Short term residual filter, TIA/IS-127 5.9.2 */
 +    residual_filter(&e->postfilter_residual[ACB_SIZE], scratch, wcoef1, e->postfilter_fir, length);
 +
 +    /* Long term postfilter */
 +    best = idx;
 +    for (i = FFMIN(MIN_DELAY, idx - 3); i <= FFMAX(MAX_DELAY, idx + 3); i++) {
 +        for (n = ACB_SIZE, sum2 = 0; n < ACB_SIZE + length; n++)
 +            sum2 += e->postfilter_residual[n] * e->postfilter_residual[n - i];
 +        if (sum2 > sum1) {
 +            sum1 = sum2;
 +            best = i;
 +        }
 +    }
 +
 +    for (i = ACB_SIZE, sum1 = 0; i < ACB_SIZE + length; i++)
 +        sum1 += e->postfilter_residual[i - best] * e->postfilter_residual[i - best];
 +    for (i = ACB_SIZE, sum2 = 0; i < ACB_SIZE + length; i++)
 +        sum2 += e->postfilter_residual[i] * e->postfilter_residual[i - best];
 +
 +    if (sum2 * sum1 == 0 || e->bitrate == RATE_QUANT) {
 +        memcpy(temp, e->postfilter_residual + ACB_SIZE, length * sizeof(float));
 +    } else {
 +        gamma = sum2 / sum1;
 +        if (gamma < 0.5)
 +            memcpy(temp, e->postfilter_residual + ACB_SIZE, length * sizeof(float));
 +        else {
 +            gamma = FFMIN(gamma, 1.0);
 +
 +            for (i = 0; i < length; i++) {
 +                temp[i] = e->postfilter_residual[ACB_SIZE + i] + gamma *
 +                    pfc->ltgain * e->postfilter_residual[ACB_SIZE + i - best];
 +            }
 +        }
 +    }
 +
 +    memcpy(scratch, temp, length * sizeof(float));
 +    memcpy(mem, e->postfilter_iir, FILTER_ORDER * sizeof(float));
 +    synthesis_filter(scratch, wcoef2, mem, length, scratch);
 +
 +    /* Gain computation, TIA/IS-127 5.9.4-2 */
 +    for (i = 0, sum1 = 0, sum2 = 0; i < length; i++) {
 +        sum1 += in[i] * in[i];
 +        sum2 += scratch[i] * scratch[i];
 +    }
 +    gain = sum2 ? sqrt(sum1 / sum2) : 1.0;
 +
 +    for (i = 0; i < length; i++)
 +        temp[i] *= gain;
 +
 +    /* Short term postfilter */
 +    synthesis_filter(temp, wcoef2, e->postfilter_iir, length, out);
 +
 +    memcpy(e->postfilter_residual,
 +           e->postfilter_residual + length, ACB_SIZE * sizeof(float));
 +}
 +
 +static void frame_erasure(EVRCContext *e, float *samples)
 +{
 +    float ilspf[FILTER_ORDER], ilpc[FILTER_ORDER], idelay[NB_SUBFRAMES],
 +          tmp[SUBFRAME_SIZE + 6], f;
 +    int i, j;
 +
 +    for (i = 0; i < FILTER_ORDER; i++) {
 +        if (e->bitrate != RATE_QUANT)
 +            e->lspf[i] = e->prev_lspf[i] * 0.875 + 0.125 * (i + 1) * 0.048;
 +        else
 +            e->lspf[i] = e->prev_lspf[i];
 +    }
 +
 +    if (e->prev_error_flag)
 +        e->avg_acb_gain *= 0.75;
 +    if (e->bitrate == RATE_FULL)
 +        memcpy(e->pitch_back, e->pitch, ACB_SIZE * sizeof(float));
 +    if (e->last_valid_bitrate == RATE_QUANT)
 +        e->bitrate = RATE_QUANT;
 +    else
 +        e->bitrate = RATE_FULL;
 +
 +    if (e->bitrate == RATE_FULL || e->bitrate == RATE_HALF) {
 +        e->pitch_delay = e->prev_pitch_delay;
 +    } else {
 +        float sum = 0;
 +
 +        idelay[0] = idelay[1] = idelay[2] = MIN_DELAY;
 +
 +        for (i = 0; i < NB_SUBFRAMES; i++)
 +            sum += evrc_energy_quant[e->prev_energy_gain][i];
 +        sum /= (float) NB_SUBFRAMES;
 +        sum  = pow(10, sum);
 +        for (i = 0; i < NB_SUBFRAMES; i++)
 +            e->energy_vector[i] = sum;
 +    }
 +
 +    if (fabs(e->pitch_delay - e->prev_pitch_delay) > 15)
 +        e->prev_pitch_delay = e->pitch_delay;
 +
 +    for (i = 0; i < NB_SUBFRAMES; i++) {
 +        int subframe_size = subframe_sizes[i];
 +        int pitch_lag;
 +
 +        interpolate_lsp(ilspf, e->lspf, e->prev_lspf, i);
 +
 +        if (e->bitrate != RATE_QUANT) {
 +            if (e->avg_acb_gain < 0.3) {
 +                idelay[0] = estimation_delay[i];
 +                idelay[1] = estimation_delay[i + 1];
 +                idelay[2] = estimation_delay[i + 2];
 +            } else {
 +                interpolate_delay(idelay, e->pitch_delay, e->prev_pitch_delay, i);
 +            }
 +        }
 +
 +        pitch_lag = lrintf((idelay[1] + idelay[0]) / 2.0);
 +        decode_predictor_coeffs(ilspf, ilpc);
 +
 +        if (e->bitrate != RATE_QUANT) {
 +            acb_excitation(e, e->pitch + ACB_SIZE,
 +                           e->avg_acb_gain, idelay, subframe_size);
 +            for (j = 0; j < subframe_size; j++)
 +                e->pitch[ACB_SIZE + j] *= e->fade_scale;
 +            e->fade_scale = FFMAX(e->fade_scale - 0.05, 0.0);
 +        } else {
 +            for (j = 0; j < subframe_size; j++)
 +                e->pitch[ACB_SIZE + j] = e->energy_vector[i];
 +        }
 +
 +        memcpy(e->pitch, e->pitch + subframe_size, ACB_SIZE * sizeof(float));
 +
 +        if (e->bitrate != RATE_QUANT && e->avg_acb_gain < 0.4) {
 +            f = 0.1 * e->avg_fcb_gain;
 +            for (j = 0; j < subframe_size; j++)
 +                e->pitch[ACB_SIZE + j] += f;
 +        } else if (e->bitrate == RATE_QUANT) {
 +            for (j = 0; j < subframe_size; j++)
 +                e->pitch[ACB_SIZE + j] = e->energy_vector[i];
 +        }
 +
 +        synthesis_filter(e->pitch + ACB_SIZE, ilpc,
 +                         e->synthesis, subframe_size, tmp);
 +        postfilter(e, tmp, ilpc, samples, pitch_lag,
 +                   &postfilter_coeffs[e->bitrate], subframe_size);
 +
 +        samples += subframe_size;
 +    }
 +}
 +
 +static int evrc_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame_ptr, AVPacket *avpkt)
 +{
 +    const uint8_t *buf = avpkt->data;
 +    AVFrame *frame     = data;
 +    EVRCContext *e     = avctx->priv_data;
 +    int buf_size       = avpkt->size;
 +    float ilspf[FILTER_ORDER], ilpc[FILTER_ORDER], idelay[NB_SUBFRAMES];
 +    float *samples;
 +    int   i, j, ret, error_flag = 0;
 +
 +    frame->nb_samples = 160;
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
 +        return ret;
 +    samples = (float *)frame->data[0];
 +
 +    if ((e->bitrate = determine_bitrate(avctx, &buf_size, &buf)) == RATE_ERRS) {
 +        warn_insufficient_frame_quality(avctx, "bitrate cannot be determined.");
 +        goto erasure;
 +    }
 +    if (e->bitrate <= SILENCE || e->bitrate == RATE_QUARTER)
 +        goto erasure;
 +    if (e->bitrate == RATE_QUANT && e->last_valid_bitrate == RATE_FULL
 +                                 && !e->prev_error_flag)
 +        goto erasure;
 +
 +    init_get_bits(&e->gb, buf, 8 * buf_size);
 +    memset(&e->frame, 0, sizeof(EVRCAFrame));
 +
 +    unpack_frame(e);
 +
 +    if (e->bitrate != RATE_QUANT) {
 +        uint8_t *p = (uint8_t *) &e->frame;
 +        for (i = 0; i < sizeof(EVRCAFrame); i++) {
 +            if (p[i])
 +                break;
 +        }
 +        if (i == sizeof(EVRCAFrame))
 +            goto erasure;
 +    } else if (e->frame.lsp[0] == 0xf &&
 +               e->frame.lsp[1] == 0xf &&
 +               e->frame.energy_gain == 0xff) {
 +        goto erasure;
 +    }
 +
 +    if (decode_lspf(e) < 0)
 +        goto erasure;
 +
 +    if (e->bitrate == RATE_FULL || e->bitrate == RATE_HALF) {
 +        /* Pitch delay parameter checking as per TIA/IS-127 5.1.5.1 */
 +        if (e->frame.pitch_delay > MAX_DELAY - MIN_DELAY)
 +            goto erasure;
 +
 +        e->pitch_delay = e->frame.pitch_delay + MIN_DELAY;
 +
 +        /* Delay diff parameter checking as per TIA/IS-127 5.1.5.2 */
 +        if (e->frame.delay_diff) {
 +            int p = e->pitch_delay - e->frame.delay_diff + 16;
 +            if (p < MIN_DELAY || p > MAX_DELAY)
 +                goto erasure;
 +        }
 +
 +        /* Delay contour reconstruction as per TIA/IS-127 5.2.2.2 */
 +        if (e->frame.delay_diff &&
 +            e->bitrate == RATE_FULL && e->prev_error_flag) {
 +            float delay;
 +
 +            memcpy(e->pitch, e->pitch_back, ACB_SIZE * sizeof(float));
 +
 +            delay = e->prev_pitch_delay;
 +            e->prev_pitch_delay = delay - e->frame.delay_diff + 16.0;
 +
 +            if (fabs(e->pitch_delay - delay) > 15)
 +                delay = e->pitch_delay;
 +
 +            for (i = 0; i < NB_SUBFRAMES; i++) {
 +                int subframe_size = subframe_sizes[i];
 +
 +                interpolate_delay(idelay, delay, e->prev_pitch_delay, i);
 +                acb_excitation(e, e->pitch + ACB_SIZE, e->avg_acb_gain, idelay, subframe_size);
 +                memcpy(e->pitch, e->pitch + subframe_size, ACB_SIZE * sizeof(float));
 +            }
 +        }
 +
 +        /* Smoothing of the decoded delay as per TIA/IS-127 5.2.2.5 */
 +        if (fabs(e->pitch_delay - e->prev_pitch_delay) > 15)
 +            e->prev_pitch_delay = e->pitch_delay;
 +
 +        e->avg_acb_gain = e->avg_fcb_gain = 0.0;
 +    } else {
 +        idelay[0] = idelay[1] = idelay[2] = MIN_DELAY;
 +
 +        /* Decode frame energy vectors as per TIA/IS-127 5.7.2 */
 +        for (i = 0; i < NB_SUBFRAMES; i++)
 +            e->energy_vector[i] = pow(10, evrc_energy_quant[e->frame.energy_gain][i]);
 +        e->prev_energy_gain = e->frame.energy_gain;
 +    }
 +
 +    for (i = 0; i < NB_SUBFRAMES; i++) {
 +        float tmp[SUBFRAME_SIZE + 6] = { 0 };
 +        int subframe_size = subframe_sizes[i];
 +        int pitch_lag;
 +
 +        interpolate_lsp(ilspf, e->lspf, e->prev_lspf, i);
 +
 +        if (e->bitrate != RATE_QUANT)
 +            interpolate_delay(idelay, e->pitch_delay, e->prev_pitch_delay, i);
 +
 +        pitch_lag = lrintf((idelay[1] + idelay[0]) / 2.0);
 +        decode_predictor_coeffs(ilspf, ilpc);
 +
 +        /* Bandwidth expansion as per TIA/IS-127 5.2.3.3 */
 +        if (e->frame.lpc_flag && e->prev_error_flag)
 +            bandwidth_expansion(ilpc, ilpc, 0.75);
 +
 +        if (e->bitrate != RATE_QUANT) {
 +            float acb_sum, f;
 +
 +            f = exp((e->bitrate == RATE_HALF ? 0.5 : 0.25)
 +                         * (e->frame.fcb_gain[i] + 1));
 +            acb_sum = pitch_gain_vq[e->frame.acb_gain[i]];
 +            e->avg_acb_gain += acb_sum / NB_SUBFRAMES;
 +            e->avg_fcb_gain += f / NB_SUBFRAMES;
 +
 +            acb_excitation(e, e->pitch + ACB_SIZE,
 +                           acb_sum, idelay, subframe_size);
 +            fcb_excitation(e, e->frame.fcb_shape[i], tmp,
 +                           acb_sum, pitch_lag, subframe_size);
 +
 +            /* Total excitation generation as per TIA/IS-127 5.2.3.9 */
 +            for (j = 0; j < subframe_size; j++)
 +                e->pitch[ACB_SIZE + j] += f * tmp[j];
 +            e->fade_scale = FFMIN(e->fade_scale + 0.2, 1.0);
 +        } else {
 +            for (j = 0; j < subframe_size; j++)
 +                e->pitch[ACB_SIZE + j] = e->energy_vector[i];
 +        }
 +
 +        memcpy(e->pitch, e->pitch + subframe_size, ACB_SIZE * sizeof(float));
 +
 +        synthesis_filter(e->pitch + ACB_SIZE, ilpc,
 +                         e->synthesis, subframe_size, tmp);
 +        postfilter(e, tmp, ilpc, samples, pitch_lag,
 +                   &postfilter_coeffs[e->bitrate], subframe_size);
 +
 +        samples += subframe_size;
 +    }
 +
 +    if (error_flag) {
 +erasure:
 +        error_flag = 1;
 +        av_log(avctx, AV_LOG_WARNING, "frame erasure\n");
 +        frame_erasure(e, samples);
 +    }
 +
 +    memcpy(e->prev_lspf, e->lspf, sizeof(e->prev_lspf));
 +    e->prev_error_flag    = error_flag;
 +    e->last_valid_bitrate = e->bitrate;
 +
 +    if (e->bitrate != RATE_QUANT)
 +        e->prev_pitch_delay = e->pitch_delay;
 +
 +    samples = (float *)frame->data[0];
 +    for (i = 0; i < 160; i++)
 +        samples[i] /= 32768;
 +
 +    *got_frame_ptr   = 1;
 +
 +    return avpkt->size;
 +}
 +
 +AVCodec ff_evrc_decoder = {
 +    .name           = "evrc",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_EVRC,
 +    .init           = evrc_decode_init,
 +    .decode         = evrc_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .priv_data_size = sizeof(EVRCContext),
 +    .long_name      = NULL_IF_CONFIG_SMALL("EVRC (Enhanced Variable Rate Codec)"),
 +};
index 1432817,0000000..cc0995c
mode 100644,000000..100644
--- /dev/null
@@@ -1,830 -1,0 +1,814 @@@
-     AVFrame picture;
 +/*
 + * OpenEXR (.exr) image decoder
 + * Copyright (c) 2009 Jimmy Christensen
 + *
 + * 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
 + * OpenEXR decoder
 + * @author Jimmy Christensen
 + *
 + * For more information on the OpenEXR format, visit:
 + *  http://openexr.com/
 + *
 + * exr_flt2uint() and exr_halflt2uint() is credited to  Reimar Döffinger
 + */
 +
 +#include <zlib.h>
 +
 +#include "avcodec.h"
 +#include "bytestream.h"
 +#include "mathops.h"
 +#include "thread.h"
 +#include "libavutil/imgutils.h"
 +#include "libavutil/avassert.h"
 +
 +enum ExrCompr {
 +    EXR_RAW   = 0,
 +    EXR_RLE   = 1,
 +    EXR_ZIP1  = 2,
 +    EXR_ZIP16 = 3,
 +    EXR_PIZ   = 4,
 +    EXR_PXR24 = 5,
 +    EXR_B44   = 6,
 +    EXR_B44A  = 7,
 +};
 +
 +enum ExrPixelType {
 +    EXR_UINT,
 +    EXR_HALF,
 +    EXR_FLOAT
 +};
 +
 +typedef struct EXRChannel {
 +    int               xsub, ysub;
 +    enum ExrPixelType pixel_type;
 +} EXRChannel;
 +
 +typedef struct EXRThreadData {
 +    uint8_t *uncompressed_data;
 +    int uncompressed_size;
 +
 +    uint8_t *tmp;
 +    int tmp_size;
 +} EXRThreadData;
 +
 +typedef struct EXRContext {
-     AVFrame *const p = &s->picture;
++    AVFrame *picture;
 +    int compr;
 +    enum ExrPixelType pixel_type;
 +    int channel_offsets[4]; // 0 = red, 1 = green, 2 = blue and 3 = alpha
 +    const AVPixFmtDescriptor *desc;
 +
 +    uint32_t xmax, xmin;
 +    uint32_t ymax, ymin;
 +    uint32_t xdelta, ydelta;
 +
 +    int ysize;
 +
 +    uint64_t scan_line_size;
 +    int scan_lines_per_block;
 +
 +    const uint8_t *buf, *table;
 +    int buf_size;
 +
 +    EXRChannel *channels;
 +    int nb_channels;
 +
 +    EXRThreadData *thread_data;
 +    int thread_data_size;
 +} EXRContext;
 +
 +/**
 + * Converts from 32-bit float as uint32_t to uint16_t
 + *
 + * @param v 32-bit float
 + * @return normalized 16-bit unsigned int
 + */
 +static inline uint16_t exr_flt2uint(uint32_t v)
 +{
 +    unsigned int exp = v >> 23;
 +    // "HACK": negative values result in exp<  0, so clipping them to 0
 +    // is also handled by this condition, avoids explicit check for sign bit.
 +    if (exp<= 127 + 7 - 24) // we would shift out all bits anyway
 +        return 0;
 +    if (exp >= 127)
 +        return 0xffff;
 +    v &= 0x007fffff;
 +    return (v + (1 << 23)) >> (127 + 7 - exp);
 +}
 +
 +/**
 + * Converts from 16-bit float as uint16_t to uint16_t
 + *
 + * @param v 16-bit float
 + * @return normalized 16-bit unsigned int
 + */
 +static inline uint16_t exr_halflt2uint(uint16_t v)
 +{
 +    unsigned exp = 14 - (v >> 10);
 +    if (exp >= 14) {
 +        if (exp == 14) return (v >> 9) & 1;
 +        else           return (v & 0x8000) ? 0 : 0xffff;
 +    }
 +    v <<= 6;
 +    return (v + (1 << 16)) >> (exp + 1);
 +}
 +
 +/**
 + * Gets the size of the header variable
 + *
 + * @param **buf the current pointer location in the header where
 + * the variable data starts
 + * @param *buf_end pointer location of the end of the buffer
 + * @return size of variable data
 + */
 +static unsigned int get_header_variable_length(const uint8_t **buf,
 +                                               const uint8_t *buf_end)
 +{
 +    unsigned int variable_buffer_data_size = bytestream_get_le32(buf);
 +    if (variable_buffer_data_size >= buf_end - *buf)
 +        return 0;
 +    return variable_buffer_data_size;
 +}
 +
 +/**
 + * Checks if the variable name corresponds with it's data type
 + *
 + * @param *avctx the AVCodecContext
 + * @param **buf the current pointer location in the header where
 + * the variable name starts
 + * @param *buf_end pointer location of the end of the buffer
 + * @param *value_name name of the varible to check
 + * @param *value_type type of the varible to check
 + * @param minimum_length minimum length of the variable data
 + * @param variable_buffer_data_size variable length read from the header
 + * after it's checked
 + * @return negative if variable is invalid
 + */
 +static int check_header_variable(AVCodecContext *avctx,
 +                                              const uint8_t **buf,
 +                                              const uint8_t *buf_end,
 +                                              const char *value_name,
 +                                              const char *value_type,
 +                                              unsigned int minimum_length,
 +                                              unsigned int *variable_buffer_data_size)
 +{
 +    if (buf_end - *buf >= minimum_length && !strcmp(*buf, value_name)) {
 +        *buf += strlen(value_name)+1;
 +        if (!strcmp(*buf, value_type)) {
 +            *buf += strlen(value_type)+1;
 +            *variable_buffer_data_size = get_header_variable_length(buf, buf_end);
 +            if (!*variable_buffer_data_size)
 +                av_log(avctx, AV_LOG_ERROR, "Incomplete header\n");
 +            return 1;
 +        }
 +        *buf -= strlen(value_name)+1;
 +        av_log(avctx, AV_LOG_WARNING, "Unknown data type for header variable %s\n", value_name);
 +    }
 +    return -1;
 +}
 +
 +static void predictor(uint8_t *src, int size)
 +{
 +    uint8_t *t = src + 1;
 +    uint8_t *stop = src + size;
 +
 +    while (t < stop) {
 +        int d = (int)t[-1] + (int)t[0] - 128;
 +        t[0] = d;
 +        ++t;
 +    }
 +}
 +
 +static void reorder_pixels(uint8_t *src, uint8_t *dst, int size)
 +{
 +    const int8_t *t1 = src;
 +    const int8_t *t2 = src + (size + 1) / 2;
 +    int8_t *s = dst;
 +    int8_t *stop = s + size;
 +
 +    while (1) {
 +        if (s < stop)
 +            *(s++) = *(t1++);
 +        else
 +            break;
 +
 +        if (s < stop)
 +            *(s++) = *(t2++);
 +        else
 +            break;
 +    }
 +}
 +
 +static int zip_uncompress(const uint8_t *src, int compressed_size,
 +                          int uncompressed_size, EXRThreadData *td)
 +{
 +    unsigned long dest_len = uncompressed_size;
 +
 +    if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK ||
 +        dest_len != uncompressed_size)
 +        return AVERROR(EINVAL);
 +
 +    predictor(td->tmp, uncompressed_size);
 +    reorder_pixels(td->tmp, td->uncompressed_data, uncompressed_size);
 +
 +    return 0;
 +}
 +
 +static int rle_uncompress(const uint8_t *src, int compressed_size,
 +                          int uncompressed_size, EXRThreadData *td)
 +{
 +    int8_t *d = (int8_t *)td->tmp;
 +    const int8_t *s = (const int8_t *)src;
 +    int ssize = compressed_size;
 +    int dsize = uncompressed_size;
 +    int8_t *dend = d + dsize;
 +    int count;
 +
 +    while (ssize > 0) {
 +        count = *s++;
 +
 +        if (count < 0) {
 +            count = -count;
 +
 +            if ((dsize -= count    ) < 0 ||
 +                (ssize -= count + 1) < 0)
 +                return -1;
 +
 +            while (count--)
 +                *d++ = *s++;
 +        } else {
 +            count++;
 +
 +            if ((dsize -= count) < 0 ||
 +                (ssize -= 2    ) < 0)
 +                return -1;
 +
 +            while (count--)
 +                *d++ = *s;
 +
 +            s++;
 +        }
 +    }
 +
 +    if (dend != d)
 +        return AVERROR_INVALIDDATA;
 +
 +    predictor(td->tmp, uncompressed_size);
 +    reorder_pixels(td->tmp, td->uncompressed_data, uncompressed_size);
 +
 +    return 0;
 +}
 +
 +static int pxr24_uncompress(EXRContext *s, const uint8_t *src,
 +                            int compressed_size, int uncompressed_size,
 +                            EXRThreadData *td)
 +{
 +    unsigned long dest_len = uncompressed_size;
 +    const uint8_t *in = td->tmp;
 +    uint8_t *out;
 +    int c, i, j;
 +
 +    if (uncompress(td->tmp, &dest_len, src, compressed_size) != Z_OK ||
 +        dest_len != uncompressed_size)
 +        return AVERROR(EINVAL);
 +
 +    out = td->uncompressed_data;
 +    for (i = 0; i < s->ysize; i++) {
 +        for (c = 0; c < s->nb_channels; c++) {
 +            EXRChannel *channel = &s->channels[c];
 +            const uint8_t *ptr[4];
 +            uint32_t pixel = 0;
 +
 +            switch (channel->pixel_type) {
 +            case EXR_FLOAT:
 +                ptr[0] = in;
 +                ptr[1] = ptr[0] + s->xdelta;
 +                ptr[2] = ptr[1] + s->xdelta;
 +                in = ptr[2] + s->xdelta;
 +
 +                for (j = 0; j < s->xdelta; ++j) {
 +                    uint32_t diff = (*(ptr[0]++) << 24) |
 +                                    (*(ptr[1]++) << 16) |
 +                                    (*(ptr[2]++) <<  8);
 +                    pixel += diff;
 +                    bytestream_put_le32(&out, pixel);
 +                }
 +                break;
 +            case EXR_HALF:
 +                ptr[0] = in;
 +                ptr[1] = ptr[0] + s->xdelta;
 +                in = ptr[1] + s->xdelta;
 +                for (j = 0; j < s->xdelta; j++) {
 +                    uint32_t diff = (*(ptr[0]++) << 8) | *(ptr[1]++);
 +
 +                    pixel += diff;
 +                    bytestream_put_le16(&out, pixel);
 +                }
 +                break;
 +            default:
 +                av_assert1(0);
 +            }
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_block(AVCodecContext *avctx, void *tdata,
 +                        int jobnr, int threadnr)
 +{
 +    EXRContext *s = avctx->priv_data;
-     AVFrame *const p = &s->picture;
++    AVFrame *const p = s->picture;
 +    EXRThreadData *td = &s->thread_data[threadnr];
 +    const uint8_t *channel_buffer[4] = { 0 };
 +    const uint8_t *buf = s->buf;
 +    uint64_t line_offset, uncompressed_size;
 +    uint32_t xdelta = s->xdelta;
 +    uint16_t *ptr_x;
 +    uint8_t *ptr;
 +    int32_t data_size, line;
 +    const uint8_t *src;
 +    int axmax = (avctx->width - (s->xmax + 1)) * 2 * s->desc->nb_components;
 +    int bxmin = s->xmin * 2 * s->desc->nb_components;
 +    int ret, i, x, buf_size = s->buf_size;
 +
 +    line_offset = AV_RL64(s->table + jobnr * 8);
 +    // Check if the buffer has the required bytes needed from the offset
 +    if (line_offset > buf_size - 8)
 +        return AVERROR_INVALIDDATA;
 +
 +    src = buf + line_offset + 8;
 +    line = AV_RL32(src - 8);
 +    if (line < s->ymin || line > s->ymax)
 +        return AVERROR_INVALIDDATA;
 +
 +    data_size = AV_RL32(src - 4);
 +    if (data_size <= 0 || data_size > buf_size)
 +        return AVERROR_INVALIDDATA;
 +
 +    s->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1);
 +    uncompressed_size = s->scan_line_size * s->ysize;
 +    if ((s->compr == EXR_RAW && (data_size != uncompressed_size ||
 +                                 line_offset > buf_size - uncompressed_size)) ||
 +        (s->compr != EXR_RAW && (data_size > uncompressed_size ||
 +                                 line_offset > buf_size - data_size))) {
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (data_size < uncompressed_size) {
 +        av_fast_padded_malloc(&td->uncompressed_data, &td->uncompressed_size, uncompressed_size);
 +        av_fast_padded_malloc(&td->tmp, &td->tmp_size, uncompressed_size);
 +        if (!td->uncompressed_data || !td->tmp)
 +            return AVERROR(ENOMEM);
 +
 +        switch (s->compr) {
 +        case EXR_ZIP1:
 +        case EXR_ZIP16:
 +            ret = zip_uncompress(src, data_size, uncompressed_size, td);
 +            break;
 +        case EXR_PXR24:
 +            ret = pxr24_uncompress(s, src, data_size, uncompressed_size, td);
 +            break;
 +        case EXR_RLE:
 +            ret = rle_uncompress(src, data_size, uncompressed_size, td);
 +        }
 +
 +        src = td->uncompressed_data;
 +    }
 +
 +    channel_buffer[0] = src + xdelta * s->channel_offsets[0];
 +    channel_buffer[1] = src + xdelta * s->channel_offsets[1];
 +    channel_buffer[2] = src + xdelta * s->channel_offsets[2];
 +    if (s->channel_offsets[3] >= 0)
 +        channel_buffer[3] = src + xdelta * s->channel_offsets[3];
 +
 +    ptr = p->data[0] + line * p->linesize[0];
 +    for (i = 0; i < s->scan_lines_per_block && line + i <= s->ymax; i++, ptr += p->linesize[0]) {
 +        const uint8_t *r, *g, *b, *a;
 +
 +        r = channel_buffer[0];
 +        g = channel_buffer[1];
 +        b = channel_buffer[2];
 +        if (channel_buffer[3])
 +            a = channel_buffer[3];
 +
 +        ptr_x = (uint16_t *)ptr;
 +
 +        // Zero out the start if xmin is not 0
 +        memset(ptr_x, 0, bxmin);
 +        ptr_x += s->xmin * s->desc->nb_components;
 +        if (s->pixel_type == EXR_FLOAT) {
 +            // 32-bit
 +            for (x = 0; x < xdelta; x++) {
 +                *ptr_x++ = exr_flt2uint(bytestream_get_le32(&r));
 +                *ptr_x++ = exr_flt2uint(bytestream_get_le32(&g));
 +                *ptr_x++ = exr_flt2uint(bytestream_get_le32(&b));
 +                if (channel_buffer[3])
 +                    *ptr_x++ = exr_flt2uint(bytestream_get_le32(&a));
 +            }
 +        } else {
 +            // 16-bit
 +            for (x = 0; x < xdelta; x++) {
 +                *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&r));
 +                *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&g));
 +                *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&b));
 +                if (channel_buffer[3])
 +                    *ptr_x++ = exr_halflt2uint(bytestream_get_le16(&a));
 +            }
 +        }
 +
 +        // Zero out the end if xmax+1 is not w
 +        memset(ptr_x, 0, axmax);
 +
 +        channel_buffer[0] += s->scan_line_size;
 +        channel_buffer[1] += s->scan_line_size;
 +        channel_buffer[2] += s->scan_line_size;
 +        if (channel_buffer[3])
 +            channel_buffer[3] += s->scan_line_size;
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx,
 +                        void *data,
 +                        int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    const uint8_t *buf      = avpkt->data;
 +    unsigned int   buf_size = avpkt->size;
 +    const uint8_t *buf_end  = buf + buf_size;
 +
 +    EXRContext *const s = avctx->priv_data;
++    ThreadFrame frame = { .f = data };
 +    AVFrame *picture  = data;
-     if (s->picture.data[0])
-         ff_thread_release_buffer(avctx, &s->picture);
 +    uint8_t *ptr;
 +
 +    int i, y, magic_number, version, flags, ret;
 +    int w = 0;
 +    int h = 0;
 +
 +    int out_line_size;
 +    int scan_line_blocks;
 +
 +    unsigned int current_channel_offset = 0;
 +
 +    s->xmin = ~0;
 +    s->xmax = ~0;
 +    s->ymin = ~0;
 +    s->ymax = ~0;
 +    s->xdelta = ~0;
 +    s->ydelta = ~0;
 +    s->channel_offsets[0] = -1;
 +    s->channel_offsets[1] = -1;
 +    s->channel_offsets[2] = -1;
 +    s->channel_offsets[3] = -1;
 +    s->pixel_type = -1;
 +    s->nb_channels = 0;
 +    s->compr = -1;
 +    s->buf = buf;
 +    s->buf_size = buf_size;
 +
 +    if (buf_size < 10) {
 +        av_log(avctx, AV_LOG_ERROR, "Too short header to parse\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    magic_number = bytestream_get_le32(&buf);
 +    if (magic_number != 20000630) { // As per documentation of OpenEXR it's supposed to be int 20000630 little-endian
 +        av_log(avctx, AV_LOG_ERROR, "Wrong magic number %d\n", magic_number);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    version = bytestream_get_byte(&buf);
 +    if (version != 2) {
 +        av_log(avctx, AV_LOG_ERROR, "Unsupported version %d\n", version);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    flags = bytestream_get_le24(&buf);
 +    if (flags & 0x2) {
 +        av_log(avctx, AV_LOG_ERROR, "Tile based images are not supported\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    // Parse the header
 +    while (buf < buf_end && buf[0]) {
 +        unsigned int variable_buffer_data_size;
 +        // Process the channel list
 +        if (check_header_variable(avctx, &buf, buf_end, "channels", "chlist", 38, &variable_buffer_data_size) >= 0) {
 +            const uint8_t *channel_list_end;
 +            if (!variable_buffer_data_size)
 +                return AVERROR_INVALIDDATA;
 +
 +            channel_list_end = buf + variable_buffer_data_size;
 +            while (channel_list_end - buf >= 19) {
 +                EXRChannel *channel;
 +                int current_pixel_type = -1;
 +                int channel_index = -1;
 +                int xsub, ysub;
 +
 +                if (!strcmp(buf, "R"))
 +                    channel_index = 0;
 +                else if (!strcmp(buf, "G"))
 +                    channel_index = 1;
 +                else if (!strcmp(buf, "B"))
 +                    channel_index = 2;
 +                else if (!strcmp(buf, "A"))
 +                    channel_index = 3;
 +                else
 +                    av_log(avctx, AV_LOG_WARNING, "Unsupported channel %.256s\n", buf);
 +
 +                while (bytestream_get_byte(&buf) && buf < channel_list_end)
 +                    continue; /* skip */
 +
 +                if (channel_list_end - * &buf < 4) {
 +                    av_log(avctx, AV_LOG_ERROR, "Incomplete header\n");
 +                    return AVERROR_INVALIDDATA;
 +                }
 +
 +                current_pixel_type = bytestream_get_le32(&buf);
 +                if (current_pixel_type > 2) {
 +                    av_log(avctx, AV_LOG_ERROR, "Unknown pixel type\n");
 +                    return AVERROR_INVALIDDATA;
 +                }
 +
 +                buf += 4;
 +                xsub = bytestream_get_le32(&buf);
 +                ysub = bytestream_get_le32(&buf);
 +                if (xsub != 1 || ysub != 1) {
 +                    av_log(avctx, AV_LOG_ERROR, "Unsupported subsampling %dx%d\n", xsub, ysub);
 +                    return AVERROR_PATCHWELCOME;
 +                }
 +
 +                if (channel_index >= 0) {
 +                    if (s->pixel_type != -1 && s->pixel_type != current_pixel_type) {
 +                        av_log(avctx, AV_LOG_ERROR, "RGB channels not of the same depth\n");
 +                        return AVERROR_INVALIDDATA;
 +                    }
 +                    s->pixel_type = current_pixel_type;
 +                    s->channel_offsets[channel_index] = current_channel_offset;
 +                }
 +
 +                s->channels = av_realloc_f(s->channels, ++s->nb_channels, sizeof(EXRChannel));
 +                if (!s->channels)
 +                    return AVERROR(ENOMEM);
 +                channel = &s->channels[s->nb_channels - 1];
 +                channel->pixel_type = current_pixel_type;
 +                channel->xsub = xsub;
 +                channel->ysub = ysub;
 +
 +                current_channel_offset += 1 << current_pixel_type;
 +            }
 +
 +            /* Check if all channels are set with an offset or if the channels
 +             * are causing an overflow  */
 +
 +            if (FFMIN3(s->channel_offsets[0],
 +                       s->channel_offsets[1],
 +                       s->channel_offsets[2]) < 0) {
 +                if (s->channel_offsets[0] < 0)
 +                    av_log(avctx, AV_LOG_ERROR, "Missing red channel\n");
 +                if (s->channel_offsets[1] < 0)
 +                    av_log(avctx, AV_LOG_ERROR, "Missing green channel\n");
 +                if (s->channel_offsets[2] < 0)
 +                    av_log(avctx, AV_LOG_ERROR, "Missing blue channel\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +
 +            buf = channel_list_end;
 +            continue;
 +        } else if (check_header_variable(avctx, &buf, buf_end, "dataWindow", "box2i", 31, &variable_buffer_data_size) >= 0) {
 +            if (!variable_buffer_data_size)
 +                return AVERROR_INVALIDDATA;
 +
 +            s->xmin = AV_RL32(buf);
 +            s->ymin = AV_RL32(buf + 4);
 +            s->xmax = AV_RL32(buf + 8);
 +            s->ymax = AV_RL32(buf + 12);
 +            s->xdelta = (s->xmax - s->xmin) + 1;
 +            s->ydelta = (s->ymax - s->ymin) + 1;
 +
 +            buf += variable_buffer_data_size;
 +            continue;
 +        } else if (check_header_variable(avctx, &buf, buf_end, "displayWindow", "box2i", 34, &variable_buffer_data_size) >= 0) {
 +            if (!variable_buffer_data_size)
 +                return AVERROR_INVALIDDATA;
 +
 +            w = AV_RL32(buf + 8) + 1;
 +            h = AV_RL32(buf + 12) + 1;
 +
 +            buf += variable_buffer_data_size;
 +            continue;
 +        } else if (check_header_variable(avctx, &buf, buf_end, "lineOrder", "lineOrder", 25, &variable_buffer_data_size) >= 0) {
 +            if (!variable_buffer_data_size)
 +                return AVERROR_INVALIDDATA;
 +
 +            av_log(avctx, AV_LOG_DEBUG, "line order : %d\n", *buf);
 +            if (*buf > 2) {
 +                av_log(avctx, AV_LOG_ERROR, "Unknown line order\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +
 +            buf += variable_buffer_data_size;
 +            continue;
 +        } else if (check_header_variable(avctx, &buf, buf_end, "pixelAspectRatio", "float", 31, &variable_buffer_data_size) >= 0) {
 +            if (!variable_buffer_data_size)
 +                return AVERROR_INVALIDDATA;
 +
 +            avctx->sample_aspect_ratio = av_d2q(av_int2float(AV_RL32(buf)), 255);
 +
 +            buf += variable_buffer_data_size;
 +            continue;
 +        } else if (check_header_variable(avctx, &buf, buf_end, "compression", "compression", 29, &variable_buffer_data_size) >= 0) {
 +            if (!variable_buffer_data_size)
 +                return AVERROR_INVALIDDATA;
 +
 +            if (s->compr == -1)
 +                s->compr = *buf;
 +            else
 +                av_log(avctx, AV_LOG_WARNING, "Found more than one compression attribute\n");
 +
 +            buf += variable_buffer_data_size;
 +            continue;
 +        }
 +
 +        // Check if there is enough bytes for a header
 +        if (buf_end - buf <= 9) {
 +            av_log(avctx, AV_LOG_ERROR, "Incomplete header\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        // Process unknown variables
 +        for (i = 0; i < 2; i++) {
 +            // Skip variable name/type
 +            while (++buf < buf_end)
 +                if (buf[0] == 0x0)
 +                    break;
 +        }
 +        buf++;
 +        // Skip variable length
 +        if (buf_end - buf >= 5) {
 +            variable_buffer_data_size = get_header_variable_length(&buf, buf_end);
 +            if (!variable_buffer_data_size) {
 +                av_log(avctx, AV_LOG_ERROR, "Incomplete header\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +            buf += variable_buffer_data_size;
 +        }
 +    }
 +
 +    if (s->compr == -1) {
 +        av_log(avctx, AV_LOG_ERROR, "Missing compression attribute\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (buf >= buf_end) {
 +        av_log(avctx, AV_LOG_ERROR, "Incomplete frame\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +    buf++;
 +
 +    switch (s->pixel_type) {
 +    case EXR_FLOAT:
 +    case EXR_HALF:
 +        if (s->channel_offsets[3] >= 0)
 +            avctx->pix_fmt = AV_PIX_FMT_RGBA64;
 +        else
 +            avctx->pix_fmt = AV_PIX_FMT_RGB48;
 +        break;
 +    case EXR_UINT:
 +        av_log_missing_feature(avctx, "32-bit unsigned int", 1);
 +        return AVERROR_PATCHWELCOME;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "Missing channel list\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    switch (s->compr) {
 +    case EXR_RAW:
 +    case EXR_RLE:
 +    case EXR_ZIP1:
 +        s->scan_lines_per_block = 1;
 +        break;
 +    case EXR_PXR24:
 +    case EXR_ZIP16:
 +        s->scan_lines_per_block = 16;
 +        break;
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "Compression type %d is not supported\n", s->compr);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
-     if ((ret = ff_thread_get_buffer(avctx, p)) < 0) {
 +    if (av_image_check_size(w, h, 0, avctx))
 +        return AVERROR_INVALIDDATA;
 +
 +    // Verify the xmin, xmax, ymin, ymax and xdelta before setting the actual image size
 +    if (s->xmin > s->xmax ||
 +        s->ymin > s->ymax ||
 +        s->xdelta != s->xmax - s->xmin + 1 ||
 +        s->xmax >= w || s->ymax >= h) {
 +        av_log(avctx, AV_LOG_ERROR, "Wrong sizing or missing size information\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (w != avctx->width || h != avctx->height) {
 +        avcodec_set_dimensions(avctx, w, h);
 +    }
 +
 +    s->desc = av_pix_fmt_desc_get(avctx->pix_fmt);
 +    out_line_size = avctx->width * 2 * s->desc->nb_components;
 +    s->scan_line_size = s->xdelta * current_channel_offset;
 +    scan_line_blocks = (s->ydelta + s->scan_lines_per_block - 1) / s->scan_lines_per_block;
 +
 +    if (s->compr != EXR_RAW) {
 +        size_t thread_data_size, prev_size;
 +        EXRThreadData *m;
 +
 +        prev_size = s->thread_data_size;
 +        if (av_size_mult(avctx->thread_count, sizeof(EXRThreadData), &thread_data_size))
 +            return AVERROR(EINVAL);
 +
 +        m = av_fast_realloc(s->thread_data, &s->thread_data_size, thread_data_size);
 +        if (!m)
 +            return AVERROR(ENOMEM);
 +        s->thread_data = m;
 +        memset(s->thread_data + prev_size, 0, s->thread_data_size - prev_size);
 +    }
 +
-     ptr = p->data[0];
++    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +
 +    if (buf_end - buf < scan_line_blocks * 8)
 +        return AVERROR_INVALIDDATA;
 +    s->table = buf;
-         ptr += p->linesize[0];
++    ptr = picture->data[0];
 +
 +    // Zero out the start if ymin is not 0
 +    for (y = 0; y < s->ymin; y++) {
 +        memset(ptr, 0, out_line_size);
-         ptr += p->linesize[0];
++        ptr += picture->linesize[0];
 +    }
 +
++    s->picture = picture;
 +    avctx->execute2(avctx, decode_block, s->thread_data, NULL, scan_line_blocks);
 +
 +    // Zero out the end if ymax+1 is not h
 +    for (y = s->ymax + 1; y < avctx->height; y++) {
 +        memset(ptr, 0, out_line_size);
-     *picture   = s->picture;
++        ptr += picture->linesize[0];
 +    }
 +
- static av_cold int decode_init(AVCodecContext *avctx)
- {
-     EXRContext *s = avctx->priv_data;
-     avcodec_get_frame_defaults(&s->picture);
-     avctx->coded_frame = &s->picture;
-     return 0;
- }
 +    *got_frame = 1;
 +
 +    return buf_size;
 +}
 +
-     if (s->picture.data[0])
-         avctx->release_buffer(avctx, &s->picture);
 +static av_cold int decode_end(AVCodecContext *avctx)
 +{
 +    EXRContext *s = avctx->priv_data;
 +    int i;
 +
-     .init               = decode_init,
 +    for (i = 0; i < s->thread_data_size / sizeof(EXRThreadData); i++) {
 +        EXRThreadData *td = &s->thread_data[i];
 +        av_free(td->uncompressed_data);
 +        av_free(td->tmp);
 +    }
 +
 +    av_freep(&s->thread_data);
 +    s->thread_data_size = 0;
 +    av_freep(&s->channels);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_exr_decoder = {
 +    .name               = "exr",
 +    .type               = AVMEDIA_TYPE_VIDEO,
 +    .id                 = AV_CODEC_ID_EXR,
 +    .priv_data_size     = sizeof(EXRContext),
 +    .close              = decode_end,
 +    .decode             = decode_frame,
 +    .capabilities       = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS,
 +    .long_name          = NULL_IF_CONFIG_SMALL("OpenEXR image"),
 +};
Simple merge
@@@ -89,11 -79,12 +89,12 @@@ typedef struct FFV1Context 
      int transparency;
      int flags;
      int picture_number;
-     AVFrame picture;
-     AVFrame last_picture;
+     AVFrame picture, last_picture;
+     AVFrame *cur;
      int plane_count;
 -    int ac;     // 1 = range coder <-> 0 = golomb rice
 -    int ac_byte_count;      // number of bytes used for AC coding
 +    int ac;                              ///< 1=range coder <-> 0=golomb rice
 +    int ac_byte_count;                   ///< number of bytes used for AC coding
      PlaneContext plane[MAX_PLANES];
      int16_t quant_table[MAX_CONTEXT_INPUTS][256];
      int16_t quant_tables[MAX_QUANT_TABLES][MAX_CONTEXT_INPUTS][256];
@@@ -322,15 -332,15 +322,15 @@@ static int decode_slice_header(FFV1Cont
  
  static int decode_slice(AVCodecContext *c, void *arg)
  {
 -    FFV1Context *fs = *(void **)arg;
 -    FFV1Context *f  = fs->avctx->priv_data;
 +    FFV1Context *fs   = *(void **)arg;
 +    FFV1Context *f    = fs->avctx->priv_data;
      int width, height, x, y, ret;
 -    const int ps = (av_pix_fmt_desc_get(c->pix_fmt)->flags & PIX_FMT_PLANAR)
 -                   ? (c->bits_per_raw_sample > 8) + 1
 -                   : 4;
 -    AVFrame *const p = f->cur;
 +    const int ps      = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step_minus1 + 1;
-     AVFrame * const p = &f->picture;
++    AVFrame * const p = f->cur;
  
      if (f->version > 2) {
 +        if (ffv1_init_slice_state(f, fs) < 0)
 +            return AVERROR(ENOMEM);
          if (decode_slice_header(f, fs) < 0) {
              fs->slice_damaged = 1;
              return AVERROR_INVALIDDATA;
      }
      if ((ret = ffv1_init_slice_state(f, fs)) < 0)
          return ret;
-     if (f->picture.key_frame)
+     if (f->cur->key_frame)
          ffv1_clear_slice_state(f, fs);
 +
      width  = fs->slice_width;
      height = fs->slice_height;
      x      = fs->slice_x;
@@@ -806,14 -864,13 +801,16 @@@ static int decode_frame(AVCodecContext 
              ff_init_range_decoder(&fs->c, buf_p, v);
          } else
              fs->c.bytestream_end = (uint8_t *)(buf_p + v);
+         fs->cur = p;
      }
  
 -    avctx->execute(avctx, decode_slice, &f->slice_context[0], NULL,
 +    avctx->execute(avctx,
 +                   decode_slice,
 +                   &f->slice_context[0],
 +                   NULL,
                     f->slice_count,
 -                   sizeof(void *));
 +                   sizeof(void*));
  
      for (i = f->slice_count - 1; i >= 0; i--) {
          FFV1Context *fs = f->slice_context[i];
              const uint8_t *src[4];
              uint8_t *dst[4];
              for (j = 0; j < 4; j++) {
 -                int sh = (j == 1 || j == 2) ? f->chroma_h_shift : 0;
 -                int sv = (j == 1 || j == 2) ? f->chroma_v_shift : 0;
 -                dst[j] = p->data[j] + p->linesize[j] *
 -                         (fs->slice_y >> sv) + (fs->slice_x >> sh);
 -                src[j] = f->last_picture.data[j] +
 -                         f->last_picture.linesize[j] *
 -                         (fs->slice_y >> sv) + (fs->slice_x >> sh);
 +                int sh = (j==1 || j==2) ? f->chroma_h_shift : 0;
 +                int sv = (j==1 || j==2) ? f->chroma_v_shift : 0;
-                 dst[j] = f->picture     .data[j] + f->picture     .linesize[j]*
++                dst[j] = p->data[j] + p->linesize[j]*
 +                         (fs->slice_y>>sv) + (fs->slice_x>>sh);
 +                src[j] = f->last_picture.data[j] + f->last_picture.linesize[j]*
 +                         (fs->slice_y>>sv) + (fs->slice_x>>sh);
              }
-             av_image_copy(dst,
-                           f->picture.linesize,
-                           (const uint8_t **)src,
+             av_image_copy(dst, p->linesize, (const uint8_t **)src,
                            f->last_picture.linesize,
 -                          avctx->pix_fmt, fs->slice_width,
 +                          avctx->pix_fmt,
 +                          fs->slice_width,
                            fs->slice_height);
          }
      }
index eb3b455,0000000..4f392f2
mode 100644,000000..100644
--- /dev/null
@@@ -1,484 -1,0 +1,484 @@@
-     r = ff_get_buffer(avc, &ws->frame);
 +/*
 + * Wavesynth pseudo-codec
 + * Copyright (c) 2011 Nicolas George
 + *
 + * 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/log.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +
 +
 +#define SIN_BITS 14
 +#define WS_MAX_CHANNELS 32
 +#define INF_TS 0x7FFFFFFFFFFFFFFF
 +
 +#define PINK_UNIT 128
 +
 +/*
 +   Format of the extradata and packets
 +
 +   THIS INFORMATION IS NOT PART OF THE PUBLIC API OR ABI.
 +   IT CAN CHANGE WITHOUT NOTIFICATION.
 +
 +   All numbers are in little endian.
 +
 +   The codec extradata define a set of intervals with uniform content.
 +   Overlapping intervals are added together.
 +
 +   extradata:
 +       uint32      number of intervals
 +       ...         intervals
 +
 +   interval:
 +       int64       start timestamp; time_base must be 1/sample_rate;
 +                   start timestamps must be in ascending order
 +       int64       end timestamp
 +       uint32      type
 +       uint32      channels mask
 +       ...         additional information, depends on type
 +
 +   sine interval (type fourcc "SINE"):
 +       int32       start frequency, in 1/(1<<16) Hz
 +       int32       end frequency
 +       int32       start amplitude, 1<<16 is the full amplitude
 +       int32       end amplitude
 +       uint32      start phase, 0 is sin(0), 0x20000000 is sin(pi/2), etc.;
 +                   n | (1<<31) means to match the phase of previous channel #n
 +
 +   pink noise interval (type fourcc "NOIS"):
 +       int32       start amplitude
 +       int32       end amplitude
 +
 +   The input packets encode the time and duration of the requested segment.
 +
 +   packet:
 +       int64       start timestamp
 +       int32       duration
 +
 +*/
 +
 +enum ws_interval_type {
 +    WS_SINE  = MKTAG('S','I','N','E'),
 +    WS_NOISE = MKTAG('N','O','I','S'),
 +};
 +
 +struct ws_interval {
 +    int64_t ts_start, ts_end;
 +    uint64_t phi0, dphi0, ddphi;
 +    uint64_t amp0, damp;
 +    uint64_t phi, dphi, amp;
 +    uint32_t channels;
 +    enum ws_interval_type type;
 +    int next;
 +};
 +
 +struct wavesynth_context {
 +    int64_t cur_ts;
 +    int64_t next_ts;
 +    int32_t *sin;
 +    AVFrame frame;
 +    struct ws_interval *inter;
 +    uint32_t dither_state;
 +    uint32_t pink_state;
 +    int32_t pink_pool[PINK_UNIT];
 +    unsigned pink_need, pink_pos;
 +    int nb_inter;
 +    int cur_inter;
 +    int next_inter;
 +};
 +
 +#define LCG_A 1284865837
 +#define LCG_C 4150755663
 +#define LCG_AI 849225893 /* A*AI = 1 [mod 1<<32] */
 +
 +static uint32_t lcg_next(uint32_t *s)
 +{
 +    *s = *s * LCG_A + LCG_C;
 +    return *s;
 +}
 +
 +static void lcg_seek(uint32_t *s, int64_t dt)
 +{
 +    uint32_t a, c, t = *s;
 +
 +    if (dt >= 0) {
 +        a = LCG_A;
 +        c = LCG_C;
 +    } else { /* coefficients for a step backward */
 +        a = LCG_AI;
 +        c = (uint32_t)(LCG_AI * LCG_C);
 +        dt = -dt;
 +    }
 +    while (dt) {
 +        if (dt & 1)
 +            t = a * t + c;
 +        c *= a + 1; /* coefficients for a double step */
 +        a *= a;
 +        dt >>= 1;
 +    }
 +    *s = t;
 +}
 +
 +/* Emulate pink noise by summing white noise at the sampling frequency,
 + * white noise at half the sampling frequency (each value taken twice),
 + * etc., with a total of 8 octaves.
 + * This is known as the Voss-McCartney algorithm. */
 +
 +static void pink_fill(struct wavesynth_context *ws)
 +{
 +    int32_t vt[7] = { 0 }, v = 0;
 +    int i, j;
 +
 +    ws->pink_pos = 0;
 +    if (!ws->pink_need)
 +        return;
 +    for (i = 0; i < PINK_UNIT; i++) {
 +        for (j = 0; j < 7; j++) {
 +            if ((i >> j) & 1)
 +                break;
 +            v -= vt[j];
 +            vt[j] = (int32_t)lcg_next(&ws->pink_state) >> 3;
 +            v += vt[j];
 +        }
 +        ws->pink_pool[i] = v + ((int32_t)lcg_next(&ws->pink_state) >> 3);
 +    }
 +    lcg_next(&ws->pink_state); /* so we use exactly 256 steps */
 +}
 +
 +/**
 + * @return  (1<<64) * a / b, without overflow, if a < b
 + */
 +static uint64_t frac64(uint64_t a, uint64_t b)
 +{
 +    uint64_t r = 0;
 +    int i;
 +
 +    if (b < (uint64_t)1 << 32) { /* b small, use two 32-bits steps */
 +        a <<= 32;
 +        return ((a / b) << 32) | ((a % b) << 32) / b;
 +    }
 +    if (b < (uint64_t)1 << 48) { /* b medium, use four 16-bits steps */
 +        for (i = 0; i < 4; i++) {
 +            a <<= 16;
 +            r = (r << 16) | (a / b);
 +            a %= b;
 +        }
 +        return r;
 +    }
 +    for (i = 63; i >= 0; i--) {
 +        if (a >= (uint64_t)1 << 63 || a << 1 >= b) {
 +            r |= (uint64_t)1 << i;
 +            a = (a << 1) - b;
 +        } else {
 +            a <<= 1;
 +        }
 +    }
 +    return r;
 +}
 +
 +static uint64_t phi_at(struct ws_interval *in, int64_t ts)
 +{
 +    uint64_t dt = ts - in->ts_start;
 +    uint64_t dt2 = dt & 1 ? /* dt * (dt - 1) / 2 without overflow */
 +                   dt * ((dt - 1) >> 1) : (dt >> 1) * (dt - 1);
 +    return in->phi0 + dt * in->dphi0 + dt2 * in->ddphi;
 +}
 +
 +static void wavesynth_seek(struct wavesynth_context *ws, int64_t ts)
 +{
 +    int *last, i;
 +    struct ws_interval *in;
 +
 +    last = &ws->cur_inter;
 +    for (i = 0; i < ws->nb_inter; i++) {
 +        in = &ws->inter[i];
 +        if (ts < in->ts_start)
 +            break;
 +        if (ts >= in->ts_end)
 +            continue;
 +        *last = i;
 +        last = &in->next;
 +        in->phi  = phi_at(in, ts);
 +        in->dphi = in->dphi0 + (ts - in->ts_start) * in->ddphi;
 +        in->amp  = in->amp0  + (ts - in->ts_start) * in->damp;
 +    }
 +    ws->next_inter = i;
 +    ws->next_ts = i < ws->nb_inter ? ws->inter[i].ts_start : INF_TS;
 +    *last = -1;
 +    lcg_seek(&ws->dither_state, ts - ws->cur_ts);
 +    if (ws->pink_need) {
 +        int64_t pink_ts_cur  = (ws->cur_ts + PINK_UNIT - 1) & ~(PINK_UNIT - 1);
 +        int64_t pink_ts_next = ts & ~(PINK_UNIT - 1);
 +        int pos = ts & (PINK_UNIT - 1);
 +        lcg_seek(&ws->pink_state, (pink_ts_next - pink_ts_cur) << 1);
 +        if (pos) {
 +            pink_fill(ws);
 +            ws->pink_pos = pos;
 +        } else {
 +            ws->pink_pos = PINK_UNIT;
 +        }
 +    }
 +    ws->cur_ts = ts;
 +}
 +
 +static int wavesynth_parse_extradata(AVCodecContext *avc)
 +{
 +    struct wavesynth_context *ws = avc->priv_data;
 +    struct ws_interval *in;
 +    uint8_t *edata, *edata_end;
 +    int32_t f1, f2, a1, a2;
 +    uint32_t phi;
 +    int64_t dphi1, dphi2, dt, cur_ts = -0x8000000000000000;
 +    int i;
 +
 +    if (avc->extradata_size < 4)
 +        return AVERROR(EINVAL);
 +    edata = avc->extradata;
 +    edata_end = edata + avc->extradata_size;
 +    ws->nb_inter = AV_RL32(edata);
 +    edata += 4;
 +    if (ws->nb_inter < 0)
 +        return AVERROR(EINVAL);
 +    ws->inter = av_calloc(ws->nb_inter, sizeof(*ws->inter));
 +    if (!ws->inter)
 +        return AVERROR(ENOMEM);
 +    for (i = 0; i < ws->nb_inter; i++) {
 +        in = &ws->inter[i];
 +        if (edata_end - edata < 24)
 +            return AVERROR(EINVAL);
 +        in->ts_start = AV_RL64(edata +  0);
 +        in->ts_end   = AV_RL64(edata +  8);
 +        in->type     = AV_RL32(edata + 16);
 +        in->channels = AV_RL32(edata + 20);
 +        edata += 24;
 +        if (in->ts_start < cur_ts || in->ts_end <= in->ts_start)
 +            return AVERROR(EINVAL);
 +        cur_ts = in->ts_start;
 +        dt = in->ts_end - in->ts_start;
 +        switch (in->type) {
 +            case WS_SINE:
 +                if (edata_end - edata < 20)
 +                    return AVERROR(EINVAL);
 +                f1  = AV_RL32(edata +  0);
 +                f2  = AV_RL32(edata +  4);
 +                a1  = AV_RL32(edata +  8);
 +                a2  = AV_RL32(edata + 12);
 +                phi = AV_RL32(edata + 16);
 +                edata += 20;
 +                dphi1 = frac64(f1, (int64_t)avc->sample_rate << 16);
 +                dphi2 = frac64(f2, (int64_t)avc->sample_rate << 16);
 +                in->dphi0 = dphi1;
 +                in->ddphi = (dphi2 - dphi1) / dt;
 +                if (phi & 0x80000000) {
 +                    phi &= ~0x80000000;
 +                    if (phi >= i)
 +                        return AVERROR(EINVAL);
 +                    in->phi0 = phi_at(&ws->inter[phi], in->ts_start);
 +                } else {
 +                    in->phi0 = (uint64_t)phi << 33;
 +                }
 +                break;
 +            case WS_NOISE:
 +                if (edata_end - edata < 8)
 +                    return AVERROR(EINVAL);
 +                a1  = AV_RL32(edata +  0);
 +                a2  = AV_RL32(edata +  4);
 +                edata += 8;
 +                break;
 +            default:
 +                return AVERROR(EINVAL);
 +        }
 +        in->amp0 = (int64_t)a1 << 32;
 +        in->damp = (((int64_t)a2 << 32) - ((int64_t)a1 << 32)) / dt;
 +    }
 +    if (edata != edata_end)
 +        return AVERROR(EINVAL);
 +    return 0;
 +}
 +
 +static av_cold int wavesynth_init(AVCodecContext *avc)
 +{
 +    struct wavesynth_context *ws = avc->priv_data;
 +    int i, r;
 +
 +    if (avc->channels > WS_MAX_CHANNELS) {
 +        av_log(avc, AV_LOG_ERROR,
 +               "This implementation is limited to %d channels.\n",
 +               WS_MAX_CHANNELS);
 +        return AVERROR(EINVAL);
 +    }
 +    r = wavesynth_parse_extradata(avc);
 +    if (r < 0) {
 +        av_log(avc, AV_LOG_ERROR, "Invalid intervals definitions.\n");
 +        goto fail;
 +    }
 +    ws->sin = av_malloc(sizeof(*ws->sin) << SIN_BITS);
 +    if (!ws->sin) {
 +        r = AVERROR(ENOMEM);
 +        goto fail;
 +    }
 +    for (i = 0; i < 1 << SIN_BITS; i++)
 +        ws->sin[i] = floor(32767 * sin(2 * M_PI * i / (1 << SIN_BITS)));
 +    ws->dither_state = MKTAG('D','I','T','H');
 +    for (i = 0; i < ws->nb_inter; i++)
 +        ws->pink_need += ws->inter[i].type == WS_NOISE;
 +    ws->pink_state = MKTAG('P','I','N','K');
 +    ws->pink_pos = PINK_UNIT;
 +    avcodec_get_frame_defaults(&ws->frame);
 +    avc->coded_frame = &ws->frame;
 +    wavesynth_seek(ws, 0);
 +    avc->sample_fmt = AV_SAMPLE_FMT_S16;
 +    return 0;
 +
 +fail:
 +    av_free(ws->inter);
 +    av_free(ws->sin);
 +    return r;
 +}
 +
 +static void wavesynth_synth_sample(struct wavesynth_context *ws, int64_t ts,
 +                                   int32_t *channels)
 +{
 +    int32_t amp, val, *cv;
 +    struct ws_interval *in;
 +    int i, *last, pink;
 +    uint32_t c, all_ch = 0;
 +
 +    i = ws->cur_inter;
 +    last = &ws->cur_inter;
 +    if (ws->pink_pos == PINK_UNIT)
 +        pink_fill(ws);
 +    pink = ws->pink_pool[ws->pink_pos++] >> 16;
 +    while (i >= 0) {
 +        in = &ws->inter[i];
 +        i = in->next;
 +        if (ts >= in->ts_end) {
 +            *last = i;
 +            continue;
 +        }
 +        last = &in->next;
 +        amp = in->amp >> 32;
 +        in->amp  += in->damp;
 +        switch (in->type) {
 +            case WS_SINE:
 +                val = amp * ws->sin[in->phi >> (64 - SIN_BITS)];
 +                in->phi  += in->dphi;
 +                in->dphi += in->ddphi;
 +                break;
 +            case WS_NOISE:
 +                val = amp * pink;
 +                break;
 +            default:
 +                val = 0;
 +        }
 +        all_ch |= in->channels;
 +        for (c = in->channels, cv = channels; c; c >>= 1, cv++)
 +            if (c & 1)
 +                *cv += val;
 +    }
 +    val = (int32_t)lcg_next(&ws->dither_state) >> 16;
 +    for (c = all_ch, cv = channels; c; c >>= 1, cv++)
 +        if (c & 1)
 +            *cv += val;
 +}
 +
 +static void wavesynth_enter_intervals(struct wavesynth_context *ws, int64_t ts)
 +{
 +    int *last, i;
 +    struct ws_interval *in;
 +
 +    last = &ws->cur_inter;
 +    for (i = ws->cur_inter; i >= 0; i = ws->inter[i].next)
 +        last = &ws->inter[i].next;
 +    for (i = ws->next_inter; i < ws->nb_inter; i++) {
 +        in = &ws->inter[i];
 +        if (ts < in->ts_start)
 +            break;
 +        if (ts >= in->ts_end)
 +            continue;
 +        *last = i;
 +        last = &in->next;
 +        in->phi = in->phi0;
 +        in->dphi = in->dphi0;
 +        in->amp = in->amp0;
 +    }
 +    ws->next_inter = i;
 +    ws->next_ts = i < ws->nb_inter ? ws->inter[i].ts_start : INF_TS;
 +    *last = -1;
 +}
 +
 +static int wavesynth_decode(AVCodecContext *avc, void *rframe, int *rgot_frame,
 +                            AVPacket *packet)
 +{
 +    struct wavesynth_context *ws = avc->priv_data;
 +    int64_t ts;
 +    int duration;
 +    int s, c, r;
 +    int16_t *pcm;
 +    int32_t channels[WS_MAX_CHANNELS];
 +
 +    *rgot_frame = 0;
 +    if (packet->size != 12)
 +        return AVERROR_INVALIDDATA;
 +    ts = AV_RL64(packet->data);
 +    if (ts != ws->cur_ts)
 +        wavesynth_seek(ws, ts);
 +    duration = AV_RL32(packet->data + 8);
 +    if (duration <= 0)
 +        return AVERROR(EINVAL);
 +    ws->frame.nb_samples = duration;
++    r = ff_get_buffer(avc, &ws->frame, 0);
 +    if (r < 0)
 +        return r;
 +    pcm = (int16_t *)ws->frame.data[0];
 +    for (s = 0; s < duration; s++, ts++) {
 +        memset(channels, 0, avc->channels * sizeof(*channels));
 +        if (ts >= ws->next_ts)
 +            wavesynth_enter_intervals(ws, ts);
 +        wavesynth_synth_sample(ws, ts, channels);
 +        for (c = 0; c < avc->channels; c++)
 +            *(pcm++) = channels[c] >> 16;
 +    }
 +    ws->cur_ts += duration;
 +    *rgot_frame = 1;
 +    *(AVFrame *)rframe = ws->frame;
 +    return packet->size;
 +}
 +
 +static av_cold int wavesynth_close(AVCodecContext *avc)
 +{
 +    struct wavesynth_context *ws = avc->priv_data;
 +
 +    av_free(ws->sin);
 +    av_free(ws->inter);
 +    return 0;
 +}
 +
 +AVCodec ff_ffwavesynth_decoder = {
 +    .name           = "wavesynth",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_FFWAVESYNTH,
 +    .priv_data_size = sizeof(struct wavesynth_context),
 +    .init           = wavesynth_init,
 +    .close          = wavesynth_close,
 +    .decode         = wavesynth_decode,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"),
 +};
Simple merge
@@@ -243,10 -239,8 +244,10 @@@ static int flashsv_decode_frame(AVCodec
  {
      int buf_size       = avpkt->size;
      FlashSVContext *s  = avctx->priv_data;
-     int h_blocks, v_blocks, h_part, v_part, i, j;
+     int h_blocks, v_blocks, h_part, v_part, i, j, ret;
      GetBitContext gb;
 +    int last_blockwidth = s->block_width;
 +    int last_blockheight= s->block_height;
  
      /* no supplementary picture */
      if (buf_size == 0)
Simple merge
index 0ac018b,0000000..b11a54a
mode 100644,000000..100644
--- /dev/null
@@@ -1,270 -1,0 +1,270 @@@
-         c->parent_avctx->release_buffer(c->parent_avctx, frame);
 +/*
 + * Copyright (c) 2012 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 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 "frame_thread_encoder.h"
 +
 +#include "libavutil/fifo.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/imgutils.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "thread.h"
 +
 +#if HAVE_PTHREADS
 +#include <pthread.h>
 +#elif HAVE_W32THREADS
 +#include "w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
 +#endif
 +
 +#define MAX_THREADS 64
 +#define BUFFER_SIZE (2*MAX_THREADS)
 +
 +typedef struct{
 +    void *indata;
 +    void *outdata;
 +    int64_t return_code;
 +    unsigned index;
 +} Task;
 +
 +typedef struct{
 +    AVCodecContext *parent_avctx;
 +    pthread_mutex_t buffer_mutex;
 +
 +    AVFifoBuffer *task_fifo;
 +    pthread_mutex_t task_fifo_mutex;
 +    pthread_cond_t task_fifo_cond;
 +
 +    Task finished_tasks[BUFFER_SIZE];
 +    pthread_mutex_t finished_task_mutex;
 +    pthread_cond_t finished_task_cond;
 +
 +    unsigned task_index;
 +    unsigned finished_task_index;
 +
 +    pthread_t worker[MAX_THREADS];
 +    int exit;
 +} ThreadContext;
 +
 +static void * attribute_align_arg worker(void *v){
 +    AVCodecContext *avctx = v;
 +    ThreadContext *c = avctx->internal->frame_thread_encoder;
 +    AVPacket *pkt = NULL;
 +
 +    while(!c->exit){
 +        int got_packet, ret;
 +        AVFrame *frame;
 +        Task task;
 +
 +        if(!pkt) pkt= av_mallocz(sizeof(*pkt));
 +        if(!pkt) continue;
 +        av_init_packet(pkt);
 +
 +        pthread_mutex_lock(&c->task_fifo_mutex);
 +        while (av_fifo_size(c->task_fifo) <= 0 || c->exit) {
 +            if(c->exit){
 +                pthread_mutex_unlock(&c->task_fifo_mutex);
 +                goto end;
 +            }
 +            pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex);
 +        }
 +        av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL);
 +        pthread_mutex_unlock(&c->task_fifo_mutex);
 +        frame = task.indata;
 +
 +        ret = avcodec_encode_video2(avctx, pkt, frame, &got_packet);
 +        pthread_mutex_lock(&c->buffer_mutex);
-         av_freep(&frame);
++        av_frame_unref(frame);
 +        pthread_mutex_unlock(&c->buffer_mutex);
-             AVFrame *new = avcodec_alloc_frame();
++        av_frame_free(&frame);
 +        if(got_packet) {
 +            av_dup_packet(pkt);
 +        } else {
 +            pkt->data = NULL;
 +            pkt->size = 0;
 +        }
 +        pthread_mutex_lock(&c->finished_task_mutex);
 +        c->finished_tasks[task.index].outdata = pkt; pkt = NULL;
 +        c->finished_tasks[task.index].return_code = ret;
 +        pthread_cond_signal(&c->finished_task_cond);
 +        pthread_mutex_unlock(&c->finished_task_mutex);
 +    }
 +end:
 +    av_free(pkt);
 +    pthread_mutex_lock(&c->buffer_mutex);
 +    avcodec_close(avctx);
 +    pthread_mutex_unlock(&c->buffer_mutex);
 +    av_freep(&avctx);
 +    return NULL;
 +}
 +
 +int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
 +    int i=0;
 +    ThreadContext *c;
 +
 +
 +    if(   !(avctx->thread_type & FF_THREAD_FRAME)
 +       || !(avctx->codec->capabilities & CODEC_CAP_INTRA_ONLY))
 +        return 0;
 +
 +    if(!avctx->thread_count) {
 +        avctx->thread_count = ff_get_logical_cpus(avctx);
 +        avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
 +    }
 +
 +    if(avctx->thread_count <= 1)
 +        return 0;
 +
 +    if(avctx->thread_count > MAX_THREADS)
 +        return AVERROR(EINVAL);
 +
 +    av_assert0(!avctx->internal->frame_thread_encoder);
 +    c = avctx->internal->frame_thread_encoder = av_mallocz(sizeof(ThreadContext));
 +    if(!c)
 +        return AVERROR(ENOMEM);
 +
 +    c->parent_avctx = avctx;
 +
 +    c->task_fifo = av_fifo_alloc(sizeof(Task) * BUFFER_SIZE);
 +    if(!c->task_fifo)
 +        goto fail;
 +
 +    pthread_mutex_init(&c->task_fifo_mutex, NULL);
 +    pthread_mutex_init(&c->finished_task_mutex, NULL);
 +    pthread_mutex_init(&c->buffer_mutex, NULL);
 +    pthread_cond_init(&c->task_fifo_cond, NULL);
 +    pthread_cond_init(&c->finished_task_cond, NULL);
 +
 +    for(i=0; i<avctx->thread_count ; i++){
 +        AVDictionary *tmp = NULL;
 +        void *tmpv;
 +        AVCodecContext *thread_avctx = avcodec_alloc_context3(avctx->codec);
 +        if(!thread_avctx)
 +            goto fail;
 +        tmpv = thread_avctx->priv_data;
 +        *thread_avctx = *avctx;
 +        thread_avctx->priv_data = tmpv;
 +        thread_avctx->internal = NULL;
 +        memcpy(thread_avctx->priv_data, avctx->priv_data, avctx->codec->priv_data_size);
 +        thread_avctx->thread_count = 1;
 +        thread_avctx->active_thread_type &= ~FF_THREAD_FRAME;
 +
 +        av_dict_copy(&tmp, options, 0);
 +        av_dict_set(&tmp, "threads", "1", 0);
 +        if(avcodec_open2(thread_avctx, avctx->codec, &tmp) < 0) {
 +            av_dict_free(&tmp);
 +            goto fail;
 +        }
 +        av_dict_free(&tmp);
 +        av_assert0(!thread_avctx->internal->frame_thread_encoder);
 +        thread_avctx->internal->frame_thread_encoder = c;
 +        if(pthread_create(&c->worker[i], NULL, worker, thread_avctx)) {
 +            goto fail;
 +        }
 +    }
 +
 +    avctx->active_thread_type = FF_THREAD_FRAME;
 +
 +    return 0;
 +fail:
 +    avctx->thread_count = i;
 +    av_log(avctx, AV_LOG_ERROR, "ff_frame_thread_encoder_init failed\n");
 +    ff_frame_thread_encoder_free(avctx);
 +    return -1;
 +}
 +
 +void ff_frame_thread_encoder_free(AVCodecContext *avctx){
 +    int i;
 +    ThreadContext *c= avctx->internal->frame_thread_encoder;
 +
 +    pthread_mutex_lock(&c->task_fifo_mutex);
 +    c->exit = 1;
 +    pthread_cond_broadcast(&c->task_fifo_cond);
 +    pthread_mutex_unlock(&c->task_fifo_mutex);
 +
 +    for (i=0; i<avctx->thread_count; i++) {
 +         pthread_join(c->worker[i], NULL);
 +    }
 +
 +    pthread_mutex_destroy(&c->task_fifo_mutex);
 +    pthread_mutex_destroy(&c->finished_task_mutex);
 +    pthread_mutex_destroy(&c->buffer_mutex);
 +    pthread_cond_destroy(&c->task_fifo_cond);
 +    pthread_cond_destroy(&c->finished_task_cond);
 +    av_fifo_free(c->task_fifo); c->task_fifo = NULL;
 +    av_freep(&avctx->internal->frame_thread_encoder);
 +}
 +
 +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr){
 +    ThreadContext *c = avctx->internal->frame_thread_encoder;
 +    Task task;
 +    int ret;
 +
 +    av_assert1(!*got_packet_ptr);
 +
 +    if(frame){
 +        if(!(avctx->flags & CODEC_FLAG_INPUT_PRESERVED)){
-             ret = ff_get_buffer(c->parent_avctx, new);
++            AVFrame *new = av_frame_alloc();
 +            if(!new)
 +                return AVERROR(ENOMEM);
 +            pthread_mutex_lock(&c->buffer_mutex);
++            ret = ff_get_buffer(c->parent_avctx, new, 0);
 +            pthread_mutex_unlock(&c->buffer_mutex);
 +            if(ret<0)
 +                return ret;
 +            new->pts = frame->pts;
 +            new->quality = frame->quality;
 +            new->pict_type = frame->pict_type;
 +            av_image_copy(new->data, new->linesize, (const uint8_t **)frame->data, frame->linesize,
 +                          avctx->pix_fmt, avctx->width, avctx->height);
 +            frame = new;
 +        }
 +
 +        task.index = c->task_index;
 +        task.indata = (void*)frame;
 +        pthread_mutex_lock(&c->task_fifo_mutex);
 +        av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL);
 +        pthread_cond_signal(&c->task_fifo_cond);
 +        pthread_mutex_unlock(&c->task_fifo_mutex);
 +
 +        c->task_index = (c->task_index+1) % BUFFER_SIZE;
 +
 +        if(!c->finished_tasks[c->finished_task_index].outdata && (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count)
 +            return 0;
 +    }
 +
 +    if(c->task_index == c->finished_task_index)
 +        return 0;
 +
 +    pthread_mutex_lock(&c->finished_task_mutex);
 +    while (!c->finished_tasks[c->finished_task_index].outdata) {
 +        pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex);
 +    }
 +    task = c->finished_tasks[c->finished_task_index];
 +    *pkt = *(AVPacket*)(task.outdata);
 +    if(pkt->data)
 +        *got_packet_ptr = 1;
 +    av_freep(&c->finished_tasks[c->finished_task_index].outdata);
 +    c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE;
 +    pthread_mutex_unlock(&c->finished_task_mutex);
 +
 +    return task.return_code;
 +}
@@@ -36,7 -36,7 +36,8 @@@
  #include "huffman.h"
  #include "bytestream.h"
  #include "dsputil.h"
+ #include "internal.h"
 +#include "thread.h"
  
  #define FPS_TAG MKTAG('F', 'P', 'S', 'x')
  
@@@ -45,7 -45,7 +46,6 @@@
   */
  typedef struct FrapsContext {
      AVCodecContext *avctx;
--    AVFrame frame;
      uint8_t *tmpbuf;
      int tmpbuf_size;
      DSPContext dsp;
@@@ -61,9 -61,8 +61,6 @@@ static av_cold int decode_init(AVCodecC
  {
      FrapsContext * const s = avctx->priv_data;
  
-     avcodec_get_frame_defaults(&s->frame);
-     avctx->coded_frame = &s->frame;
 -    avctx->pix_fmt     = AV_PIX_FMT_NONE; /* set in decode_frame */
--
      s->avctx  = avctx;
      s->tmpbuf = NULL;
  
@@@ -134,18 -133,16 +131,17 @@@ static int decode_frame(AVCodecContext 
      FrapsContext * const s = avctx->priv_data;
      const uint8_t *buf     = avpkt->data;
      int buf_size           = avpkt->size;
--    AVFrame *frame         = data;
--    AVFrame * const f      = &s->frame;
++    ThreadFrame frame = { .f = data };
++    AVFrame * const f = data;
      uint32_t header;
      unsigned int version,header_size;
      unsigned int x, y;
      const uint32_t *buf32;
      uint32_t *luma1,*luma2,*cb,*cr;
      uint32_t offs[4];
 -    int i, j, ret, is_chroma, planes;
 -    enum AVPixelFormat pix_fmt;
 +    int i, j, ret, is_chroma;
 +    const int planes = 3;
 +    uint8_t *out;
-     enum AVPixelFormat pix_fmt;
  
      header      = AV_RL32(buf);
      version     = header & 0xff;
          return AVERROR_PATCHWELCOME;
      }
  
 -    buf += 4;
 -    if (header_size == 8)
 -        buf += 4;
 +    buf += header_size;
 +
 +    if (version < 2) {
 +        unsigned needed_size = avctx->width * avctx->height * 3;
 +        if (version == 0) needed_size /= 2;
 +        needed_size += header_size;
 +        /* bit 31 means same as previous pic */
 +        if (header & (1U<<31)) {
 +            *got_frame = 0;
 +            return buf_size;
 +        }
 +        if (buf_size != needed_size) {
 +            av_log(avctx, AV_LOG_ERROR,
 +                   "Invalid frame length %d (should be %d)\n",
 +                   buf_size, needed_size);
 +            return AVERROR_INVALIDDATA;
 +        }
 +    } else {
 +        /* skip frame */
 +        if (buf_size == 8) {
 +            *got_frame = 0;
 +            return buf_size;
 +        }
 +        if (AV_RL32(buf) != FPS_TAG || buf_size < planes*1024 + 24) {
 +            av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +        for (i = 0; i < planes; i++) {
 +            offs[i] = AV_RL32(buf + 4 + i * 4);
 +            if (offs[i] >= buf_size - header_size || (i && offs[i] <= offs[i - 1] + 1024)) {
 +                av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i);
 +                return AVERROR_INVALIDDATA;
 +            }
 +        }
 +        offs[planes] = buf_size - header_size;
 +        for (i = 0; i < planes; i++) {
 +            av_fast_padded_malloc(&s->tmpbuf, &s->tmpbuf_size, offs[i + 1] - offs[i] - 1024);
 +            if (!s->tmpbuf)
 +                return AVERROR(ENOMEM);
 +        }
 +    }
 +
-     if (f->data[0])
-         ff_thread_release_buffer(avctx, f);
 +    f->pict_type = AV_PICTURE_TYPE_I;
 +    f->key_frame = 1;
-     f->reference = 0;
-     f->buffer_hints = FF_BUFFER_HINTS_VALID;
 +
-     pix_fmt = version & 1 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P;
-     if (avctx->pix_fmt != pix_fmt && f->data[0]) {
-         avctx->release_buffer(avctx, f);
-     }
-     avctx->pix_fmt = pix_fmt;
++    avctx->pix_fmt = version & 1 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P;
  
-     if ((ret = ff_thread_get_buffer(avctx, f))) {
 -    pix_fmt = version & 1 ? AV_PIX_FMT_BGR24 : AV_PIX_FMT_YUVJ420P;
 -    if (avctx->pix_fmt != pix_fmt && f->data[0]) {
 -        av_frame_unref(f);
++    if ((ret = ff_thread_get_buffer(avctx, &frame, 0))) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
      }
 -    avctx->pix_fmt = pix_fmt;
  
      switch (version) {
      case 0:
          break;
      }
  
-     *frame = *f;
 -    if ((ret = av_frame_ref(frame, f)) < 0)
 -        return ret;
      *got_frame = 1;
  
      return buf_size;
@@@ -312,9 -351,8 +299,6 @@@ static av_cold int decode_end(AVCodecCo
  {
      FrapsContext *s = (FrapsContext*)avctx->priv_data;
  
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
 -    av_frame_unref(&s->frame);
--
      av_freep(&s->tmpbuf);
      return 0;
  }
@@@ -48,9 -38,8 +44,9 @@@ static av_cold int decode_init(AVCodecC
  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                          AVPacket *avpkt)
  {
 +    FRWUContext *s = avctx->priv_data;
      int field, ret;
-     AVFrame *pic = avctx->coded_frame;
+     AVFrame *pic = data;
      const uint8_t *buf = avpkt->data;
      const uint8_t *buf_end = buf + avpkt->size;
  
      return avpkt->size;
  }
  
- static av_cold int decode_close(AVCodecContext *avctx)
- {
-     AVFrame *pic = avctx->coded_frame;
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
-     av_freep(&avctx->coded_frame);
-     return 0;
- }
 +static const AVOption frwu_options[] = {
 +    {"change_field_order", "Change field order", offsetof(FRWUContext, change_field_order), FF_OPT_TYPE_INT,
 +     {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM},
 +    {NULL}
 +};
 +
 +static const AVClass frwu_class = {
 +    .class_name = "frwu Decoder",
 +    .item_name  = av_default_item_name,
 +    .option     = frwu_options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  AVCodec ff_frwu_decoder = {
      .name           = "frwu",
      .type           = AVMEDIA_TYPE_VIDEO,
      .id             = AV_CODEC_ID_FRWU,
 +    .priv_data_size = sizeof(FRWUContext),
      .init           = decode_init,
-     .close          = decode_close,
      .decode         = decode_frame,
      .capabilities   = CODEC_CAP_DR1,
      .long_name      = NULL_IF_CONFIG_SMALL("Forward Uncompressed"),
Simple merge
Simple merge
Simple merge
index db3f013,0000000..c9af370
mode 100644,000000..100644
--- /dev/null
@@@ -1,732 -1,0 +1,732 @@@
-     if ((ret = ff_get_buffer(avctx, &ctx->frame)) < 0) {
 +/*
 + * G.729, G729 Annex D decoders
 + * Copyright (c) 2008 Vladimir Voroshilov
 + *
 + * 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 <inttypes.h>
 +#include <string.h>
 +
 +#include "avcodec.h"
 +#include "libavutil/avutil.h"
 +#include "get_bits.h"
 +#include "dsputil.h"
 +#include "internal.h"
 +
 +
 +#include "g729.h"
 +#include "lsp.h"
 +#include "celp_math.h"
 +#include "celp_filters.h"
 +#include "acelp_filters.h"
 +#include "acelp_pitch_delay.h"
 +#include "acelp_vectors.h"
 +#include "g729data.h"
 +#include "g729postfilter.h"
 +
 +/**
 + * minimum quantized LSF value (3.2.4)
 + * 0.005 in Q13
 + */
 +#define LSFQ_MIN                   40
 +
 +/**
 + * maximum quantized LSF value (3.2.4)
 + * 3.135 in Q13
 + */
 +#define LSFQ_MAX                   25681
 +
 +/**
 + * minimum LSF distance (3.2.4)
 + * 0.0391 in Q13
 + */
 +#define LSFQ_DIFF_MIN              321
 +
 +/// interpolation filter length
 +#define INTERPOL_LEN              11
 +
 +/**
 + * minimum gain pitch value (3.8, Equation 47)
 + * 0.2 in (1.14)
 + */
 +#define SHARP_MIN                  3277
 +
 +/**
 + * maximum gain pitch value (3.8, Equation 47)
 + * (EE) This does not comply with the specification.
 + * Specification says about 0.8, which should be
 + * 13107 in (1.14), but reference C code uses
 + * 13017 (equals to 0.7945) instead of it.
 + */
 +#define SHARP_MAX                  13017
 +
 +/**
 + * MR_ENERGY (mean removed energy) = mean_energy + 10 * log10(2^26  * subframe_size) in (7.13)
 + */
 +#define MR_ENERGY 1018156
 +
 +#define DECISION_NOISE        0
 +#define DECISION_INTERMEDIATE 1
 +#define DECISION_VOICE        2
 +
 +typedef enum {
 +    FORMAT_G729_8K = 0,
 +    FORMAT_G729D_6K4,
 +    FORMAT_COUNT,
 +} G729Formats;
 +
 +typedef struct {
 +    uint8_t ac_index_bits[2];   ///< adaptive codebook index for second subframe (size in bits)
 +    uint8_t parity_bit;         ///< parity bit for pitch delay
 +    uint8_t gc_1st_index_bits;  ///< gain codebook (first stage) index (size in bits)
 +    uint8_t gc_2nd_index_bits;  ///< gain codebook (second stage) index (size in bits)
 +    uint8_t fc_signs_bits;      ///< number of pulses in fixed-codebook vector
 +    uint8_t fc_indexes_bits;    ///< size (in bits) of fixed-codebook index entry
 +} G729FormatDescription;
 +
 +typedef struct {
 +    DSPContext dsp;
 +    AVFrame frame;
 +
 +    /// past excitation signal buffer
 +    int16_t exc_base[2*SUBFRAME_SIZE+PITCH_DELAY_MAX+INTERPOL_LEN];
 +
 +    int16_t* exc;               ///< start of past excitation data in buffer
 +    int pitch_delay_int_prev;   ///< integer part of previous subframe's pitch delay (4.1.3)
 +
 +    /// (2.13) LSP quantizer outputs
 +    int16_t  past_quantizer_output_buf[MA_NP + 1][10];
 +    int16_t* past_quantizer_outputs[MA_NP + 1];
 +
 +    int16_t lsfq[10];           ///< (2.13) quantized LSF coefficients from previous frame
 +    int16_t lsp_buf[2][10];     ///< (0.15) LSP coefficients (previous and current frames) (3.2.5)
 +    int16_t *lsp[2];            ///< pointers to lsp_buf
 +
 +    int16_t quant_energy[4];    ///< (5.10) past quantized energy
 +
 +    /// previous speech data for LP synthesis filter
 +    int16_t syn_filter_data[10];
 +
 +
 +    /// residual signal buffer (used in long-term postfilter)
 +    int16_t residual[SUBFRAME_SIZE + RES_PREV_DATA_SIZE];
 +
 +    /// previous speech data for residual calculation filter
 +    int16_t res_filter_data[SUBFRAME_SIZE+10];
 +
 +    /// previous speech data for short-term postfilter
 +    int16_t pos_filter_data[SUBFRAME_SIZE+10];
 +
 +    /// (1.14) pitch gain of current and five previous subframes
 +    int16_t past_gain_pitch[6];
 +
 +    /// (14.1) gain code from current and previous subframe
 +    int16_t past_gain_code[2];
 +
 +    /// voice decision on previous subframe (0-noise, 1-intermediate, 2-voice), G.729D
 +    int16_t voice_decision;
 +
 +    int16_t onset;              ///< detected onset level (0-2)
 +    int16_t was_periodic;       ///< whether previous frame was declared as periodic or not (4.4)
 +    int16_t ht_prev_data;       ///< previous data for 4.2.3, equation 86
 +    int gain_coeff;             ///< (1.14) gain coefficient (4.2.4)
 +    uint16_t rand_value;        ///< random number generator value (4.4.4)
 +    int ma_predictor_prev;      ///< switched MA predictor of LSP quantizer from last good frame
 +
 +    /// (14.14) high-pass filter data (past input)
 +    int hpf_f[2];
 +
 +    /// high-pass filter data (past output)
 +    int16_t hpf_z[2];
 +}  G729Context;
 +
 +static const G729FormatDescription format_g729_8k = {
 +    .ac_index_bits     = {8,5},
 +    .parity_bit        = 1,
 +    .gc_1st_index_bits = GC_1ST_IDX_BITS_8K,
 +    .gc_2nd_index_bits = GC_2ND_IDX_BITS_8K,
 +    .fc_signs_bits     = 4,
 +    .fc_indexes_bits   = 13,
 +};
 +
 +static const G729FormatDescription format_g729d_6k4 = {
 +    .ac_index_bits     = {8,4},
 +    .parity_bit        = 0,
 +    .gc_1st_index_bits = GC_1ST_IDX_BITS_6K4,
 +    .gc_2nd_index_bits = GC_2ND_IDX_BITS_6K4,
 +    .fc_signs_bits     = 2,
 +    .fc_indexes_bits   = 9,
 +};
 +
 +/**
 + * @brief pseudo random number generator
 + */
 +static inline uint16_t g729_prng(uint16_t value)
 +{
 +    return 31821 * value + 13849;
 +}
 +
 +/**
 + * Get parity bit of bit 2..7
 + */
 +static inline int get_parity(uint8_t value)
 +{
 +   return (0x6996966996696996ULL >> (value >> 2)) & 1;
 +}
 +
 +/**
 + * Decodes LSF (Line Spectral Frequencies) from L0-L3 (3.2.4).
 + * @param[out] lsfq (2.13) quantized LSF coefficients
 + * @param[in,out] past_quantizer_outputs (2.13) quantizer outputs from previous frames
 + * @param ma_predictor switched MA predictor of LSP quantizer
 + * @param vq_1st first stage vector of quantizer
 + * @param vq_2nd_low second stage lower vector of LSP quantizer
 + * @param vq_2nd_high second stage higher vector of LSP quantizer
 + */
 +static void lsf_decode(int16_t* lsfq, int16_t* past_quantizer_outputs[MA_NP + 1],
 +                       int16_t ma_predictor,
 +                       int16_t vq_1st, int16_t vq_2nd_low, int16_t vq_2nd_high)
 +{
 +    int i,j;
 +    static const uint8_t min_distance[2]={10, 5}; //(2.13)
 +    int16_t* quantizer_output = past_quantizer_outputs[MA_NP];
 +
 +    for (i = 0; i < 5; i++) {
 +        quantizer_output[i]     = cb_lsp_1st[vq_1st][i    ] + cb_lsp_2nd[vq_2nd_low ][i    ];
 +        quantizer_output[i + 5] = cb_lsp_1st[vq_1st][i + 5] + cb_lsp_2nd[vq_2nd_high][i + 5];
 +    }
 +
 +    for (j = 0; j < 2; j++) {
 +        for (i = 1; i < 10; i++) {
 +            int diff = (quantizer_output[i - 1] - quantizer_output[i] + min_distance[j]) >> 1;
 +            if (diff > 0) {
 +                quantizer_output[i - 1] -= diff;
 +                quantizer_output[i    ] += diff;
 +            }
 +        }
 +    }
 +
 +    for (i = 0; i < 10; i++) {
 +        int sum = quantizer_output[i] * cb_ma_predictor_sum[ma_predictor][i];
 +        for (j = 0; j < MA_NP; j++)
 +            sum += past_quantizer_outputs[j][i] * cb_ma_predictor[ma_predictor][j][i];
 +
 +        lsfq[i] = sum >> 15;
 +    }
 +
 +    ff_acelp_reorder_lsf(lsfq, LSFQ_DIFF_MIN, LSFQ_MIN, LSFQ_MAX, 10);
 +}
 +
 +/**
 + * Restores past LSP quantizer output using LSF from previous frame
 + * @param[in,out] lsfq (2.13) quantized LSF coefficients
 + * @param[in,out] past_quantizer_outputs (2.13) quantizer outputs from previous frames
 + * @param ma_predictor_prev MA predictor from previous frame
 + * @param lsfq_prev (2.13) quantized LSF coefficients from previous frame
 + */
 +static void lsf_restore_from_previous(int16_t* lsfq,
 +                                      int16_t* past_quantizer_outputs[MA_NP + 1],
 +                                      int ma_predictor_prev)
 +{
 +    int16_t* quantizer_output = past_quantizer_outputs[MA_NP];
 +    int i,k;
 +
 +    for (i = 0; i < 10; i++) {
 +        int tmp = lsfq[i] << 15;
 +
 +        for (k = 0; k < MA_NP; k++)
 +            tmp -= past_quantizer_outputs[k][i] * cb_ma_predictor[ma_predictor_prev][k][i];
 +
 +        quantizer_output[i] = ((tmp >> 15) * cb_ma_predictor_sum_inv[ma_predictor_prev][i]) >> 12;
 +    }
 +}
 +
 +/**
 + * Constructs new excitation signal and applies phase filter to it
 + * @param[out] out constructed speech signal
 + * @param in original excitation signal
 + * @param fc_cur (2.13) original fixed-codebook vector
 + * @param gain_code (14.1) gain code
 + * @param subframe_size length of the subframe
 + */
 +static void g729d_get_new_exc(
 +        int16_t* out,
 +        const int16_t* in,
 +        const int16_t* fc_cur,
 +        int dstate,
 +        int gain_code,
 +        int subframe_size)
 +{
 +    int i;
 +    int16_t fc_new[SUBFRAME_SIZE];
 +
 +    ff_celp_convolve_circ(fc_new, fc_cur, phase_filter[dstate], subframe_size);
 +
 +    for(i=0; i<subframe_size; i++)
 +    {
 +        out[i]  = in[i];
 +        out[i] -= (gain_code * fc_cur[i] + 0x2000) >> 14;
 +        out[i] += (gain_code * fc_new[i] + 0x2000) >> 14;
 +    }
 +}
 +
 +/**
 + * Makes decision about onset in current subframe
 + * @param past_onset decision result of previous subframe
 + * @param past_gain_code gain code of current and previous subframe
 + *
 + * @return onset decision result for current subframe
 + */
 +static int g729d_onset_decision(int past_onset, const int16_t* past_gain_code)
 +{
 +    if((past_gain_code[0] >> 1) > past_gain_code[1])
 +        return 2;
 +    else
 +        return FFMAX(past_onset-1, 0);
 +}
 +
 +/**
 + * Makes decision about voice presence in current subframe
 + * @param onset onset level
 + * @param prev_voice_decision voice decision result from previous subframe
 + * @param past_gain_pitch pitch gain of current and previous subframes
 + *
 + * @return voice decision result for current subframe
 + */
 +static int16_t g729d_voice_decision(int onset, int prev_voice_decision, const int16_t* past_gain_pitch)
 +{
 +    int i, low_gain_pitch_cnt, voice_decision;
 +
 +    if(past_gain_pitch[0] >= 14745)      // 0.9
 +        voice_decision = DECISION_VOICE;
 +    else if (past_gain_pitch[0] <= 9830) // 0.6
 +        voice_decision = DECISION_NOISE;
 +    else
 +        voice_decision = DECISION_INTERMEDIATE;
 +
 +    for(i=0, low_gain_pitch_cnt=0; i<6; i++)
 +        if(past_gain_pitch[i] < 9830)
 +            low_gain_pitch_cnt++;
 +
 +    if(low_gain_pitch_cnt > 2 && !onset)
 +        voice_decision = DECISION_NOISE;
 +
 +    if(!onset && voice_decision > prev_voice_decision + 1)
 +        voice_decision--;
 +
 +    if(onset && voice_decision < DECISION_VOICE)
 +        voice_decision++;
 +
 +    return voice_decision;
 +}
 +
 +static int32_t scalarproduct_int16_c(const int16_t * v1, const int16_t * v2, int order)
 +{
 +    int res = 0;
 +
 +    while (order--)
 +        res += *v1++ * *v2++;
 +
 +    return res;
 +}
 +
 +static av_cold int decoder_init(AVCodecContext * avctx)
 +{
 +    G729Context* ctx = avctx->priv_data;
 +    int i,k;
 +
 +    if (avctx->channels != 1) {
 +        av_log(avctx, AV_LOG_ERROR, "Only mono sound is supported (requested channels: %d).\n", avctx->channels);
 +        return AVERROR(EINVAL);
 +    }
 +    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
 +
 +    /* Both 8kbit/s and 6.4kbit/s modes uses two subframes per frame. */
 +    avctx->frame_size = SUBFRAME_SIZE << 1;
 +
 +    ctx->gain_coeff = 16384; // 1.0 in (1.14)
 +
 +    for (k = 0; k < MA_NP + 1; k++) {
 +        ctx->past_quantizer_outputs[k] = ctx->past_quantizer_output_buf[k];
 +        for (i = 1; i < 11; i++)
 +            ctx->past_quantizer_outputs[k][i - 1] = (18717 * i) >> 3;
 +    }
 +
 +    ctx->lsp[0] = ctx->lsp_buf[0];
 +    ctx->lsp[1] = ctx->lsp_buf[1];
 +    memcpy(ctx->lsp[0], lsp_init, 10 * sizeof(int16_t));
 +
 +    ctx->exc = &ctx->exc_base[PITCH_DELAY_MAX+INTERPOL_LEN];
 +
 +    ctx->pitch_delay_int_prev = PITCH_DELAY_MIN;
 +
 +    /* random seed initialization */
 +    ctx->rand_value = 21845;
 +
 +    /* quantized prediction error */
 +    for(i=0; i<4; i++)
 +        ctx->quant_energy[i] = -14336; // -14 in (5.10)
 +
 +    ff_dsputil_init(&ctx->dsp, avctx);
 +    ctx->dsp.scalarproduct_int16 = scalarproduct_int16_c;
 +
 +    avcodec_get_frame_defaults(&ctx->frame);
 +    avctx->coded_frame = &ctx->frame;
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr,
 +                        AVPacket *avpkt)
 +{
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size       = avpkt->size;
 +    int16_t *out_frame;
 +    GetBitContext gb;
 +    const G729FormatDescription *format;
 +    int frame_erasure = 0;    ///< frame erasure detected during decoding
 +    int bad_pitch = 0;        ///< parity check failed
 +    int i;
 +    int16_t *tmp;
 +    G729Formats packet_type;
 +    G729Context *ctx = avctx->priv_data;
 +    int16_t lp[2][11];           // (3.12)
 +    uint8_t ma_predictor;     ///< switched MA predictor of LSP quantizer
 +    uint8_t quantizer_1st;    ///< first stage vector of quantizer
 +    uint8_t quantizer_2nd_lo; ///< second stage lower vector of quantizer (size in bits)
 +    uint8_t quantizer_2nd_hi; ///< second stage higher vector of quantizer (size in bits)
 +
 +    int pitch_delay_int[2];      // pitch delay, integer part
 +    int pitch_delay_3x;          // pitch delay, multiplied by 3
 +    int16_t fc[SUBFRAME_SIZE];   // fixed-codebook vector
 +    int16_t synth[SUBFRAME_SIZE+10]; // fixed-codebook vector
 +    int j, ret;
 +    int gain_before, gain_after;
 +    int is_periodic = 0;         // whether one of the subframes is declared as periodic or not
 +
 +    ctx->frame.nb_samples = SUBFRAME_SIZE<<1;
++    if ((ret = ff_get_buffer(avctx, &ctx->frame, 0)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +    out_frame = (int16_t*) ctx->frame.data[0];
 +
 +    if (buf_size == 10) {
 +        packet_type = FORMAT_G729_8K;
 +        format = &format_g729_8k;
 +        //Reset voice decision
 +        ctx->onset = 0;
 +        ctx->voice_decision = DECISION_VOICE;
 +        av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729 @ 8kbit/s");
 +    } else if (buf_size == 8) {
 +        packet_type = FORMAT_G729D_6K4;
 +        format = &format_g729d_6k4;
 +        av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729D @ 6.4kbit/s");
 +    } else {
 +        av_log(avctx, AV_LOG_ERROR, "Packet size %d is unknown.\n", buf_size);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    for (i=0; i < buf_size; i++)
 +        frame_erasure |= buf[i];
 +    frame_erasure = !frame_erasure;
 +
 +    init_get_bits(&gb, buf, 8*buf_size);
 +
 +    ma_predictor     = get_bits(&gb, 1);
 +    quantizer_1st    = get_bits(&gb, VQ_1ST_BITS);
 +    quantizer_2nd_lo = get_bits(&gb, VQ_2ND_BITS);
 +    quantizer_2nd_hi = get_bits(&gb, VQ_2ND_BITS);
 +
 +    if(frame_erasure)
 +        lsf_restore_from_previous(ctx->lsfq, ctx->past_quantizer_outputs,
 +                                  ctx->ma_predictor_prev);
 +    else {
 +        lsf_decode(ctx->lsfq, ctx->past_quantizer_outputs,
 +                   ma_predictor,
 +                   quantizer_1st, quantizer_2nd_lo, quantizer_2nd_hi);
 +        ctx->ma_predictor_prev = ma_predictor;
 +    }
 +
 +    tmp = ctx->past_quantizer_outputs[MA_NP];
 +    memmove(ctx->past_quantizer_outputs + 1, ctx->past_quantizer_outputs,
 +            MA_NP * sizeof(int16_t*));
 +    ctx->past_quantizer_outputs[0] = tmp;
 +
 +    ff_acelp_lsf2lsp(ctx->lsp[1], ctx->lsfq, 10);
 +
 +    ff_acelp_lp_decode(&lp[0][0], &lp[1][0], ctx->lsp[1], ctx->lsp[0], 10);
 +
 +    FFSWAP(int16_t*, ctx->lsp[1], ctx->lsp[0]);
 +
 +    for (i = 0; i < 2; i++) {
 +        int gain_corr_factor;
 +
 +        uint8_t ac_index;      ///< adaptive codebook index
 +        uint8_t pulses_signs;  ///< fixed-codebook vector pulse signs
 +        int fc_indexes;        ///< fixed-codebook indexes
 +        uint8_t gc_1st_index;  ///< gain codebook (first stage) index
 +        uint8_t gc_2nd_index;  ///< gain codebook (second stage) index
 +
 +        ac_index      = get_bits(&gb, format->ac_index_bits[i]);
 +        if(!i && format->parity_bit)
 +            bad_pitch = get_parity(ac_index) == get_bits1(&gb);
 +        fc_indexes    = get_bits(&gb, format->fc_indexes_bits);
 +        pulses_signs  = get_bits(&gb, format->fc_signs_bits);
 +        gc_1st_index  = get_bits(&gb, format->gc_1st_index_bits);
 +        gc_2nd_index  = get_bits(&gb, format->gc_2nd_index_bits);
 +
 +        if (frame_erasure)
 +            pitch_delay_3x   = 3 * ctx->pitch_delay_int_prev;
 +        else if(!i) {
 +            if (bad_pitch)
 +                pitch_delay_3x   = 3 * ctx->pitch_delay_int_prev;
 +            else
 +                pitch_delay_3x = ff_acelp_decode_8bit_to_1st_delay3(ac_index);
 +        } else {
 +            int pitch_delay_min = av_clip(ctx->pitch_delay_int_prev - 5,
 +                                          PITCH_DELAY_MIN, PITCH_DELAY_MAX - 9);
 +
 +            if(packet_type == FORMAT_G729D_6K4)
 +                pitch_delay_3x = ff_acelp_decode_4bit_to_2nd_delay3(ac_index, pitch_delay_min);
 +            else
 +                pitch_delay_3x = ff_acelp_decode_5_6_bit_to_2nd_delay3(ac_index, pitch_delay_min);
 +        }
 +
 +        /* Round pitch delay to nearest (used everywhere except ff_acelp_interpolate). */
 +        pitch_delay_int[i]  = (pitch_delay_3x + 1) / 3;
 +        if (pitch_delay_int[i] > PITCH_DELAY_MAX) {
 +            av_log(avctx, AV_LOG_WARNING, "pitch_delay_int %d is too large\n", pitch_delay_int[i]);
 +            pitch_delay_int[i] = PITCH_DELAY_MAX;
 +        }
 +
 +        if (frame_erasure) {
 +            ctx->rand_value = g729_prng(ctx->rand_value);
 +            fc_indexes   = ctx->rand_value & ((1 << format->fc_indexes_bits) - 1);
 +
 +            ctx->rand_value = g729_prng(ctx->rand_value);
 +            pulses_signs = ctx->rand_value;
 +        }
 +
 +
 +        memset(fc, 0, sizeof(int16_t) * SUBFRAME_SIZE);
 +        switch (packet_type) {
 +            case FORMAT_G729_8K:
 +                ff_acelp_fc_pulse_per_track(fc, ff_fc_4pulses_8bits_tracks_13,
 +                                            ff_fc_4pulses_8bits_track_4,
 +                                            fc_indexes, pulses_signs, 3, 3);
 +                break;
 +            case FORMAT_G729D_6K4:
 +                ff_acelp_fc_pulse_per_track(fc, ff_fc_2pulses_9bits_track1_gray,
 +                                            ff_fc_2pulses_9bits_track2_gray,
 +                                            fc_indexes, pulses_signs, 1, 4);
 +                break;
 +        }
 +
 +        /*
 +          This filter enhances harmonic components of the fixed-codebook vector to
 +          improve the quality of the reconstructed speech.
 +
 +                     / fc_v[i],                                    i < pitch_delay
 +          fc_v[i] = <
 +                     \ fc_v[i] + gain_pitch * fc_v[i-pitch_delay], i >= pitch_delay
 +        */
 +        ff_acelp_weighted_vector_sum(fc + pitch_delay_int[i],
 +                                     fc + pitch_delay_int[i],
 +                                     fc, 1 << 14,
 +                                     av_clip(ctx->past_gain_pitch[0], SHARP_MIN, SHARP_MAX),
 +                                     0, 14,
 +                                     SUBFRAME_SIZE - pitch_delay_int[i]);
 +
 +        memmove(ctx->past_gain_pitch+1, ctx->past_gain_pitch, 5 * sizeof(int16_t));
 +        ctx->past_gain_code[1] = ctx->past_gain_code[0];
 +
 +        if (frame_erasure) {
 +            ctx->past_gain_pitch[0] = (29491 * ctx->past_gain_pitch[0]) >> 15; // 0.90 (0.15)
 +            ctx->past_gain_code[0]  = ( 2007 * ctx->past_gain_code[0] ) >> 11; // 0.98 (0.11)
 +
 +            gain_corr_factor = 0;
 +        } else {
 +            if (packet_type == FORMAT_G729D_6K4) {
 +                ctx->past_gain_pitch[0]  = cb_gain_1st_6k4[gc_1st_index][0] +
 +                                           cb_gain_2nd_6k4[gc_2nd_index][0];
 +                gain_corr_factor = cb_gain_1st_6k4[gc_1st_index][1] +
 +                                   cb_gain_2nd_6k4[gc_2nd_index][1];
 +
 +                /* Without check below overflow can occur in ff_acelp_update_past_gain.
 +                   It is not issue for G.729, because gain_corr_factor in it's case is always
 +                   greater than 1024, while in G.729D it can be even zero. */
 +                gain_corr_factor = FFMAX(gain_corr_factor, 1024);
 +#ifndef G729_BITEXACT
 +                gain_corr_factor >>= 1;
 +#endif
 +            } else {
 +                ctx->past_gain_pitch[0]  = cb_gain_1st_8k[gc_1st_index][0] +
 +                                           cb_gain_2nd_8k[gc_2nd_index][0];
 +                gain_corr_factor = cb_gain_1st_8k[gc_1st_index][1] +
 +                                   cb_gain_2nd_8k[gc_2nd_index][1];
 +            }
 +
 +            /* Decode the fixed-codebook gain. */
 +            ctx->past_gain_code[0] = ff_acelp_decode_gain_code(&ctx->dsp, gain_corr_factor,
 +                                                               fc, MR_ENERGY,
 +                                                               ctx->quant_energy,
 +                                                               ma_prediction_coeff,
 +                                                               SUBFRAME_SIZE, 4);
 +#ifdef G729_BITEXACT
 +            /*
 +              This correction required to get bit-exact result with
 +              reference code, because gain_corr_factor in G.729D is
 +              two times larger than in original G.729.
 +
 +              If bit-exact result is not issue then gain_corr_factor
 +              can be simpler divided by 2 before call to g729_get_gain_code
 +              instead of using correction below.
 +            */
 +            if (packet_type == FORMAT_G729D_6K4) {
 +                gain_corr_factor >>= 1;
 +                ctx->past_gain_code[0] >>= 1;
 +            }
 +#endif
 +        }
 +        ff_acelp_update_past_gain(ctx->quant_energy, gain_corr_factor, 2, frame_erasure);
 +
 +        /* Routine requires rounding to lowest. */
 +        ff_acelp_interpolate(ctx->exc + i * SUBFRAME_SIZE,
 +                             ctx->exc + i * SUBFRAME_SIZE - pitch_delay_3x / 3,
 +                             ff_acelp_interp_filter, 6,
 +                             (pitch_delay_3x % 3) << 1,
 +                             10, SUBFRAME_SIZE);
 +
 +        ff_acelp_weighted_vector_sum(ctx->exc + i * SUBFRAME_SIZE,
 +                                     ctx->exc + i * SUBFRAME_SIZE, fc,
 +                                     (!ctx->was_periodic && frame_erasure) ? 0 : ctx->past_gain_pitch[0],
 +                                     ( ctx->was_periodic && frame_erasure) ? 0 : ctx->past_gain_code[0],
 +                                     1 << 13, 14, SUBFRAME_SIZE);
 +
 +        memcpy(synth, ctx->syn_filter_data, 10 * sizeof(int16_t));
 +
 +        if (ff_celp_lp_synthesis_filter(
 +            synth+10,
 +            &lp[i][1],
 +            ctx->exc  + i * SUBFRAME_SIZE,
 +            SUBFRAME_SIZE,
 +            10,
 +            1,
 +            0,
 +            0x800))
 +            /* Overflow occurred, downscale excitation signal... */
 +            for (j = 0; j < 2 * SUBFRAME_SIZE + PITCH_DELAY_MAX + INTERPOL_LEN; j++)
 +                ctx->exc_base[j] >>= 2;
 +
 +        /* ... and make synthesis again. */
 +        if (packet_type == FORMAT_G729D_6K4) {
 +            int16_t exc_new[SUBFRAME_SIZE];
 +
 +            ctx->onset = g729d_onset_decision(ctx->onset, ctx->past_gain_code);
 +            ctx->voice_decision = g729d_voice_decision(ctx->onset, ctx->voice_decision, ctx->past_gain_pitch);
 +
 +            g729d_get_new_exc(exc_new, ctx->exc  + i * SUBFRAME_SIZE, fc, ctx->voice_decision, ctx->past_gain_code[0], SUBFRAME_SIZE);
 +
 +            ff_celp_lp_synthesis_filter(
 +                    synth+10,
 +                    &lp[i][1],
 +                    exc_new,
 +                    SUBFRAME_SIZE,
 +                    10,
 +                    0,
 +                    0,
 +                    0x800);
 +        } else {
 +            ff_celp_lp_synthesis_filter(
 +                    synth+10,
 +                    &lp[i][1],
 +                    ctx->exc  + i * SUBFRAME_SIZE,
 +                    SUBFRAME_SIZE,
 +                    10,
 +                    0,
 +                    0,
 +                    0x800);
 +        }
 +        /* Save data (without postfilter) for use in next subframe. */
 +        memcpy(ctx->syn_filter_data, synth+SUBFRAME_SIZE, 10 * sizeof(int16_t));
 +
 +        /* Calculate gain of unfiltered signal for use in AGC. */
 +        gain_before = 0;
 +        for (j = 0; j < SUBFRAME_SIZE; j++)
 +            gain_before += FFABS(synth[j+10]);
 +
 +        /* Call postfilter and also update voicing decision for use in next frame. */
 +        ff_g729_postfilter(
 +                &ctx->dsp,
 +                &ctx->ht_prev_data,
 +                &is_periodic,
 +                &lp[i][0],
 +                pitch_delay_int[0],
 +                ctx->residual,
 +                ctx->res_filter_data,
 +                ctx->pos_filter_data,
 +                synth+10,
 +                SUBFRAME_SIZE);
 +
 +        /* Calculate gain of filtered signal for use in AGC. */
 +        gain_after = 0;
 +        for(j=0; j<SUBFRAME_SIZE; j++)
 +            gain_after += FFABS(synth[j+10]);
 +
 +        ctx->gain_coeff = ff_g729_adaptive_gain_control(
 +                gain_before,
 +                gain_after,
 +                synth+10,
 +                SUBFRAME_SIZE,
 +                ctx->gain_coeff);
 +
 +        if (frame_erasure)
 +            ctx->pitch_delay_int_prev = FFMIN(ctx->pitch_delay_int_prev + 1, PITCH_DELAY_MAX);
 +        else
 +            ctx->pitch_delay_int_prev = pitch_delay_int[i];
 +
 +        memcpy(synth+8, ctx->hpf_z, 2*sizeof(int16_t));
 +        ff_acelp_high_pass_filter(
 +                out_frame + i*SUBFRAME_SIZE,
 +                ctx->hpf_f,
 +                synth+10,
 +                SUBFRAME_SIZE);
 +        memcpy(ctx->hpf_z, synth+8+SUBFRAME_SIZE, 2*sizeof(int16_t));
 +    }
 +
 +    ctx->was_periodic = is_periodic;
 +
 +    /* Save signal for use in next frame. */
 +    memmove(ctx->exc_base, ctx->exc_base + 2 * SUBFRAME_SIZE, (PITCH_DELAY_MAX+INTERPOL_LEN)*sizeof(int16_t));
 +
 +    *got_frame_ptr = 1;
 +    *(AVFrame*)data = ctx->frame;
 +    return buf_size;
 +}
 +
 +AVCodec ff_g729_decoder = {
 +    .name           = "g729",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_G729,
 +    .priv_data_size = sizeof(G729Context),
 +    .init           = decoder_init,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("G.729"),
 +};
  #include "bytestream.h"
  #include "internal.h"
  #include "lzw.h"
 +#include "gif.h"
  
 -#define GCE_DISPOSAL_NONE       0
 -#define GCE_DISPOSAL_INPLACE    1
 -#define GCE_DISPOSAL_BACKGROUND 2
 -#define GCE_DISPOSAL_RESTORE    3
 +/* This value is intentionally set to "transparent white" color.
 + * It is much better to have white background instead of black
 + * when gif image converted to format which not support transparency.
 + */
 +#define GIF_TRANSPARENT_COLOR    0x00ffffff
  
  typedef struct GifState {
-     AVFrame picture;
 +    const AVClass *class;
++    AVFrame *frame;
      int screen_width;
      int screen_height;
 +    int has_global_palette;
      int bits_per_pixel;
 +    uint32_t bg_color;
      int background_color_index;
      int transparent_color_index;
      int color_resolution;
      LZWState *lzw;
  
      /* aux buffers */
 -    uint8_t global_palette[256 * 3];
 -    uint8_t local_palette[256 * 3];
 +    uint32_t global_palette[256];
 +    uint32_t local_palette[256];
  
 -  AVCodecContext* avctx;
 +    AVCodecContext *avctx;
 +    int keyframe;
 +    int keyframe_ok;
 +    int trans_color;    /**< color value that is used instead of transparent color */
  } GifState;
  
 -static const uint8_t gif87a_sig[6] = "GIF87a";
 -static const uint8_t gif89a_sig[6] = "GIF89a";
 +static void gif_read_palette(GifState *s, uint32_t *pal, int nb)
 +{
 +    int i;
 +
 +    for (i = 0; i < nb; i++, pal++)
 +        *pal = (0xffu << 24) | bytestream2_get_be24u(&s->gb);
 +}
 +
 +static void gif_fill(AVFrame *picture, uint32_t color)
 +{
 +    uint32_t *p = (uint32_t *)picture->data[0];
 +    uint32_t *p_end = p + (picture->linesize[0] / sizeof(uint32_t)) * picture->height;
 +
 +    for (; p < p_end; p++)
 +        *p = color;
 +}
 +
 +static void gif_fill_rect(AVFrame *picture, uint32_t color, int l, int t, int w, int h)
 +{
 +    const int linesize = picture->linesize[0] / sizeof(uint32_t);
 +    const uint32_t *py = (uint32_t *)picture->data[0] + t * linesize;
 +    const uint32_t *pr, *pb = py + h * linesize;
 +    uint32_t *px;
 +
 +    for (; py < pb; py += linesize) {
 +        px = (uint32_t *)py + l;
 +        pr = px + w;
 +
 +        for (; px < pr; px++)
 +            *px = color;
 +    }
 +}
 +
 +static void gif_copy_img_rect(const uint32_t *src, uint32_t *dst,
 +                              int linesize, int l, int t, int w, int h)
 +{
 +    const int y_start = t * linesize;
 +    const uint32_t *src_px,
 +                   *src_py = src + y_start,
 +                   *dst_py = dst + y_start;
 +    const uint32_t *src_pb = src_py + h * linesize;
 +    uint32_t *dst_px;
 +
 +    for (; src_py < src_pb; src_py += linesize, dst_py += linesize) {
 +        src_px = src_py + l;
 +        dst_px = (uint32_t *)dst_py + l;
 +
 +        memcpy(dst_px, src_px, w * sizeof(uint32_t));
 +    }
 +}
  
- static int gif_read_image(GifState *s)
+ static int gif_read_image(GifState *s, AVFrame *frame)
  {
      int left, top, width, height, bits_per_pixel, code_size, flags;
 -    int is_interleaved, has_local_palette, y, pass, y1, linesize, n, i;
 -    uint8_t *ptr, *spal, *palette, *ptr1;
 -
 -    left = bytestream_get_le16(&s->bytestream);
 -    top = bytestream_get_le16(&s->bytestream);
 -    width = bytestream_get_le16(&s->bytestream);
 -    height = bytestream_get_le16(&s->bytestream);
 -    flags = bytestream_get_byte(&s->bytestream);
 +    int is_interleaved, has_local_palette, y, pass, y1, linesize, pal_size;
 +    uint32_t *ptr, *pal, *px, *pr, *ptr1;
 +    int ret;
 +    uint8_t *idx;
 +
 +    /* At least 9 bytes of Image Descriptor. */
 +    if (bytestream2_get_bytes_left(&s->gb) < 9)
 +        return AVERROR_INVALIDDATA;
 +
 +    left = bytestream2_get_le16u(&s->gb);
 +    top = bytestream2_get_le16u(&s->gb);
 +    width = bytestream2_get_le16u(&s->gb);
 +    height = bytestream2_get_le16u(&s->gb);
 +    flags = bytestream2_get_byteu(&s->gb);
      is_interleaved = flags & 0x40;
      has_local_palette = flags & 0x80;
      bits_per_pixel = (flags & 0x07) + 1;
  
 -    av_dlog(s->avctx, "gif: image x=%d y=%d w=%d h=%d\n", left, top, width, height);
 +    av_dlog(s->avctx, "image x=%d y=%d w=%d h=%d\n", left, top, width, height);
  
      if (has_local_palette) {
 -        bytestream_get_buffer(&s->bytestream, s->local_palette, 3 * (1 << bits_per_pixel));
 -        palette = s->local_palette;
 +        pal_size = 1 << bits_per_pixel;
 +
 +        if (bytestream2_get_bytes_left(&s->gb) < pal_size * 3)
 +            return AVERROR_INVALIDDATA;
 +
 +        gif_read_palette(s, s->local_palette, pal_size);
 +        pal = s->local_palette;
      } else {
 -        palette = s->global_palette;
 -        bits_per_pixel = s->bits_per_pixel;
 +        if (!s->has_global_palette) {
 +            av_log(s->avctx, AV_LOG_ERROR, "picture doesn't have either global or local palette.\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        pal = s->global_palette;
 +    }
 +
 +    if (s->keyframe) {
 +        if (s->transparent_color_index == -1 && s->has_global_palette) {
 +            /* transparency wasn't set before the first frame, fill with background color */
-             gif_fill(&s->picture, s->bg_color);
++            gif_fill(frame, s->bg_color);
 +        } else {
 +            /* otherwise fill with transparent color.
 +             * this is necessary since by default picture filled with 0x80808080. */
-             gif_fill(&s->picture, s->trans_color);
++            gif_fill(frame, s->trans_color);
 +        }
      }
  
      /* verify that all the image is inside the screen dimensions */
      if (left + width > s->screen_width ||
          top + height > s->screen_height)
 -        return AVERROR(EINVAL);
 -
 -    /* build the palette */
 -    n = (1 << bits_per_pixel);
 -    spal = palette;
 -    for(i = 0; i < n; i++) {
 -        s->image_palette[i] = (0xffu << 24) | AV_RB24(spal);
 -        spal += 3;
 +        return AVERROR_INVALIDDATA;
 +    if (width <= 0 || height <= 0)
 +        return AVERROR_INVALIDDATA;
 +
 +    /* process disposal method */
 +    if (s->gce_prev_disposal == GCE_DISPOSAL_BACKGROUND) {
-         gif_fill_rect(&s->picture, s->stored_bg_color, s->gce_l, s->gce_t, s->gce_w, s->gce_h);
++        gif_fill_rect(frame, s->stored_bg_color, s->gce_l, s->gce_t, s->gce_w, s->gce_h);
 +    } else if (s->gce_prev_disposal == GCE_DISPOSAL_RESTORE) {
-         gif_copy_img_rect(s->stored_img, (uint32_t *)s->picture.data[0],
-             s->picture.linesize[0] / sizeof(uint32_t), s->gce_l, s->gce_t, s->gce_w, s->gce_h);
++        gif_copy_img_rect(s->stored_img, (uint32_t *)frame->data[0],
++            frame->linesize[0] / sizeof(uint32_t), s->gce_l, s->gce_t, s->gce_w, s->gce_h);
      }
 -    for(; i < 256; i++)
 -        s->image_palette[i] = (0xffu << 24);
 -    /* handle transparency */
 -    if (s->transparent_color_index >= 0)
 -        s->image_palette[s->transparent_color_index] = 0;
 +
 +    s->gce_prev_disposal = s->gce_disposal;
 +
 +    if (s->gce_disposal != GCE_DISPOSAL_NONE) {
 +        s->gce_l = left;  s->gce_t = top;
 +        s->gce_w = width; s->gce_h = height;
 +
 +        if (s->gce_disposal == GCE_DISPOSAL_BACKGROUND) {
 +            if (s->transparent_color_index >= 0)
 +                s->stored_bg_color = s->trans_color;
 +            else
 +                s->stored_bg_color = s->bg_color;
 +        } else if (s->gce_disposal == GCE_DISPOSAL_RESTORE) {
-             av_fast_malloc(&s->stored_img, &s->stored_img_size, s->picture.linesize[0] * s->picture.height);
++            av_fast_malloc(&s->stored_img, &s->stored_img_size, frame->linesize[0] * frame->height);
 +            if (!s->stored_img)
 +                return AVERROR(ENOMEM);
 +
-             gif_copy_img_rect((uint32_t *)s->picture.data[0], s->stored_img,
-                 s->picture.linesize[0] / sizeof(uint32_t), left, top, width, height);
++            gif_copy_img_rect((uint32_t *)frame->data[0], s->stored_img,
++                frame->linesize[0] / sizeof(uint32_t), left, top, width, height);
 +        }
 +    }
 +
 +    /* Expect at least 2 bytes: 1 for lzw code size and 1 for block size. */
 +    if (bytestream2_get_bytes_left(&s->gb) < 2)
 +        return AVERROR_INVALIDDATA;
  
      /* now get the image data */
 -    code_size = bytestream_get_byte(&s->bytestream);
 -    ff_lzw_decode_init(s->lzw, code_size, s->bytestream,
 -                       s->bytestream_end - s->bytestream, FF_LZW_GIF);
 +    code_size = bytestream2_get_byteu(&s->gb);
 +    if ((ret = ff_lzw_decode_init(s->lzw, code_size, s->gb.buffer,
 +                                  bytestream2_get_bytes_left(&s->gb), FF_LZW_GIF)) < 0) {
 +        av_log(s->avctx, AV_LOG_ERROR, "LZW init failed\n");
 +        return ret;
 +    }
  
      /* read all the image */
-     linesize = s->picture.linesize[0] / sizeof(uint32_t);
-     ptr1 = (uint32_t *)s->picture.data[0] + top * linesize + left;
 -    linesize = frame->linesize[0];
 -    ptr1 = frame->data[0] + top * linesize + left;
++    linesize = frame->linesize[0] / sizeof(uint32_t);
++    ptr1 = (uint32_t *)frame->data[0] + top * linesize + left;
      ptr = ptr1;
      pass = 0;
      y1 = 0;
@@@ -400,18 -244,18 +400,18 @@@ static int gif_read_header1(GifState *s
      return 0;
  }
  
- static int gif_parse_next_image(GifState *s)
+ static int gif_parse_next_image(GifState *s, AVFrame *frame)
  {
 -    while (s->bytestream < s->bytestream_end) {
 -        int code = bytestream_get_byte(&s->bytestream);
 +    while (bytestream2_get_bytes_left(&s->gb)) {
 +        int code = bytestream2_get_byte(&s->gb);
          int ret;
  
 -        av_dlog(s->avctx, "gif: code=%02x '%c'\n", code, code);
 +        av_dlog(s->avctx, "code=%02x '%c'\n", code, code);
  
          switch (code) {
 -        case ',':
 +        case GIF_IMAGE_SEPARATOR:
-             return gif_read_image(s);
+             return gif_read_image(s, frame);
 -        case '!':
 +        case GIF_EXTENSION_INTRODUCER:
              if ((ret = gif_read_extension(s)) < 0)
                  return ret;
              break;
@@@ -432,81 -275,40 +432,79 @@@ static av_cold int gif_decode_init(AVCo
  
      s->avctx = avctx;
  
-     avcodec_get_frame_defaults(&s->picture);
-     avctx->coded_frame= &s->picture;
-     s->picture.data[0] = NULL;
 +    avctx->pix_fmt = AV_PIX_FMT_RGB32;
++    s->frame = av_frame_alloc();
++    if (!s->frame)
++        return AVERROR(ENOMEM);
      ff_lzw_decode_open(&s->lzw);
      return 0;
  }
  
 -static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 -                            AVPacket *avpkt)
 +static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
  {
 -    const uint8_t *buf = avpkt->data;
 -    int buf_size = avpkt->size;
      GifState *s = avctx->priv_data;
--    AVFrame *picture = data;
      int ret;
  
 -    s->bytestream = buf;
 -    s->bytestream_end = buf + buf_size;
 -    if ((ret = gif_read_header1(s)) < 0)
 -        return ret;
 +    bytestream2_init(&s->gb, avpkt->data, avpkt->size);
  
-     s->picture.pts          = avpkt->pts;
-     s->picture.pkt_pts      = avpkt->pts;
-     s->picture.pkt_dts      = avpkt->dts;
-     av_frame_set_pkt_duration(&s->picture, avpkt->duration);
 -    avctx->pix_fmt = AV_PIX_FMT_PAL8;
 -    if ((ret = av_image_check_size(s->screen_width, s->screen_height, 0, avctx)) < 0)
 -        return ret;
 -    avcodec_set_dimensions(avctx, s->screen_width, s->screen_height);
++    s->frame->pts     = avpkt->pts;
++    s->frame->pkt_pts = avpkt->pts;
++    s->frame->pkt_dts = avpkt->dts;
++    av_frame_set_pkt_duration(s->frame, avpkt->duration);
  
 -    if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -        return ret;
 +    if (avpkt->size >= 6) {
 +        s->keyframe = memcmp(avpkt->data, gif87a_sig, 6) == 0 ||
 +                      memcmp(avpkt->data, gif89a_sig, 6) == 0;
 +    } else {
 +        s->keyframe = 0;
 +    }
 +
 +    if (s->keyframe) {
 +        s->keyframe_ok = 0;
 +        if ((ret = gif_read_header1(s)) < 0)
 +            return ret;
 +
 +        if ((ret = av_image_check_size(s->screen_width, s->screen_height, 0, avctx)) < 0)
 +            return ret;
 +        avcodec_set_dimensions(avctx, s->screen_width, s->screen_height);
 +
-         if (s->picture.data[0])
-             avctx->release_buffer(avctx, &s->picture);
-         if ((ret = ff_get_buffer(avctx, &s->picture)) < 0) {
++        av_frame_unref(s->frame);
++        if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +            return ret;
 +        }
 +
 +        av_fast_malloc(&s->idx_line, &s->idx_line_size, s->screen_width);
 +        if (!s->idx_line)
 +            return AVERROR(ENOMEM);
 +
-         s->picture.pict_type = AV_PICTURE_TYPE_I;
-         s->picture.key_frame = 1;
++        s->frame->pict_type = AV_PICTURE_TYPE_I;
++        s->frame->key_frame = 1;
 +        s->keyframe_ok = 1;
 +    } else {
 +        if (!s->keyframe_ok) {
 +            av_log(avctx, AV_LOG_ERROR, "cannot decode frame without keyframe\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
-         if ((ret = avctx->reget_buffer(avctx, &s->picture)) < 0) {
++        if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 +            return ret;
 +        }
 +
-         s->picture.pict_type = AV_PICTURE_TYPE_P;
-         s->picture.key_frame = 0;
++        s->frame->pict_type = AV_PICTURE_TYPE_P;
++        s->frame->key_frame = 0;
      }
 -    s->image_palette = (uint32_t *)picture->data[1];
 -    ret = gif_parse_next_image(s, picture);
 +
-     ret = gif_parse_next_image(s);
++    ret = gif_parse_next_image(s, s->frame);
      if (ret < 0)
          return ret;
  
-     *picture = s->picture;
++    if ((ret = av_frame_ref(data, s->frame)) < 0)
++        return ret;
      *got_frame = 1;
 -    return s->bytestream - buf;
 +
 +    return avpkt->size;
  }
  
  static av_cold int gif_decode_close(AVCodecContext *avctx)
      GifState *s = avctx->priv_data;
  
      ff_lzw_decode_close(&s->lzw);
-     if(s->picture.data[0])
-         avctx->release_buffer(avctx, &s->picture);
++    av_frame_free(&s->frame);
 +    av_freep(&s->idx_line);
 +    av_freep(&s->stored_img);
 +
      return 0;
  }
  
Simple merge
@@@ -629,11 -621,12 +629,12 @@@ retry
      }
      ff_MPV_frame_end(s);
  
 -assert(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type);
 -assert(s->current_picture.f.pict_type == s->pict_type);
 +    av_assert0(s->current_picture.f.pict_type == s->current_picture_ptr->f.pict_type);
 +    av_assert0(s->current_picture.f.pict_type == s->pict_type);
  
-     *pict = s->current_picture_ptr->f;
-     ff_print_debug_info(s, pict);
+     if ((ret = av_frame_ref(pict, &s->current_picture_ptr->f)) < 0)
+         return ret;
+     ff_print_debug_info(s, s->current_picture_ptr);
  
      *got_frame = 1;
  
Simple merge
Simple merge
@@@ -126,15 -113,7 +126,15 @@@ static void h264_er_decode_mb(void *opa
       * practice then correct remapping should be added. */
      if (ref >= h->ref_count[0])
          ref = 0;
-     if ((h->ref_list[0][ref].f.reference&3) != 3) {
 +    if (!h->ref_list[0][ref].f.data[0]) {
 +        av_log(h->avctx, AV_LOG_DEBUG, "Reference not available for error concealing\n");
 +        ref = 0;
 +    }
-     fill_rectangle(&h->cur_pic.f.ref_index[0][4 * h->mb_xy],
++    if ((h->ref_list[0][ref].reference&3) != 3) {
 +        av_log(h->avctx, AV_LOG_DEBUG, "Reference invalid\n");
 +        return;
 +    }
+     fill_rectangle(&h->cur_pic.ref_index[0][4 * h->mb_xy],
                     2, 2, 2, ref, 1);
      fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
      fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8,
@@@ -188,29 -166,25 +188,26 @@@ void ff_h264_draw_horiz_band(H264Contex
      }
  }
  
- static void free_frame_buffer(H264Context *h, Picture *pic)
- {
-     pic->period_since_free = 0;
-     ff_thread_release_buffer(h->avctx, &pic->f);
-     av_freep(&pic->f.hwaccel_picture_private);
- }
- static void free_picture(H264Context *h, Picture *pic)
+ static void unref_picture(H264Context *h, Picture *pic)
  {
+     int off = offsetof(Picture, tf) + sizeof(pic->tf);
      int i;
  
-     if (pic->f.data[0])
-         free_frame_buffer(h, pic);
+     if (!pic->f.data[0])
+         return;
++    pic->period_since_free = 0;
+     ff_thread_release_buffer(h->avctx, &pic->tf);
+     av_buffer_unref(&pic->hwaccel_priv_buf);
  
-     av_freep(&pic->qscale_table_base);
-     pic->f.qscale_table = NULL;
-     av_freep(&pic->mb_type_base);
-     pic->f.mb_type = NULL;
+     av_buffer_unref(&pic->qscale_table_buf);
+     av_buffer_unref(&pic->mb_type_buf);
      for (i = 0; i < 2; i++) {
-         av_freep(&pic->motion_val_base[i]);
-         av_freep(&pic->f.ref_index[i]);
-         pic->f.motion_val[i] = NULL;
+         av_buffer_unref(&pic->motion_val_buf[i]);
+         av_buffer_unref(&pic->ref_index_buf[i]);
      }
+     memset((uint8_t*)pic + off, 0, sizeof(*pic) - off);
  }
  
  static void release_unused_pictures(H264Context *h, int remove_current)
      }
  }
  
+ static int ref_picture(H264Context *h, Picture *dst, Picture *src)
+ {
+     int ret, i;
+     av_assert0(!dst->f.buf[0]);
+     av_assert0(src->f.buf[0]);
+     src->tf.f = &src->f;
+     dst->tf.f = &dst->f;
+     ret = ff_thread_ref_frame(&dst->tf, &src->tf);
+     if (ret < 0)
+         goto fail;
+     dst->qscale_table_buf = av_buffer_ref(src->qscale_table_buf);
+     dst->mb_type_buf      = av_buffer_ref(src->mb_type_buf);
+     if (!dst->qscale_table_buf || !dst->mb_type_buf)
+         goto fail;
+     dst->qscale_table = src->qscale_table;
+     dst->mb_type      = src->mb_type;
+     for (i = 0; i < 2; i ++) {
+         dst->motion_val_buf[i] = av_buffer_ref(src->motion_val_buf[i]);
+         dst->ref_index_buf[i]  = av_buffer_ref(src->ref_index_buf[i]);
+         if (!dst->motion_val_buf[i] || !dst->ref_index_buf[i])
+             goto fail;
+         dst->motion_val[i] = src->motion_val[i];
+         dst->ref_index[i]  = src->ref_index[i];
+     }
+     if (src->hwaccel_picture_private) {
+         dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
+         if (!dst->hwaccel_priv_buf)
+             goto fail;
+         dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
+     }
+     for (i = 0; i < 2; i++)
+         dst->field_poc[i] = src->field_poc[i];
+     memcpy(dst->ref_poc,   src->ref_poc,   sizeof(src->ref_poc));
+     memcpy(dst->ref_count, src->ref_count, sizeof(src->ref_count));
+     dst->poc                     = src->poc;
+     dst->frame_num               = src->frame_num;
+     dst->mmco_reset              = src->mmco_reset;
+     dst->pic_id                  = src->pic_id;
+     dst->long_ref                = src->long_ref;
+     dst->mbaff                   = src->mbaff;
+     dst->field_picture           = src->field_picture;
+     dst->needs_realloc           = src->needs_realloc;
+     dst->reference               = src->reference;
++    dst->sync                    = src->sync;
++    dst->period_since_free       = src->period_since_free;
+     return 0;
+ fail:
+     unref_picture(h, dst);
+     return ret;
+ }
  static int alloc_scratch_buffers(H264Context *h, int linesize)
  {
      int alloc_size = FFALIGN(FFABS(linesize) + 32, 32);
@@@ -311,15 -370,10 +395,14 @@@ fail
  
  static inline int pic_is_unused(H264Context *h, Picture *pic)
  {
 +    if (   (h->avctx->active_thread_type & FF_THREAD_FRAME)
 +        && pic->f.qscale_table //check if the frame has anything allocated
 +        && pic->period_since_free < h->avctx->thread_count)
 +        return 0;
      if (pic->f.data[0] == NULL)
          return 1;
-     if (pic->needs_realloc && !(pic->f.reference & DELAYED_PIC_REF))
-         if (!pic->owner2 || pic->owner2 == h)
-             return 1;
+     if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF))
+         return 1;
      return 0;
  }
  
@@@ -1040,16 -1089,17 +1122,20 @@@ static void free_tables(H264Context *h
      av_freep(&h->mb2b_xy);
      av_freep(&h->mb2br_xy);
  
-     if (free_rbsp) {
-         for (i = 0; i < h->picture_count && !h->avctx->internal->is_copy; i++)
-             free_picture(h, &h->DPB[i]);
 +    for (i = 0; i < 3; i++)
 +        av_freep(&h->visualization_buffer[i]);
 +
+     av_buffer_pool_uninit(&h->qscale_table_pool);
+     av_buffer_pool_uninit(&h->mb_type_pool);
+     av_buffer_pool_uninit(&h->motion_val_pool);
+     av_buffer_pool_uninit(&h->ref_index_pool);
+     if (free_rbsp && h->DPB) {
+         for (i = 0; i < MAX_PICTURE_COUNT; i++)
+             unref_picture(h, &h->DPB[i]);
          av_freep(&h->DPB);
-         h->picture_count = 0;
      } else if (h->DPB) {
-         for (i = 0; i < h->picture_count; i++)
+         for (i = 0; i < MAX_PICTURE_COUNT; i++)
              h->DPB[i].needs_realloc = 1;
      }
  
@@@ -1461,7 -1489,7 +1544,8 @@@ av_cold int ff_h264_decode_init(AVCodec
          h->low_delay           = 0;
      }
  
 +    ff_init_cabac_states();
+     avctx->internal->allocate_progress = 1;
  
      return 0;
  }
@@@ -1531,9 -1559,9 +1615,9 @@@ static int decode_update_thread_context
      H264Context *h = dst->priv_data, *h1 = src->priv_data;
      int inited = h->context_initialized, err = 0;
      int context_reinitialized = 0;
-     int i;
+     int i, ret;
  
 -    if (dst == src || !h1->context_initialized)
 +    if (dst == src)
          return 0;
  
      if (inited &&
          for (i = 0; i < MAX_PPS_COUNT; i++)
              av_freep(h->pps_buffers + i);
  
 -        memcpy(h, h1, sizeof(*h1));
 +        memcpy(h, h1, offsetof(H264Context, intra_pcm_ptr));
 +        memcpy(&h->cabac, &h1->cabac,
 +               sizeof(H264Context) - offsetof(H264Context, cabac));
 +        av_assert0((void*)&h->cabac == &h->mb_padding + 1);
 +
          memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
          memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
 +
          memset(&h->er, 0, sizeof(h->er));
          memset(&h->me, 0, sizeof(h->me));
 -        h->context_initialized = 0;
 -
 -        memset(&h->cur_pic, 0, sizeof(h->cur_pic));
 -        avcodec_get_frame_defaults(&h->cur_pic.f);
 -        h->cur_pic.tf.f = &h->cur_pic.f;
 -
          h->avctx = dst;
          h->DPB   = NULL;
+         h->qscale_table_pool = NULL;
+         h->mb_type_pool = NULL;
+         h->ref_index_pool = NULL;
+         h->motion_val_pool = NULL;
  
-         h->picture_range_start  += MAX_PICTURE_COUNT;
-         h->picture_range_end    += MAX_PICTURE_COUNT;
-         h->cur_pic.f.extended_data = h->cur_pic.f.data;
 +        if (h1->context_initialized) {
 +        h->context_initialized = 0;
 +
++        memset(&h->cur_pic, 0, sizeof(h->cur_pic));
++        avcodec_get_frame_defaults(&h->cur_pic.f);
++        h->cur_pic.tf.f = &h->cur_pic.f;
 +
          if (ff_h264_alloc_tables(h) < 0) {
              av_log(dst, AV_LOG_ERROR, "Could not allocate memory for h264\n");
              return AVERROR(ENOMEM);
      h->data_partitioning    = h1->data_partitioning;
      h->low_delay            = h1->low_delay;
  
-     memcpy(h->DPB, h1->DPB, h1->picture_count * sizeof(*h1->DPB));
-     // reset s->picture[].f.extended_data to s->picture[].f.data
-     for (i = 0; i < h->picture_count; i++) {
-         h->DPB[i].f.extended_data = h->DPB[i].f.data;
+     for (i = 0; i < MAX_PICTURE_COUNT; i++) {
 +        h->DPB[i].period_since_free ++;
+         unref_picture(h, &h->DPB[i]);
+         if (h1->DPB[i].f.data[0] &&
+             (ret = ref_picture(h, &h->DPB[i], &h1->DPB[i])) < 0)
+             return ret;
      }
  
      h->cur_pic_ptr     = REBASE_PICTURE(h1->cur_pic_ptr, h, h1);
@@@ -1741,10 -1749,9 +1829,10 @@@ int ff_h264_frame_start(H264Context *h
      }
      pic = &h->DPB[i];
  
-     pic->f.reference            = h->droppable ? 0 : h->picture_structure;
+     pic->reference            = h->droppable ? 0 : h->picture_structure;
      pic->f.coded_picture_number = h->coded_picture_number++;
      pic->field_picture          = h->picture_structure != PICT_FRAME;
 +
      /*
       * Zero key_frame here; IDR markings per slice in frame or fields are ORed
       * in later.
  
      if ((ret = alloc_picture(h, pic)) < 0)
          return ret;
 +    if(!h->sync && !h->avctx->hwaccel &&
 +       !(h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU))
 +        avpriv_color_frame(&pic->f, c);
  
      h->cur_pic_ptr = pic;
-     h->cur_pic     = *h->cur_pic_ptr;
-     h->cur_pic.f.extended_data = h->cur_pic.f.data;
+     unref_picture(h, &h->cur_pic);
+     if ((ret = ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0)
+         return ret;
  
 -    ff_er_frame_start(&h->er);
 +    if (CONFIG_ERROR_RESILIENCE) {
 +        ff_er_frame_start(&h->er);
 +        h->er.last_pic =
 +        h->er.next_pic = NULL;
 +    }
  
      assert(h->linesize && h->uvlinesize);
  
      memset(h->slice_table, -1,
             (h->mb_height * h->mb_stride - 1) * sizeof(*h->slice_table));
  
 -    // s->decode = (s->flags & CODEC_FLAG_PSNR) || !s->encoding ||
 -    //             s->current_picture.f.reference /* || h->contains_intra */ || 1;
 +    // s->decode = (h->flags & CODEC_FLAG_PSNR) || !s->encoding ||
-     //             h->cur_pic.f.reference /* || h->contains_intra */ || 1;
++    //             h->cur_pic.reference /* || h->contains_intra */ || 1;
  
      /* We mark the current picture as non-reference after allocating it, so
       * that if we break out due to an error it can be released automatically
@@@ -1822,8 -1831,8 +1911,7 @@@ static void decode_postinit(H264Contex
      Picture *out = h->cur_pic_ptr;
      Picture *cur = h->cur_pic_ptr;
      int i, pics, out_of_order, out_idx;
 -    int invalid = 0, cnt = 0;
  
-     h->cur_pic_ptr->f.qscale_type = FF_QSCALE_TYPE_H264;
      h->cur_pic_ptr->f.pict_type   = h->pict_type;
  
      if (h->next_output_pic)
      while (h->delayed_pic[pics])
          pics++;
  
 -    assert(pics <= MAX_DELAYED_PIC_COUNT);
 +    av_assert0(pics <= MAX_DELAYED_PIC_COUNT);
  
      h->delayed_pic[pics++] = cur;
-     if (cur->f.reference == 0)
-         cur->f.reference = DELAYED_PIC_REF;
+     if (cur->reference == 0)
+         cur->reference = DELAYED_PIC_REF;
  
 -    /* Frame reordering. This code takes pictures from coding order and sorts
 -     * them by their incremental POC value into display order. It supports POC
 -     * gaps, MMCO reset codes and random resets.
 -     * A "display group" can start either with a IDR frame (f.key_frame = 1),
 -     * and/or can be closed down with a MMCO reset code. In sequences where
 -     * there is no delay, we can't detect that (since the frame was already
 -     * output to the user), so we also set h->mmco_reset to detect the MMCO
 -     * reset code.
 -     * FIXME: if we detect insufficient delays (as per h->avctx->has_b_frames),
 -     * we increase the delay between input and output. All frames affected by
 -     * the lag (e.g. those that should have been output before another frame
 -     * that we already returned to the user) will be dropped. This is a bug
 -     * that we will fix later. */
 -    for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) {
 -        cnt     += out->poc < h->last_pocs[i];
 -        invalid += out->poc == INT_MIN;
 -    }
 -    if (!h->mmco_reset && !cur->f.key_frame &&
 -        cnt + invalid == MAX_DELAYED_PIC_COUNT && cnt > 0) {
 -        h->mmco_reset = 2;
 -        if (pics > 1)
 -            h->delayed_pic[pics - 2]->mmco_reset = 2;
 -    }
 -    if (h->mmco_reset || cur->f.key_frame) {
 -        for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
 -            h->last_pocs[i] = INT_MIN;
 -        cnt     = 0;
 -        invalid = MAX_DELAYED_PIC_COUNT;
 -    }
 -    out     = h->delayed_pic[0];
 +    out = h->delayed_pic[0];
      out_idx = 0;
 -    for (i = 1; i < MAX_DELAYED_PIC_COUNT &&
 -                h->delayed_pic[i] &&
 -                !h->delayed_pic[i - 1]->mmco_reset &&
 -                !h->delayed_pic[i]->f.key_frame;
 +    for (i = 1; h->delayed_pic[i] &&
 +                !h->delayed_pic[i]->f.key_frame &&
 +                !h->delayed_pic[i]->mmco_reset;
           i++)
          if (h->delayed_pic[i]->poc < out->poc) {
              out     = h->delayed_pic[i];
              out_idx = i;
          }
      if (h->avctx->has_b_frames == 0 &&
 -        (h->delayed_pic[0]->f.key_frame || h->mmco_reset))
 +        (h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset))
          h->next_outputed_poc = INT_MIN;
 -    out_of_order = !out->f.key_frame && !h->mmco_reset &&
 -                   (out->poc < h->next_outputed_poc);
 +    out_of_order = out->poc < h->next_outputed_poc;
  
 -    if (h->sps.bitstream_restriction_flag &&
 -        h->avctx->has_b_frames >= h->sps.num_reorder_frames) {
 -    } else if (out_of_order && pics - 1 == h->avctx->has_b_frames &&
 -               h->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) {
 -        if (invalid + cnt < MAX_DELAYED_PIC_COUNT) {
 -            h->avctx->has_b_frames = FFMAX(h->avctx->has_b_frames, cnt);
 -        }
 -        h->low_delay = 0;
 -    } else if (h->low_delay &&
 -               ((h->next_outputed_poc != INT_MIN &&
 -                 out->poc > h->next_outputed_poc + 2) ||
 -                cur->f.pict_type == AV_PICTURE_TYPE_B)) {
 -        h->low_delay = 0;
 -        h->avctx->has_b_frames++;
 -    }
 -
 -    if (pics > h->avctx->has_b_frames) {
 +    if (out_of_order || pics > h->avctx->has_b_frames) {
-         out->f.reference &= ~DELAYED_PIC_REF;
+         out->reference &= ~DELAYED_PIC_REF;
          // for frame threading, the owner must be the second field's thread or
          // else the first thread can release the picture and reuse it unsafely
-         out->owner2       = h;
          for (i = out_idx; h->delayed_pic[i]; i++)
              h->delayed_pic[i] = h->delayed_pic[i + 1];
      }
@@@ -2567,14 -2603,8 +2654,15 @@@ static void flush_change(H264Context *h
      h->outputed_poc = h->next_outputed_poc = INT_MIN;
      h->prev_interlaced_frame = 1;
      idr(h);
 -    if (h->cur_pic_ptr)
++
 +    h->prev_frame_num = -1;
 +    if (h->cur_pic_ptr) {
-         h->cur_pic_ptr->f.reference = 0;
+         h->cur_pic_ptr->reference = 0;
 +        for (j=i=0; h->delayed_pic[i]; i++)
 +            if (h->delayed_pic[i] != h->cur_pic_ptr)
 +                h->delayed_pic[j++] = h->delayed_pic[i];
 +        h->delayed_pic[j] = NULL;
 +    }
      h->first_field = 0;
      memset(h->ref_list[0], 0, sizeof(h->ref_list[0]));
      memset(h->ref_list[1], 0, sizeof(h->ref_list[1]));
@@@ -2593,9 -2619,9 +2681,9 @@@ static void flush_dpb(AVCodecContext *a
      H264Context *h = avctx->priv_data;
      int i;
  
 -    for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) {
 +    for (i = 0; i <= MAX_DELAYED_PIC_COUNT; i++) {
          if (h->delayed_pic[i])
-             h->delayed_pic[i]->f.reference = 0;
+             h->delayed_pic[i]->reference = 0;
          h->delayed_pic[i] = NULL;
      }
  
@@@ -3362,14 -3326,8 +3448,14 @@@ static int decode_slice_header(H264Cont
          if (h0->first_field) {
              assert(h0->cur_pic_ptr);
              assert(h0->cur_pic_ptr->f.data[0]);
-             assert(h0->cur_pic_ptr->f.reference != DELAYED_PIC_REF);
+             assert(h0->cur_pic_ptr->reference != DELAYED_PIC_REF);
  
-             if (!last_pic_droppable && h0->cur_pic_ptr->owner2 == h0) {
-                 ff_thread_report_progress(&h0->cur_pic_ptr->f, INT_MAX,
 +            /* Mark old field/frame as completed */
++            if (!last_pic_droppable && h0->cur_pic_ptr->tf.owner == h0->avctx) {
++                ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
 +                                          last_pic_structure == PICT_BOTTOM_FIELD);
 +            }
 +
              /* figure out if we have a complementary field pair */
              if (!FIELD_PICTURE || h->picture_structure == last_pic_structure) {
                  /* Previous field is unmatched. Don't display it, but let it
                  h0->first_field = FIELD_PICTURE;
              } else {
                  if (h0->cur_pic_ptr->frame_num != h->frame_num) {
-                     ff_thread_report_progress((AVFrame*)h0->cur_pic_ptr, INT_MAX,
++                    ff_thread_report_progress(&h0->cur_pic_ptr->tf, INT_MAX,
 +                                              h0->picture_structure==PICT_BOTTOM_FIELD);
                      /* This and the previous field had different frame_nums.
                       * Consider this field first in pair. Throw away previous
                       * one except for reference purposes. */
              ref2frm[18 + 1] = -1;
          for (i = 16; i < 48; i++)
              ref2frm[i + 4] = 4 * id_list[(i - 16) >> 1] +
-                              (h->ref_list[j][i].f.reference & 3);
+                              (h->ref_list[j][i].reference & 3);
      }
  
 +    if (h->ref_count[0]) h->er.last_pic = &h->ref_list[0][0];
 +    if (h->ref_count[1]) h->er.next_pic = &h->ref_list[1][0];
 +
      if (h->avctx->debug & FF_DEBUG_PICT_INFO) {
          av_log(h->avctx, AV_LOG_DEBUG,
                 "slice:%d %s mb:%d %c%s%s pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n",
@@@ -3833,12 -3762,12 +3911,12 @@@ static av_always_inline void fill_filte
          if (USES_LIST(top_type, list)) {
              const int b_xy  = h->mb2b_xy[top_xy] + 3 * b_stride;
              const int b8_xy = 4 * top_xy + 2;
 -            int (*ref2frm)[64] = h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF ? 20 : 2);
 +            int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_table[top_xy] & (MAX_SLICES - 1)][0] + (MB_MBAFF ? 20 : 2));
-             AV_COPY128(mv_dst - 1 * 8, h->cur_pic.f.motion_val[list][b_xy + 0]);
+             AV_COPY128(mv_dst - 1 * 8, h->cur_pic.motion_val[list][b_xy + 0]);
              ref_cache[0 - 1 * 8] =
-             ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.f.ref_index[list][b8_xy + 0]];
+             ref_cache[1 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 0]];
              ref_cache[2 - 1 * 8] =
-             ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.f.ref_index[list][b8_xy + 1]];
+             ref_cache[3 - 1 * 8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 1]];
          } else {
              AV_ZERO128(mv_dst - 1 * 8);
              AV_WN32A(&ref_cache[0 - 1 * 8], ((LIST_NOT_USED) & 0xFF) * 0x01010101u);
              if (USES_LIST(left_type[LTOP], list)) {
                  const int b_xy  = h->mb2b_xy[left_xy[LTOP]] + 3;
                  const int b8_xy = 4 * left_xy[LTOP] + 1;
 -                int (*ref2frm)[64] = h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF ? 20 : 2);
 +                int (*ref2frm)[64] =(void*)( h->ref2frm[h->slice_table[left_xy[LTOP]] & (MAX_SLICES - 1)][0] + (MB_MBAFF ? 20 : 2));
-                 AV_COPY32(mv_dst - 1 +  0, h->cur_pic.f.motion_val[list][b_xy + b_stride * 0]);
-                 AV_COPY32(mv_dst - 1 +  8, h->cur_pic.f.motion_val[list][b_xy + b_stride * 1]);
-                 AV_COPY32(mv_dst - 1 + 16, h->cur_pic.f.motion_val[list][b_xy + b_stride * 2]);
-                 AV_COPY32(mv_dst - 1 + 24, h->cur_pic.f.motion_val[list][b_xy + b_stride * 3]);
+                 AV_COPY32(mv_dst - 1 +  0, h->cur_pic.motion_val[list][b_xy + b_stride * 0]);
+                 AV_COPY32(mv_dst - 1 +  8, h->cur_pic.motion_val[list][b_xy + b_stride * 1]);
+                 AV_COPY32(mv_dst - 1 + 16, h->cur_pic.motion_val[list][b_xy + b_stride * 2]);
+                 AV_COPY32(mv_dst - 1 + 24, h->cur_pic.motion_val[list][b_xy + b_stride * 3]);
                  ref_cache[-1 +  0] =
-                 ref_cache[-1 +  8] = ref2frm[list][h->cur_pic.f.ref_index[list][b8_xy + 2 * 0]];
+                 ref_cache[-1 +  8] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 0]];
                  ref_cache[-1 + 16] =
-                 ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.f.ref_index[list][b8_xy + 2 * 1]];
+                 ref_cache[-1 + 24] = ref2frm[list][h->cur_pic.ref_index[list][b8_xy + 2 * 1]];
              } else {
                  AV_ZERO32(mv_dst - 1 +  0);
                  AV_ZERO32(mv_dst - 1 +  8);
      }
  
      {
-         int8_t *ref = &h->cur_pic.f.ref_index[list][4 * mb_xy];
+         int8_t *ref = &h->cur_pic.ref_index[list][4 * mb_xy];
 -        int (*ref2frm)[64] = h->ref2frm[h->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF ? 20 : 2);
 +        int (*ref2frm)[64] = (void*)(h->ref2frm[h->slice_num & (MAX_SLICES - 1)][0] + (MB_MBAFF ? 20 : 2));
          uint32_t ref01 = (pack16to32(ref2frm[list][ref[0]], ref2frm[list][ref[1]]) & 0x00FF00FF) * 0x0101;
          uint32_t ref23 = (pack16to32(ref2frm[list][ref[2]], ref2frm[list][ref[3]]) & 0x00FF00FF) * 0x0101;
          AV_WN32A(&ref_cache[0 * 8], ref01);
@@@ -4750,8 -4614,7 +4827,9 @@@ static int decode_frame(AVCodecContext 
      H264Context *h     = avctx->priv_data;
      AVFrame *pict      = data;
      int buf_index      = 0;
 +    Picture *out;
 +    int i, out_idx;
+     int ret;
  
      h->flags  = avctx->flags;
  
              h->delayed_pic[i] = h->delayed_pic[i + 1];
  
          if (out) {
-             out->f.reference &= ~DELAYED_PIC_REF;
++            out->reference &= ~DELAYED_PIC_REF;
+             if ((ret = av_frame_ref(pict, &out->f)) < 0)
+                 return ret;
              *got_frame = 1;
-             *pict      = out->f;
          }
  
          return buf_index;
@@@ -4833,11 -4674,13 +4912,12 @@@ not_extra
  
          field_end(h, 0);
  
 -        if (!h->next_output_pic) {
 -            /* Wait for second field. */
 -            *got_frame = 0;
 -        } else {
 +        /* Wait for second field. */
 +        *got_frame = 0;
 +        if (h->next_output_pic && (h->next_output_pic->sync || h->sync>1)) {
+             if ((ret = av_frame_ref(pict, &h->next_output_pic->f)) < 0)
+                 return ret;
              *got_frame = 1;
-             *pict      = h->next_output_pic->f;
          }
      }
  
@@@ -4869,12 -4707,11 +4949,12 @@@ static av_cold int h264_decode_end(AVCo
      H264Context *h    = avctx->priv_data;
      int i;
  
 +    ff_h264_remove_all_refs(h);
      ff_h264_free_context(h);
  
-     if (h->DPB && !h->avctx->internal->is_copy) {
-         for (i = 0; i < h->picture_count; i++) {
-             free_picture(h, &h->DPB[i]);
+     if (h->DPB) {
+         for (i = 0; i < MAX_PICTURE_COUNT; i++) {
+             unref_picture(h, &h->DPB[i]);
          }
      }
      av_freep(&h->DPB);
@@@ -647,10 -620,13 +645,15 @@@ typedef struct H264Context 
      uint8_t *edge_emu_buffer;
      int16_t *dc_val_base;
  
 +    uint8_t *visualization_buffer[3]; ///< temporary buffer vor MV visualization
++
+     AVBufferPool *qscale_table_pool;
+     AVBufferPool *mb_type_pool;
+     AVBufferPool *motion_val_pool;
+     AVBufferPool *ref_index_pool;
  } H264Context;
  
 -extern const uint8_t ff_h264_chroma_qp[3][QP_MAX_NUM + 1]; ///< One chroma qp table for each supported bit depth (8, 9, 10).
 +extern const uint8_t ff_h264_chroma_qp[7][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-14).
  extern const uint16_t ff_h264_mb_sizes[4];
  
  /**
Simple merge
Simple merge
@@@ -288,10 -288,10 +288,10 @@@ single_col
  
      await_reference_mb_row(h, &h->ref_list[1][0], mb_y);
  
-     l1mv0  = (void*)&h->ref_list[1][0].f.motion_val[0][h->mb2b_xy [mb_xy]];
-     l1mv1  = (void*)&h->ref_list[1][0].f.motion_val[1][h->mb2b_xy [mb_xy]];
-     l1ref0 = &h->ref_list[1][0].f.ref_index [0][4 * mb_xy];
-     l1ref1 = &h->ref_list[1][0].f.ref_index [1][4 * mb_xy];
 -    l1mv0  = &h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]];
 -    l1mv1  = &h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]];
++    l1mv0  = (void*)&h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]];
++    l1mv1  = (void*)&h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]];
+     l1ref0 = &h->ref_list[1][0].ref_index [0][4 * mb_xy];
+     l1ref1 = &h->ref_list[1][0].ref_index [1][4 * mb_xy];
      if(!b8_stride){
          if(h->mb_y&1){
              l1ref0 += 2;
@@@ -478,10 -478,10 +478,10 @@@ single_col
  
      await_reference_mb_row(h, &h->ref_list[1][0], mb_y);
  
-     l1mv0  = (void*)&h->ref_list[1][0].f.motion_val[0][h->mb2b_xy [mb_xy]];
-     l1mv1  = (void*)&h->ref_list[1][0].f.motion_val[1][h->mb2b_xy [mb_xy]];
-     l1ref0 = &h->ref_list[1][0].f.ref_index [0][4 * mb_xy];
-     l1ref1 = &h->ref_list[1][0].f.ref_index [1][4 * mb_xy];
 -    l1mv0  = &h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]];
 -    l1mv1  = &h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]];
++    l1mv0  = (void*)&h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]];
++    l1mv1  = (void*)&h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]];
+     l1ref0 = &h->ref_list[1][0].ref_index [0][4 * mb_xy];
+     l1ref1 = &h->ref_list[1][0].ref_index [1][4 * mb_xy];
      if(!b8_stride){
          if(h->mb_y&1){
              l1ref0 += 2;
@@@ -577,12 -580,10 +577,12 @@@ static av_always_inline void filter_mb_
              // Do not use s->qscale as luma quantizer because it has not the same
              // value in IPCM macroblocks.
              if(bS[0]+bS[1]+bS[2]+bS[3]){
-                 qp = (h->cur_pic.f.qscale_table[mb_xy] + h->cur_pic.f.qscale_table[mbm_xy] + 1) >> 1;
+                 qp = (h->cur_pic.qscale_table[mb_xy] + h->cur_pic.qscale_table[mbm_xy] + 1) >> 1;
 +                //tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], h->cur_pic.qscale_table[mbn_xy]);
                  tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);
-                 chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, h->cur_pic.f.qscale_table[mbm_xy]) + 1) >> 1;
-                 chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, h->cur_pic.f.qscale_table[mbm_xy]) + 1) >> 1;
 +                //{ int i; for (i = 0; i < 4; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); }
+                 chroma_qp_avg[0] = (h->chroma_qp[0] + get_chroma_qp(h, 0, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1;
+                 chroma_qp_avg[1] = (h->chroma_qp[1] + get_chroma_qp(h, 1, h->cur_pic.qscale_table[mbm_xy]) + 1) >> 1;
                  if( dir == 0 ) {
                      filter_mb_edgev( &img_y[0], linesize, bS, qp, a, b, h, 1 );
                      if (chroma) {
          /* Filter edge */
          // Do not use s->qscale as luma quantizer because it has not the same
          // value in IPCM macroblocks.
-         qp = h->cur_pic.f.qscale_table[mb_xy];
+         qp = h->cur_pic.qscale_table[mb_xy];
 +        //tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp[0], h->cur_pic.qscale_table[mbn_xy]);
          tprintf(h->avctx, "filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);
 +        //{ int i; for (i = 0; i < 4; i++) tprintf(h->avctx, " bS[%d]:%d", i, bS[i]); tprintf(h->avctx, "\n"); }
          if( dir == 0 ) {
              filter_mb_edgev( &img_y[4*edge << h->pixel_shift], linesize, bS, qp, a, b, h, 0 );
              if (chroma) {
Simple merge
@@@ -68,9 -68,9 +68,9 @@@ static void MCFUNC(hl_motion)(H264Conte
                                h264_biweight_func *weight_avg)
  {
      const int mb_xy   = h->mb_xy;
-     const int mb_type = h->cur_pic.f.mb_type[mb_xy];
+     const int mb_type = h->cur_pic.mb_type[mb_xy];
  
 -    assert(IS_INTER(mb_type));
 +    av_assert2(IS_INTER(mb_type));
  
      if (HAVE_THREADS && (h->avctx->active_thread_type & FF_THREAD_FRAME))
          await_references(h);
@@@ -479,9 -480,9 +479,9 @@@ static void fill_decode_caches(H264Cont
                          h->left_samples_available    &= 0xFF5F;
                      }
                  } else {
-                     int left_typei = h->cur_pic.f.mb_type[left_xy[LTOP] + h->mb_stride];
+                     int left_typei = h->cur_pic.mb_type[left_xy[LTOP] + h->mb_stride];
  
 -                    assert(left_xy[LTOP] == left_xy[LBOT]);
 +                    av_assert2(left_xy[LTOP] == left_xy[LBOT]);
                      if (!((left_typei & type_mask) && (left_type[LTOP] & type_mask))) {
                          h->topleft_samples_available &= 0xDF5F;
                          h->left_samples_available    &= 0x5F5F;
          int b_stride = h->b_stride;
          for (list = 0; list < h->list_count; list++) {
              int8_t *ref_cache = &h->ref_cache[list][scan8[0]];
-             int8_t *ref       = h->cur_pic.f.ref_index[list];
+             int8_t *ref       = h->cur_pic.ref_index[list];
              int16_t(*mv_cache)[2] = &h->mv_cache[list][scan8[0]];
-             int16_t(*mv)[2]       = h->cur_pic.f.motion_val[list];
+             int16_t(*mv)[2]       = h->cur_pic.motion_val[list];
              if (!USES_LIST(mb_type, list))
                  continue;
 -            assert(!(IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred));
 +            av_assert2(!(IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred));
  
              if (USES_LIST(top_type, list)) {
                  const int b_xy = h->mb2b_xy[top_xy] + 3 * b_stride;
@@@ -282,12 -293,9 +294,12 @@@ int ff_h264_decode_ref_pic_list_reorder
      for(list=0; list<h->list_count; list++){
          for(index= 0; index < h->ref_count[list]; index++){
              if (!h->ref_list[list][index].f.data[0]) {
 -                av_log(h->avctx, AV_LOG_ERROR, "Missing reference picture\n");
 +                int i;
 +                av_log(h->avctx, AV_LOG_ERROR, "Missing reference picture, default is %d\n", h->default_ref_list[list][0].poc);
 +                for (i=0; i<FF_ARRAY_ELEMS(h->last_pocs); i++)
 +                    h->last_pocs[i] = INT_MIN;
                  if (h->default_ref_list[list][0].f.data[0])
-                     h->ref_list[list][index]= h->default_ref_list[list][0];
+                     COPY_PICTURE(&h->ref_list[list][index], &h->default_ref_list[list][0]);
                  else
                      return -1;
              }
@@@ -496,9 -498,11 +508,9 @@@ int ff_generate_sliding_window_mmcos(H2
      MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp;
      int mmco_index = 0, i;
  
 -    assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count);
 -
      if (h->short_ref_count &&
 -        h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count &&
 +        h->long_ref_count + h->short_ref_count >= h->sps.ref_frame_count &&
-         !(FIELD_PICTURE && !h->first_field && h->cur_pic_ptr->f.reference)) {
+         !(FIELD_PICTURE && !h->first_field && h->cur_pic_ptr->reference)) {
          mmco[0].opcode = MMCO_SHORT2UNUSED;
          mmco[0].short_pic_num = h->short_ref[h->short_ref_count - 1]->frame_num;
          mmco_index = 1;
@@@ -256,8 -241,6 +256,7 @@@ static av_cold int decode_init(AVCodecC
      ff_huffyuv_common_init(avctx);
      memset(s->vlc, 0, 3 * sizeof(VLC));
  
-     avctx->coded_frame = &s->picture;
 +    avcodec_get_frame_defaults(&s->picture);
      s->interlaced = s->height > 288;
  
      s->bgr32 = 1;
@@@ -364,11 -336,7 +363,10 @@@ static av_cold int decode_init_thread_c
      HYuvContext *s = avctx->priv_data;
      int i;
  
-     avctx->coded_frame= &s->picture;
 -    ff_huffyuv_alloc_temp(s);
 +    if (ff_huffyuv_alloc_temp(s)) {
 +        ff_huffyuv_common_end(s);
 +        return AVERROR(ENOMEM);
 +    }
  
      for (i = 0; i < 6; i++)
          s->vlc[i].table = NULL;
@@@ -512,27 -480,23 +510,22 @@@ static int decode_frame(AVCodecContext 
      const int width2 = s->width>>1;
      const int height = s->height;
      int fake_ystride, fake_ustride, fake_vstride;
-     AVFrame * const p = &s->picture;
+     ThreadFrame frame = { .f = data };
+     AVFrame * const p = data;
 -    int table_size = 0;
 +    int table_size = 0, ret;
  
-     AVFrame *picture = data;
 -    av_fast_malloc(&s->bitstream_buffer,
 +    av_fast_padded_malloc(&s->bitstream_buffer,
                     &s->bitstream_buffer_size,
 -                   buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
 +                   buf_size);
      if (!s->bitstream_buffer)
          return AVERROR(ENOMEM);
  
      s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer,
                       (const uint32_t*)buf, buf_size / 4);
  
-     if (p->data[0])
-         ff_thread_release_buffer(avctx, p);
-     p->reference = 0;
-     if ((ret = ff_thread_get_buffer(avctx, p)) < 0) {
 -    if (ff_thread_get_buffer(avctx, &frame, 0) < 0) {
++    if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -        return -1;
 +        return ret;
      }
  
      if (s->context) {
@@@ -171,9 -170,7 +170,7 @@@ static av_cold int idcin_decode_init(AV
      return 0;
  }
  
- static int idcin_decode_vlcs(IdcinContext *s)
 -static void idcin_decode_vlcs(IdcinContext *s, AVFrame *frame)
++static int idcin_decode_vlcs(IdcinContext *s, AVFrame *frame)
  {
      hnode *hnodes;
      long x, y;
@@@ -224,19 -220,15 +222,16 @@@ static int idcin_decode_frame(AVCodecCo
      s->buf = buf;
      s->size = buf_size;
  
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
-     if ((ret = ff_get_buffer(avctx, &s->frame))) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "  id CIN Video: get_buffer() failed\n");
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
  
-     if (idcin_decode_vlcs(s))
 -    idcin_decode_vlcs(s, frame);
++    if (idcin_decode_vlcs(s, frame))
 +        return AVERROR_INVALIDDATA;
  
      if (pal) {
-         s->frame.palette_has_changed = 1;
+         frame->palette_has_changed = 1;
          memcpy(s->pal, pal, AVPALETTE_SIZE);
      }
      /* make the palette available on the way out */
  #include "get_bits.h"
  #include "internal.h"
  
 +// TODO: masking bits
 +typedef enum {
 +    MASK_NONE,
 +    MASK_HAS_MASK,
 +    MASK_HAS_TRANSPARENT_COLOR,
 +    MASK_LASSO
 +} mask_type;
 +
  typedef struct {
--    AVFrame frame;
++    AVFrame *frame;
      int planesize;
      uint8_t * planebuf;
 +    uint8_t * ham_buf;      ///< temporary buffer for planar to chunky conversation
 +    uint32_t *ham_palbuf;   ///< HAM decode table
 +    uint32_t *mask_buf;     ///< temporary buffer for palette indices
 +    uint32_t *mask_palbuf;  ///< masking palette table
 +    unsigned  compression;  ///< delta compression method used
 +    unsigned  bpp;          ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
 +    unsigned  ham;          ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
 +    unsigned  flags;        ///< 1 for EHB, 0 is no extra half darkening
 +    unsigned  transparency; ///< TODO: transparency color index in palette
 +    unsigned  masking;      ///< TODO: masking method used
      int init; // 1 if buffer and palette data already initialized, 0 otherwise
 +    int16_t   tvdc[16];     ///< TVDC lookup table
  } IffContext;
  
  #define LUT8_PART(plane, v)                             \
@@@ -360,13 -168,6 +360,14 @@@ static av_cold int decode_init(AVCodecC
      if (!s->planebuf)
          return AVERROR(ENOMEM);
  
-     avcodec_get_frame_defaults(&s->frame);
 +    s->bpp = avctx->bits_per_coded_sample;
-     s->frame.reference = 3;
++    s->frame = av_frame_alloc();
++    if (!s->frame)
++        return AVERROR(ENOMEM);
 +
 +    if ((err = extract_header(avctx, NULL)) < 0)
 +        return err;
 +
      return 0;
  }
  
@@@ -654,218 -305,61 +655,218 @@@ static int decode_frame(AVCodecContext 
                              AVPacket *avpkt)
  {
      IffContext *s = avctx->priv_data;
 -    const uint8_t *buf = avpkt->data;
 -    int buf_size = avpkt->size;
 +    const uint8_t *buf = avpkt->size >= 2 ? avpkt->data + AV_RB16(avpkt->data) : NULL;
 +    const int buf_size = avpkt->size >= 2 ? avpkt->size - AV_RB16(avpkt->data) : 0;
      const uint8_t *buf_end = buf+buf_size;
      int y, plane, res;
 +    GetByteContext gb;
  
 -    if ((res = ff_reget_buffer(avctx, &s->frame)) < 0)
 +    if ((res = extract_header(avctx, avpkt)) < 0)
          return res;
-     if (s->init) {
-         if ((res = avctx->reget_buffer(avctx, &s->frame)) < 0) {
-             av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
-             return res;
-         }
-     } else if ((res = ff_get_buffer(avctx, &s->frame)) < 0) {
-         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -
++    if ((res = ff_reget_buffer(avctx, s->frame)) < 0) {
++        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 +        return res;
-     } else if (avctx->bits_per_coded_sample <= 8 && avctx->pix_fmt == AV_PIX_FMT_PAL8) {
-         if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
++    }
+     if (!s->init && avctx->bits_per_coded_sample <= 8 &&
 -        avctx->pix_fmt != AV_PIX_FMT_GRAY8) {
 -        if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame.data[1])) < 0)
++        avctx->pix_fmt == AV_PIX_FMT_PAL8) {
++        if ((res = cmap_read_palette(avctx, (uint32_t*)s->frame->data[1])) < 0)
 +            return res;
-     } else if (avctx->pix_fmt == AV_PIX_FMT_RGB32 && avctx->bits_per_coded_sample <= 8) {
++    } else if (!s->init && avctx->bits_per_coded_sample <= 8 &&
++               avctx->pix_fmt == AV_PIX_FMT_RGB32) {
 +        if ((res = cmap_read_palette(avctx, s->mask_palbuf)) < 0)
              return res;
      }
      s->init = 1;
  
 -    if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
 -        if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
 -            for(y = 0; y < avctx->height ; y++ ) {
 -                uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
 -                memset(row, 0, avctx->width);
 -                for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
 -                    buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
 -                    decodeplane8(row, s->planebuf, s->planesize, plane);
 +    switch (s->compression) {
 +    case 0:
 +        if (avctx->codec_tag == MKTAG('A','C','B','M')) {
 +            if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
-                 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
++                memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]);
 +                for (plane = 0; plane < s->bpp; plane++) {
 +                    for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
-                         uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
++                        uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
 +                        decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
 +                        buf += s->planesize;
 +                    }
 +                }
 +            } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
-                 memset(s->frame.data[0], 0, avctx->height * s->frame.linesize[0]);
++                memset(s->frame->data[0], 0, avctx->height * s->frame->linesize[0]);
 +                for(y = 0; y < avctx->height; y++) {
-                     uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
 +                    memset(s->ham_buf, 0, s->planesize * 8);
 +                    for (plane = 0; plane < s->bpp; plane++) {
 +                        const uint8_t * start = buf + (plane * avctx->height + y) * s->planesize;
 +                        if (start >= buf_end)
 +                            break;
 +                        decodeplane8(s->ham_buf, start, FFMIN(s->planesize, buf_end - start), plane);
 +                    }
 +                    decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
 +                }
 +            } else
 +                return unsupported(avctx);
 +        } else if (avctx->codec_tag == MKTAG('D','E','E','P')) {
 +            const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
 +            int raw_width = avctx->width * (av_get_bits_per_pixel(desc) >> 3);
 +            int x;
 +            for(y = 0; y < avctx->height && buf < buf_end; y++ ) {
-                 uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
++                uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
 +                memcpy(row, buf, FFMIN(raw_width, buf_end - buf));
 +                buf += raw_width;
 +                if (avctx->pix_fmt == AV_PIX_FMT_BGR32) {
 +                    for(x = 0; x < avctx->width; x++)
 +                        row[4 * x + 3] = row[4 * x + 3] & 0xF0 | (row[4 * x + 3] >> 4);
                  }
              }
 -        } else { //AV_PIX_FMT_BGR32
 -            for(y = 0; y < avctx->height ; y++ ) {
 -                uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
 -                memset(row, 0, avctx->width << 2);
 -                for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
 -                    buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
 -                    decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
 +        } else if (avctx->codec_tag == MKTAG('I','L','B','M')) { // interleaved
 +            if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
 +                for(y = 0; y < avctx->height; y++ ) {
-                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
++                    uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
 +                    memset(row, 0, avctx->width);
 +                    for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
 +                        decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
 +                        buf += s->planesize;
 +                    }
 +                }
 +            } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
 +                for (y = 0; y < avctx->height; y++) {
-                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
++                    uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
 +                    memset(s->ham_buf, 0, s->planesize * 8);
 +                    for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
 +                        decodeplane8(s->ham_buf, buf, FFMIN(s->planesize, buf_end - buf), plane);
 +                        buf += s->planesize;
 +                    }
 +                    decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
 +                }
 +            } else { // AV_PIX_FMT_BGR32
 +                for(y = 0; y < avctx->height; y++ ) {
-                     uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
 +                    memset(row, 0, avctx->width << 2);
 +                    for (plane = 0; plane < s->bpp && buf < buf_end; plane++) {
 +                        decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
 +                        buf += s->planesize;
 +                    }
                  }
              }
-                     uint8_t *row = &s->frame.data[0][y * s->frame.linesize[0]];
 +        } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
 +            if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
 +                for(y = 0; y < avctx->height && buf_end > buf; y++ ) {
-                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
++                    uint8_t *row = &s->frame->data[0][y * s->frame->linesize[0]];
 +                    memcpy(row, buf, FFMIN(avctx->width, buf_end - buf));
 +                    buf += avctx->width + (avctx->width % 2); // padding if odd
 +                }
 +            } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
 +                for (y = 0; y < avctx->height && buf_end > buf; y++) {
++                    uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
 +                    memcpy(s->ham_buf, buf, FFMIN(avctx->width, buf_end - buf));
 +                    buf += avctx->width + (avctx->width & 1); // padding if odd
 +                    decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
 +                }
 +            } else
 +                return unsupported(avctx);
          }
 -    } else {
 -        for(y = 0; y < avctx->height ; y++ ) {
 -            uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
 -            buf += decode_byterun(row, avctx->width, buf, buf_end);
 +        break;
 +    case 1:
 +        if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
 +            if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
 +                for(y = 0; y < avctx->height ; y++ ) {
-                     uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
++                    uint8_t *row = &s->frame->data[0][ y*s->frame->linesize[0] ];
 +                    memset(row, 0, avctx->width);
 +                    for (plane = 0; plane < s->bpp; plane++) {
 +                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
 +                        decodeplane8(row, s->planebuf, s->planesize, plane);
 +                    }
 +                }
 +            } else if (avctx->bits_per_coded_sample <= 8) { //8-bit (+ mask) to AV_PIX_FMT_BGR32
 +                for (y = 0; y < avctx->height ; y++ ) {
-                     uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
 +                    memset(s->mask_buf, 0, avctx->width * sizeof(uint32_t));
 +                    for (plane = 0; plane < s->bpp; plane++) {
 +                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
 +                        decodeplane32(s->mask_buf, s->planebuf, s->planesize, plane);
 +                    }
 +                    lookup_pal_indicies((uint32_t *) row, s->mask_buf, s->mask_palbuf, avctx->width);
 +                }
 +            } else if (s->ham) { // HAM to AV_PIX_FMT_BGR32
 +                for (y = 0; y < avctx->height ; y++) {
-                     uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
 +                    memset(s->ham_buf, 0, s->planesize * 8);
 +                    for (plane = 0; plane < s->bpp; plane++) {
 +                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
 +                        decodeplane8(s->ham_buf, s->planebuf, s->planesize, plane);
 +                    }
 +                    decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
 +                }
 +            } else { //AV_PIX_FMT_BGR32
 +                for(y = 0; y < avctx->height ; y++ ) {
-                     uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
 +                    memset(row, 0, avctx->width << 2);
 +                    for (plane = 0; plane < s->bpp; plane++) {
 +                        buf += decode_byterun(s->planebuf, s->planesize, buf, buf_end);
 +                        decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
 +                    }
 +                }
 +            }
 +        } else if (avctx->codec_tag == MKTAG('P','B','M',' ')) { // IFF-PBM
 +            if (avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8) {
 +                for(y = 0; y < avctx->height ; y++ ) {
-                     uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
 +                    buf += decode_byterun(row, avctx->width, buf, buf_end);
 +                }
 +            } else if (s->ham) { // IFF-PBM: HAM to AV_PIX_FMT_BGR32
 +                for (y = 0; y < avctx->height ; y++) {
-                     uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
++                    uint8_t *row = &s->frame->data[0][y*s->frame->linesize[0]];
 +                    buf += decode_byterun(s->ham_buf, avctx->width, buf, buf_end);
 +                    decode_ham_plane32((uint32_t *) row, s->ham_buf, s->ham_palbuf, s->planesize);
 +                }
 +            } else
 +                return unsupported(avctx);
 +        } else if (avctx->codec_tag == MKTAG('D','E','E','P')) { // IFF-DEEP
 +            const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
 +            if (av_get_bits_per_pixel(desc) == 32)
-                 decode_deep_rle32(s->frame.data[0], buf, buf_size, avctx->width, avctx->height, s->frame.linesize[0]);
++                decode_deep_rle32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0]);
 +            else
 +                return unsupported(avctx);
          }
-             decode_rgb8(&gb, s->frame.data[0], avctx->width, avctx->height, s->frame.linesize[0]);
 +        break;
 +    case 4:
 +        bytestream2_init(&gb, buf, buf_size);
 +        if (avctx->codec_tag == MKTAG('R','G','B','8'))
-             decode_rgbn(&gb, s->frame.data[0], avctx->width, avctx->height, s->frame.linesize[0]);
++            decode_rgb8(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
 +        else if (avctx->codec_tag == MKTAG('R','G','B','N'))
-                 decode_deep_tvdc32(s->frame.data[0], buf, buf_size, avctx->width, avctx->height, s->frame.linesize[0], s->tvdc);
++            decode_rgbn(&gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
 +        else
 +            return unsupported(avctx);
 +        break;
 +    case 5:
 +        if (avctx->codec_tag == MKTAG('D','E','E','P')) {
 +            const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
 +            if (av_get_bits_per_pixel(desc) == 32)
++                decode_deep_tvdc32(s->frame->data[0], buf, buf_size, avctx->width, avctx->height, s->frame->linesize[0], s->tvdc);
 +            else
 +                return unsupported(avctx);
 +        } else
 +            return unsupported(avctx);
 +        break;
 +    default:
 +        return unsupported(avctx);
      }
  
 -    if ((res = av_frame_ref(data, &s->frame)) < 0)
++    if ((res = av_frame_ref(data, s->frame)) < 0)
+         return res;
      *got_frame = 1;
-     *(AVFrame*)data = s->frame;
      return buf_size;
  }
  
  static av_cold int decode_end(AVCodecContext *avctx)
  {
      IffContext *s = avctx->priv_data;
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
 -    av_frame_unref(&s->frame);
++    av_frame_free(&s->frame);
      av_freep(&s->planebuf);
 +    av_freep(&s->ham_buf);
 +    av_freep(&s->ham_palbuf);
      return 0;
  }
  
Simple merge
Simple merge
@@@ -1047,8 -1013,9 +1046,7 @@@ static av_cold int decode_init(AVCodecC
      Indeo3DecodeContext *ctx = avctx->priv_data;
  
      ctx->avctx     = avctx;
 -    ctx->width     = avctx->width;
 -    ctx->height    = avctx->height;
      avctx->pix_fmt = AV_PIX_FMT_YUV410P;
-     avcodec_get_frame_defaults(&ctx->frame);
  
      build_requant_tab();
  
@@@ -1089,15 -1059,6 +1088,11 @@@ static int decode_frame(AVCodecContext 
      /* use BS_BUFFER flag for buffer switching */
      ctx->buf_sel = (ctx->frame_flags >> BS_BUFFER) & 1;
  
-     if (ctx->frame.data[0])
-         avctx->release_buffer(avctx, &ctx->frame);
-     ctx->frame.reference = 0;
-     if ((res = ff_get_buffer(avctx, &ctx->frame)) < 0) {
++    if ((res = ff_get_buffer(avctx, frame, 0)) < 0) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return res;
 +    }
 +
      /* decode luma plane */
      if ((res = decode_plane(ctx, avctx, ctx->planes, ctx->y_data_ptr, ctx->y_data_size, 40)))
          return res;
      if ((res = decode_plane(ctx, avctx, &ctx->planes[2], ctx->v_data_ptr, ctx->v_data_size, 10)))
          return res;
  
 -    if ((res = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -        return res;
 -    }
 -
      output_plane(&ctx->planes[0], ctx->buf_sel,
-                  ctx->frame.data[0], ctx->frame.linesize[0],
+                  frame->data[0], frame->linesize[0],
                   avctx->height);
      output_plane(&ctx->planes[1], ctx->buf_sel,
-                  ctx->frame.data[1], ctx->frame.linesize[1],
+                  frame->data[1], frame->linesize[1],
                   (avctx->height + 3) >> 2);
      output_plane(&ctx->planes[2], ctx->buf_sel,
-                  ctx->frame.data[2], ctx->frame.linesize[2],
+                  frame->data[2], frame->linesize[2],
                   (avctx->height + 3) >> 2);
  
      *got_frame = 1;
Simple merge
@@@ -76,24 -90,9 +90,22 @@@ typedef struct AVCodecInternal 
       */
      int last_audio_frame;
  
-     /**
-      * The data for the last allocated audio frame.
-      * Stored here so we can free it.
-      */
-     uint8_t *audio_data;
+     AVFrame to_free;
+     FramePool *pool;
 +
 +    /**
 +     * temporary buffer used for encoders to store their bitstream
 +     */
 +    uint8_t *byte_buffer;
 +    unsigned int byte_buffer_size;
 +
 +    void *frame_thread_encoder;
 +
 +    /**
 +     * Number of audio samples to skip at the start of the next decoded frame
 +     */
 +    int skip_samples;
  } AVCodecInternal;
  
  struct AVCodecDefault {
@@@ -184,33 -161,12 +196,35 @@@ static av_always_inline int64_t ff_samp
   * AVCodecContext.get_buffer() and should be used instead calling get_buffer()
   * directly.
   */
- int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame);
+ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags);
+ /**
+  * Identical in function to av_frame_make_writable(), except it uses
+  * ff_get_buffer() to allocate the buffer when needed.
+  */
+ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame);
  
- void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table,
-                          uint8_t *visualization_buffer[3], int *low_delay,
-                          int mb_width, int mb_height, int mb_stride, int quarter_sample);
 +int ff_thread_can_start_frame(AVCodecContext *avctx);
 +
 +int ff_get_logical_cpus(AVCodecContext *avctx);
 +
 +int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx);
 +
 +/**
 + * Call avcodec_open2 recursively by decrementing counter, unlocking mutex,
 + * calling the function and then restoring again. Assumes the mutex is
 + * already locked
 + */
 +int ff_codec_open2_recursive(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
 +
 +/**
 + * Call avcodec_close recursively, counterpart to avcodec_open2_recursive.
 + */
 +int ff_codec_close_recursive(AVCodecContext *avctx);
 +
 +/**
 + * Finalize buf into extradata and set its size appropriately.
 + */
 +int avpriv_bprint_to_extradata(AVCodecContext *avctx, struct AVBPrint *buf);
 +
  #endif /* AVCODEC_INTERNAL_H */
@@@ -67,16 -66,16 +66,16 @@@ typedef struct IpvideoContext 
      uint32_t pal[256];
  } IpvideoContext;
  
- static int copy_from(IpvideoContext *s, AVFrame *src, int delta_x, int delta_y)
+ static int copy_from(IpvideoContext *s, AVFrame *src, AVFrame *dst, int delta_x, int delta_y)
  {
-     int current_offset = s->pixel_ptr - s->current_frame.data[0];
-     int motion_offset = current_offset + delta_y * s->current_frame.linesize[0]
+     int current_offset = s->pixel_ptr - dst->data[0];
+     int motion_offset = current_offset + delta_y * dst->linesize[0]
                         + delta_x * (1 + s->is_16bpp);
      if (motion_offset < 0) {
 -        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset < 0 (%d)\n", motion_offset);
 +        av_log(s->avctx, AV_LOG_ERROR, "motion offset < 0 (%d)\n", motion_offset);
          return AVERROR_INVALIDDATA;
      } else if (motion_offset > s->upper_motion_limit_offset) {
 -        av_log(s->avctx, AV_LOG_ERROR, " Interplay video: motion offset above limit (%d >= %d)\n",
 +        av_log(s->avctx, AV_LOG_ERROR, "motion offset above limit (%d >= %d)\n",
              motion_offset, s->upper_motion_limit_offset);
          return AVERROR_INVALIDDATA;
      }
@@@ -119,11 -118,11 +118,11 @@@ static int ipvideo_decode_block_opcode_
          y =   8 + ((B - 56) / 29);
      }
  
 -    av_dlog(NULL, "    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
 +    av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
-     return copy_from(s, &s->second_last_frame, x, y);
+     return copy_from(s, s->second_last_frame, frame, x, y);
  }
  
- static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s)
+ static int ipvideo_decode_block_opcode_0x3(IpvideoContext *s, AVFrame *frame)
  {
      unsigned char B;
      int x, y;
          y = -(  8 + ((B - 56) / 29));
      }
  
 -    av_dlog(NULL, "    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
 +    av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
-     return copy_from(s, &s->current_frame, x, y);
+     return copy_from(s, frame, frame, x, y);
  }
  
- static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s)
+ static int ipvideo_decode_block_opcode_0x4(IpvideoContext *s, AVFrame *frame)
  {
      int x, y;
      unsigned char B, BL, BH;
      x = -8 + BL;
      y = -8 + BH;
  
 -    av_dlog(NULL, "    motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
 +    av_dlog(s->avctx, "motion byte = %d, (x, y) = (%d, %d)\n", B, x, y);
-     return copy_from(s, &s->last_frame, x, y);
+     return copy_from(s, s->last_frame, frame, x, y);
  }
  
- static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s)
+ static int ipvideo_decode_block_opcode_0x5(IpvideoContext *s, AVFrame *frame)
  {
      signed char x, y;
  
      x = bytestream2_get_byte(&s->stream_ptr);
      y = bytestream2_get_byte(&s->stream_ptr);
  
 -    av_dlog(NULL, "    motion bytes = %d, %d\n", x, y);
 +    av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y);
-     return copy_from(s, &s->last_frame, x, y);
+     return copy_from(s, s->last_frame, frame, x, y);
  }
  
- static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s)
+ static int ipvideo_decode_block_opcode_0x6(IpvideoContext *s, AVFrame *frame)
  {
      /* mystery opcode? skip multiple blocks? */
 -    av_log(s->avctx, AV_LOG_ERROR, "  Interplay video: Help! Mystery opcode 0x6 seen\n");
 +    av_log(s->avctx, AV_LOG_ERROR, "Help! Mystery opcode 0x6 seen\n");
  
      /* report success */
      return 0;
@@@ -529,11 -528,11 +528,11 @@@ static int ipvideo_decode_block_opcode_
      x = bytestream2_get_byte(&s->stream_ptr);
      y = bytestream2_get_byte(&s->stream_ptr);
  
 -    av_dlog(NULL, "    motion bytes = %d, %d\n", x, y);
 +    av_dlog(s->avctx, "motion bytes = %d, %d\n", x, y);
-     return copy_from(s, &s->second_last_frame, x, y);
+     return copy_from(s, s->second_last_frame, frame, x, y);
  }
  
- static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s)
+ static int ipvideo_decode_block_opcode_0x7_16(IpvideoContext *s, AVFrame *frame)
  {
      int x, y;
      uint16_t P[2];
@@@ -909,16 -908,16 +908,16 @@@ static void ipvideo_decode_opcodes(Ipvi
                      x, y, opcode, bytestream2_tell(&s->stream_ptr));
  
              if (!s->is_16bpp) {
-                 s->pixel_ptr = s->current_frame.data[0] + x
-                               + y*s->current_frame.linesize[0];
-                 ret = ipvideo_decode_block[opcode](s);
+                 s->pixel_ptr = frame->data[0] + x
+                               + y*frame->linesize[0];
+                 ret = ipvideo_decode_block[opcode](s, frame);
              } else {
-                 s->pixel_ptr = s->current_frame.data[0] + x*2
-                               + y*s->current_frame.linesize[0];
-                 ret = ipvideo_decode_block16[opcode](s);
+                 s->pixel_ptr = frame->data[0] + x*2
+                               + y*frame->linesize[0];
+                 ret = ipvideo_decode_block16[opcode](s, frame);
              }
              if (ret != 0) {
 -                av_log(s->avctx, AV_LOG_ERROR, " Interplay video: decode problem on frame %d, @ block (%d, %d)\n",
 +                av_log(s->avctx, AV_LOG_ERROR, "decode problem on frame %d, @ block (%d, %d)\n",
                         s->avctx->frame_number, x, y);
                  return;
              }
@@@ -969,20 -970,12 +970,17 @@@ static int ipvideo_decode_frame(AVCodec
      if (buf_size < s->decoding_map_size)
          return buf_size;
  
-     if (s->last_frame.data[0] && av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
-         if (s->last_frame.data[0])
-             avctx->release_buffer(avctx, &s->last_frame);
-         if (s->second_last_frame.data[0])
-             avctx->release_buffer(avctx, &s->second_last_frame);
++    if (av_packet_get_side_data(avpkt, AV_PKT_DATA_PARAM_CHANGE, NULL)) {
++        av_frame_unref(s->last_frame);
++        av_frame_unref(s->second_last_frame);
 +    }
 +
      s->decoding_map = buf;
      bytestream2_init(&s->stream_ptr, buf + s->decoding_map_size,
                       buf_size - s->decoding_map_size);
  
-     s->current_frame.reference = 3;
-     if ((ret = ff_get_buffer(avctx, &s->current_frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "  Interplay Video: get_buffer() failed\n");
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
  
Simple merge
Simple merge
Simple merge
@@@ -900,15 -862,8 +901,11 @@@ int ff_ivi_decode_frame(AVCodecContext 
              av_log(avctx, AV_LOG_ERROR, "Buffer contains IP frames!\n");
      }
  
-     if (ctx->frame.data[0])
-         avctx->release_buffer(avctx, &ctx->frame);
-     ctx->frame.reference = 0;
 +    if (!ctx->is_nonnull_frame(ctx))
 +        return buf_size;
 +
      avcodec_set_dimensions(avctx, ctx->planes[0].width, ctx->planes[0].height);
-     if ((result = ff_get_buffer(avctx, &ctx->frame)) < 0) {
+     if ((result = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return result;
      }
Simple merge
index 53c4f07,0000000..fef0348
mode 100644,000000..100644
--- /dev/null
@@@ -1,1107 -1,0 +1,1101 @@@
-     AVFrame picture;
 +/*
 + * JPEG2000 image decoder
 + * Copyright (c) 2007 Kamil Nowosad
 + *
 + * 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
 + */
 +
 +/**
 + * JPEG2000 image decoder
 + * @file
 + * @author Kamil Nowosad
 + */
 +
 +// #define DEBUG
 +
 +#include "avcodec.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "j2k.h"
 +#include "libavutil/common.h"
 +
 +#define JP2_SIG_TYPE    0x6A502020
 +#define JP2_SIG_VALUE   0x0D0A870A
 +#define JP2_CODESTREAM  0x6A703263
 +
 +#define HAD_COC 0x01
 +#define HAD_QCC 0x02
 +
 +typedef struct {
 +   J2kComponent *comp;
 +   uint8_t properties[4];
 +   J2kCodingStyle codsty[4];
 +   J2kQuantStyle  qntsty[4];
 +} J2kTile;
 +
 +typedef struct {
 +    AVCodecContext *avctx;
-     if (s->picture.data[0])
-         s->avctx->release_buffer(s->avctx, &s->picture);
++    AVFrame *picture;
 +    GetByteContext g;
 +
 +    int width, height; ///< image width and height
 +    int image_offset_x, image_offset_y;
 +    int tile_offset_x, tile_offset_y;
 +    uint8_t cbps[4]; ///< bits per sample in particular components
 +    uint8_t sgnd[4]; ///< if a component is signed
 +    uint8_t properties[4];
 +    int cdx[4], cdy[4];
 +    int precision;
 +    int ncomponents;
 +    int tile_width, tile_height; ///< tile size
 +    int numXtiles, numYtiles;
 +    int maxtilelen;
 +
 +    J2kCodingStyle codsty[4];
 +    J2kQuantStyle  qntsty[4];
 +
 +    int bit_index;
 +
 +    int curtileno;
 +
 +    J2kTile *tile;
 +} J2kDecoderContext;
 +
 +static int get_bits(J2kDecoderContext *s, int n)
 +{
 +    int res = 0;
 +
 +    while (--n >= 0){
 +        res <<= 1;
 +        if (s->bit_index == 0) {
 +            s->bit_index = 7 + (bytestream2_get_byte(&s->g) != 0xFFu);
 +        }
 +        s->bit_index--;
 +        res |= (bytestream2_peek_byte(&s->g) >> s->bit_index) & 1;
 +    }
 +    return res;
 +}
 +
 +static void j2k_flush(J2kDecoderContext *s)
 +{
 +    if (bytestream2_get_byte(&s->g) == 0xff)
 +        bytestream2_skip(&s->g, 1);
 +    s->bit_index = 8;
 +}
 +#if 0
 +void printcomp(J2kComponent *comp)
 +{
 +    int i;
 +    for (i = 0; i < comp->y1 - comp->y0; i++)
 +        ff_j2k_printv(comp->data + i * (comp->x1 - comp->x0), comp->x1 - comp->x0);
 +}
 +
 +static void nspaces(FILE *fd, int n)
 +{
 +    while(n--) putc(' ', fd);
 +}
 +
 +static void dump(J2kDecoderContext *s, FILE *fd)
 +{
 +    int tileno, compno, reslevelno, bandno, precno;
 +    fprintf(fd, "XSiz = %d, YSiz = %d, tile_width = %d, tile_height = %d\n"
 +                "numXtiles = %d, numYtiles = %d, ncomponents = %d\n"
 +                "tiles:\n",
 +            s->width, s->height, s->tile_width, s->tile_height,
 +            s->numXtiles, s->numYtiles, s->ncomponents);
 +    for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
 +        J2kTile *tile = s->tile + tileno;
 +        nspaces(fd, 2);
 +        fprintf(fd, "tile %d:\n", tileno);
 +        for(compno = 0; compno < s->ncomponents; compno++){
 +            J2kComponent *comp = tile->comp + compno;
 +            nspaces(fd, 4);
 +            fprintf(fd, "component %d:\n", compno);
 +            nspaces(fd, 4);
 +            fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d\n",
 +                        comp->x0, comp->x1, comp->y0, comp->y1);
 +            for(reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
 +                J2kResLevel *reslevel = comp->reslevel + reslevelno;
 +                nspaces(fd, 6);
 +                fprintf(fd, "reslevel %d:\n", reslevelno);
 +                nspaces(fd, 6);
 +                fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d, nbands = %d\n",
 +                        reslevel->x0, reslevel->x1, reslevel->y0,
 +                        reslevel->y1, reslevel->nbands);
 +                for(bandno = 0; bandno < reslevel->nbands; bandno++){
 +                    J2kBand *band = reslevel->band + bandno;
 +                    nspaces(fd, 8);
 +                    fprintf(fd, "band %d:\n", bandno);
 +                    nspaces(fd, 8);
 +                    fprintf(fd, "x0 = %d, x1 = %d, y0 = %d, y1 = %d,"
 +                                "codeblock_width = %d, codeblock_height = %d cblknx = %d cblkny = %d\n",
 +                                band->x0, band->x1,
 +                                band->y0, band->y1,
 +                                band->codeblock_width, band->codeblock_height,
 +                                band->cblknx, band->cblkny);
 +                    for (precno = 0; precno < reslevel->num_precincts_x * reslevel->num_precincts_y; precno++){
 +                        J2kPrec *prec = band->prec + precno;
 +                        nspaces(fd, 10);
 +                        fprintf(fd, "prec %d:\n", precno);
 +                        nspaces(fd, 10);
 +                        fprintf(fd, "xi0 = %d, xi1 = %d, yi0 = %d, yi1 = %d\n",
 +                                     prec->xi0, prec->xi1, prec->yi0, prec->yi1);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +}
 +#endif
 +
 +/** decode the value stored in node */
 +static int tag_tree_decode(J2kDecoderContext *s, J2kTgtNode *node, int threshold)
 +{
 +    J2kTgtNode *stack[30];
 +    int sp = -1, curval = 0;
 +
 +    if(!node)
 +        return AVERROR(EINVAL);
 +
 +    while(node && !node->vis){
 +        stack[++sp] = node;
 +        node = node->parent;
 +    }
 +
 +    if (node)
 +        curval = node->val;
 +    else
 +        curval = stack[sp]->val;
 +
 +    while(curval < threshold && sp >= 0){
 +        if (curval < stack[sp]->val)
 +            curval = stack[sp]->val;
 +        while (curval < threshold){
 +            int ret;
 +            if ((ret = get_bits(s, 1)) > 0){
 +                stack[sp]->vis++;
 +                break;
 +            } else if (!ret)
 +                curval++;
 +            else
 +                return ret;
 +        }
 +        stack[sp]->val = curval;
 +        sp--;
 +    }
 +    return curval;
 +}
 +
 +/* marker segments */
 +/** get sizes and offsets of image, tiles; number of components */
 +static int get_siz(J2kDecoderContext *s)
 +{
 +    int i, ret;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 36)
 +        return AVERROR(EINVAL);
 +
 +                        bytestream2_get_be16u(&s->g); // Rsiz (skipped)
 +             s->width = bytestream2_get_be32u(&s->g); // width
 +            s->height = bytestream2_get_be32u(&s->g); // height
 +    s->image_offset_x = bytestream2_get_be32u(&s->g); // X0Siz
 +    s->image_offset_y = bytestream2_get_be32u(&s->g); // Y0Siz
 +
 +        s->tile_width = bytestream2_get_be32u(&s->g); // XTSiz
 +       s->tile_height = bytestream2_get_be32u(&s->g); // YTSiz
 +     s->tile_offset_x = bytestream2_get_be32u(&s->g); // XT0Siz
 +     s->tile_offset_y = bytestream2_get_be32u(&s->g); // YT0Siz
 +       s->ncomponents = bytestream2_get_be16u(&s->g); // CSiz
 +
 +    if(s->ncomponents <= 0 || s->ncomponents > 4) {
 +        av_log(s->avctx, AV_LOG_ERROR, "unsupported/invalid ncomponents: %d\n", s->ncomponents);
 +        return AVERROR(EINVAL);
 +    }
 +    if(s->tile_width<=0 || s->tile_height<=0)
 +        return AVERROR(EINVAL);
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 3 * s->ncomponents)
 +        return AVERROR(EINVAL);
 +
 +    for (i = 0; i < s->ncomponents; i++){ // Ssiz_i XRsiz_i, YRsiz_i
 +        uint8_t x = bytestream2_get_byteu(&s->g);
 +        s->cbps[i] = (x & 0x7f) + 1;
 +        s->precision = FFMAX(s->cbps[i], s->precision);
 +        s->sgnd[i] = !!(x & 0x80);
 +        s->cdx[i] = bytestream2_get_byteu(&s->g);
 +        s->cdy[i] = bytestream2_get_byteu(&s->g);
 +    }
 +
 +    s->numXtiles = ff_j2k_ceildiv(s->width - s->tile_offset_x, s->tile_width);
 +    s->numYtiles = ff_j2k_ceildiv(s->height - s->tile_offset_y, s->tile_height);
 +
 +    if(s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(J2kTile))
 +        return AVERROR(EINVAL);
 +
 +    s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(J2kTile));
 +    if (!s->tile)
 +        return AVERROR(ENOMEM);
 +
 +    for (i = 0; i < s->numXtiles * s->numYtiles; i++){
 +        J2kTile *tile = s->tile + i;
 +
 +        tile->comp = av_mallocz(s->ncomponents * sizeof(J2kComponent));
 +        if (!tile->comp)
 +            return AVERROR(ENOMEM);
 +    }
 +
 +    s->avctx->width  = s->width  - s->image_offset_x;
 +    s->avctx->height = s->height - s->image_offset_y;
 +
 +    switch(s->ncomponents){
 +    case 1:
 +        if (s->precision > 8) {
 +            s->avctx->pix_fmt = AV_PIX_FMT_GRAY16;
 +        } else {
 +            s->avctx->pix_fmt = AV_PIX_FMT_GRAY8;
 +        }
 +        break;
 +    case 3:
 +        if (s->precision > 8) {
 +            s->avctx->pix_fmt = AV_PIX_FMT_RGB48;
 +        } else {
 +            s->avctx->pix_fmt = AV_PIX_FMT_RGB24;
 +        }
 +        break;
 +    case 4:
 +        s->avctx->pix_fmt = AV_PIX_FMT_RGBA;
 +        break;
 +    }
 +
-     if ((ret = ff_get_buffer(s->avctx, &s->picture)) < 0)
 +
-     s->picture.pict_type = AV_PICTURE_TYPE_I;
-     s->picture.key_frame = 1;
++    if ((ret = ff_get_buffer(s->avctx, s->picture, 0)) < 0)
 +        return ret;
 +
-             line = s->picture.data[0] + y * s->picture.linesize[0];
++    s->picture->pict_type = AV_PICTURE_TYPE_I;
++    s->picture->key_frame = 1;
 +
 +    return 0;
 +}
 +
 +/** get common part for COD and COC segments */
 +static int get_cox(J2kDecoderContext *s, J2kCodingStyle *c)
 +{
 +    if (bytestream2_get_bytes_left(&s->g) < 5)
 +        return AVERROR(EINVAL);
 +          c->nreslevels = bytestream2_get_byteu(&s->g) + 1; // num of resolution levels - 1
 +     c->log2_cblk_width = bytestream2_get_byteu(&s->g) + 2; // cblk width
 +    c->log2_cblk_height = bytestream2_get_byteu(&s->g) + 2; // cblk height
 +
 +    c->cblk_style = bytestream2_get_byteu(&s->g);
 +    if (c->cblk_style != 0){ // cblk style
 +        av_log(s->avctx, AV_LOG_WARNING, "extra cblk styles %X\n", c->cblk_style);
 +    }
 +    c->transform = bytestream2_get_byteu(&s->g); // transformation
 +    if (c->csty & J2K_CSTY_PREC) {
 +        int i;
 +
 +        for (i = 0; i < c->nreslevels; i++)
 +            bytestream2_get_byte(&s->g);
 +    }
 +    return 0;
 +}
 +
 +/** get coding parameters for a particular tile or whole image*/
 +static int get_cod(J2kDecoderContext *s, J2kCodingStyle *c, uint8_t *properties)
 +{
 +    J2kCodingStyle tmp;
 +    int compno;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 5)
 +        return AVERROR(EINVAL);
 +
 +    tmp.log2_prec_width  =
 +    tmp.log2_prec_height = 15;
 +
 +    tmp.csty = bytestream2_get_byteu(&s->g);
 +
 +    if (bytestream2_get_byteu(&s->g)){ // progression level
 +        av_log(s->avctx, AV_LOG_ERROR, "only LRCP progression supported\n");
 +        return -1;
 +    }
 +
 +    tmp.nlayers = bytestream2_get_be16u(&s->g);
 +        tmp.mct = bytestream2_get_byteu(&s->g); // multiple component transformation
 +
 +    get_cox(s, &tmp);
 +    for (compno = 0; compno < s->ncomponents; compno++){
 +        if (!(properties[compno] & HAD_COC))
 +            memcpy(c + compno, &tmp, sizeof(J2kCodingStyle));
 +    }
 +    return 0;
 +}
 +
 +/** get coding parameters for a component in the whole image on a particular tile */
 +static int get_coc(J2kDecoderContext *s, J2kCodingStyle *c, uint8_t *properties)
 +{
 +    int compno;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 2)
 +        return AVERROR(EINVAL);
 +
 +    compno = bytestream2_get_byteu(&s->g);
 +
 +    c += compno;
 +    c->csty = bytestream2_get_byte(&s->g);
 +    get_cox(s, c);
 +
 +    properties[compno] |= HAD_COC;
 +    return 0;
 +}
 +
 +/** get common part for QCD and QCC segments */
 +static int get_qcx(J2kDecoderContext *s, int n, J2kQuantStyle *q)
 +{
 +    int i, x;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 1)
 +        return AVERROR(EINVAL);
 +
 +    x = bytestream2_get_byteu(&s->g); // Sqcd
 +
 +    q->nguardbits = x >> 5;
 +      q->quantsty = x & 0x1f;
 +
 +    if (q->quantsty == J2K_QSTY_NONE){
 +        n -= 3;
 +        if (bytestream2_get_bytes_left(&s->g) < n || 32*3 < n)
 +            return AVERROR(EINVAL);
 +        for (i = 0; i < n; i++)
 +            q->expn[i] = bytestream2_get_byteu(&s->g) >> 3;
 +    } else if (q->quantsty == J2K_QSTY_SI){
 +        if (bytestream2_get_bytes_left(&s->g) < 2)
 +            return AVERROR(EINVAL);
 +        x = bytestream2_get_be16u(&s->g);
 +        q->expn[0] = x >> 11;
 +        q->mant[0] = x & 0x7ff;
 +        for (i = 1; i < 32 * 3; i++){
 +            int curexpn = FFMAX(0, q->expn[0] - (i-1)/3);
 +            q->expn[i] = curexpn;
 +            q->mant[i] = q->mant[0];
 +        }
 +    } else{
 +        n = (n - 3) >> 1;
 +        if (bytestream2_get_bytes_left(&s->g) < 2 * n || 32*3 < n)
 +            return AVERROR(EINVAL);
 +        for (i = 0; i < n; i++){
 +            x = bytestream2_get_be16u(&s->g);
 +            q->expn[i] = x >> 11;
 +            q->mant[i] = x & 0x7ff;
 +        }
 +    }
 +    return 0;
 +}
 +
 +/** get quantization parameters for a particular tile or a whole image */
 +static int get_qcd(J2kDecoderContext *s, int n, J2kQuantStyle *q, uint8_t *properties)
 +{
 +    J2kQuantStyle tmp;
 +    int compno;
 +
 +    if (get_qcx(s, n, &tmp))
 +        return -1;
 +    for (compno = 0; compno < s->ncomponents; compno++)
 +        if (!(properties[compno] & HAD_QCC))
 +            memcpy(q + compno, &tmp, sizeof(J2kQuantStyle));
 +    return 0;
 +}
 +
 +/** get quantization parameters for a component in the whole image on in a particular tile */
 +static int get_qcc(J2kDecoderContext *s, int n, J2kQuantStyle *q, uint8_t *properties)
 +{
 +    int compno;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 1)
 +        return AVERROR(EINVAL);
 +
 +    compno = bytestream2_get_byteu(&s->g);
 +    properties[compno] |= HAD_QCC;
 +    return get_qcx(s, n-1, q+compno);
 +}
 +
 +/** get start of tile segment */
 +static uint8_t get_sot(J2kDecoderContext *s)
 +{
 +    if (bytestream2_get_bytes_left(&s->g) < 8)
 +        return AVERROR(EINVAL);
 +
 +    s->curtileno = bytestream2_get_be16u(&s->g); ///< Isot
 +    if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){
 +        s->curtileno=0;
 +        return AVERROR(EINVAL);
 +    }
 +
 +    bytestream2_skipu(&s->g, 4); ///< Psot (ignored)
 +
 +    if (!bytestream2_get_byteu(&s->g)){ ///< TPsot
 +        J2kTile *tile = s->tile + s->curtileno;
 +
 +        /* copy defaults */
 +        memcpy(tile->codsty, s->codsty, s->ncomponents * sizeof(J2kCodingStyle));
 +        memcpy(tile->qntsty, s->qntsty, s->ncomponents * sizeof(J2kQuantStyle));
 +    }
 +    bytestream2_get_byteu(&s->g); ///< TNsot
 +
 +    return 0;
 +}
 +
 +static int init_tile(J2kDecoderContext *s, int tileno)
 +{
 +    int compno,
 +        tilex = tileno % s->numXtiles,
 +        tiley = tileno / s->numXtiles;
 +    J2kTile *tile = s->tile + tileno;
 +
 +    if (!tile->comp)
 +        return AVERROR(ENOMEM);
 +    for (compno = 0; compno < s->ncomponents; compno++){
 +        J2kComponent *comp = tile->comp + compno;
 +        J2kCodingStyle *codsty = tile->codsty + compno;
 +        J2kQuantStyle  *qntsty = tile->qntsty + compno;
 +        int ret; // global bandno
 +
 +        comp->coord[0][0] = FFMAX(tilex * s->tile_width + s->tile_offset_x, s->image_offset_x);
 +        comp->coord[0][1] = FFMIN((tilex+1)*s->tile_width + s->tile_offset_x, s->width);
 +        comp->coord[1][0] = FFMAX(tiley * s->tile_height + s->tile_offset_y, s->image_offset_y);
 +        comp->coord[1][1] = FFMIN((tiley+1)*s->tile_height + s->tile_offset_y, s->height);
 +
 +        if (ret = ff_j2k_init_component(comp, codsty, qntsty, s->cbps[compno], s->cdx[compno], s->cdy[compno]))
 +            return ret;
 +    }
 +    return 0;
 +}
 +
 +/** read the number of coding passes */
 +static int getnpasses(J2kDecoderContext *s)
 +{
 +    int num;
 +    if (!get_bits(s, 1))
 +        return 1;
 +    if (!get_bits(s, 1))
 +        return 2;
 +    if ((num = get_bits(s, 2)) != 3)
 +        return num < 0 ? num : 3 + num;
 +    if ((num = get_bits(s, 5)) != 31)
 +        return num < 0 ? num : 6 + num;
 +    num = get_bits(s, 7);
 +    return num < 0 ? num : 37 + num;
 +}
 +
 +static int getlblockinc(J2kDecoderContext *s)
 +{
 +    int res = 0, ret;
 +    while (ret = get_bits(s, 1)){
 +        if (ret < 0)
 +            return ret;
 +        res++;
 +    }
 +    return res;
 +}
 +
 +static int decode_packet(J2kDecoderContext *s, J2kCodingStyle *codsty, J2kResLevel *rlevel, int precno,
 +                         int layno, uint8_t *expn, int numgbits)
 +{
 +    int bandno, cblkny, cblknx, cblkno, ret;
 +
 +    if (!(ret = get_bits(s, 1))){
 +        j2k_flush(s);
 +        return 0;
 +    } else if (ret < 0)
 +        return ret;
 +
 +    for (bandno = 0; bandno < rlevel->nbands; bandno++){
 +        J2kBand *band = rlevel->band + bandno;
 +        J2kPrec *prec = band->prec + precno;
 +        int pos = 0;
 +
 +        if (band->coord[0][0] == band->coord[0][1]
 +        ||  band->coord[1][0] == band->coord[1][1])
 +            continue;
 +
 +        for (cblkny = prec->yi0; cblkny < prec->yi1; cblkny++)
 +            for(cblknx = prec->xi0, cblkno = cblkny * band->cblknx + cblknx; cblknx < prec->xi1; cblknx++, cblkno++, pos++){
 +                J2kCblk *cblk = band->cblk + cblkno;
 +                int incl, newpasses, llen;
 +
 +                if (cblk->npasses)
 +                    incl = get_bits(s, 1);
 +                else
 +                    incl = tag_tree_decode(s, prec->cblkincl + pos, layno+1) == layno;
 +                if (!incl)
 +                    continue;
 +                else if (incl < 0)
 +                    return incl;
 +
 +                if (!cblk->npasses)
 +                    cblk->nonzerobits = expn[bandno] + numgbits - 1 - tag_tree_decode(s, prec->zerobits + pos, 100);
 +                if ((newpasses = getnpasses(s)) < 0)
 +                    return newpasses;
 +                if ((llen = getlblockinc(s)) < 0)
 +                    return llen;
 +                cblk->lblock += llen;
 +                if ((ret = get_bits(s, av_log2(newpasses) + cblk->lblock)) < 0)
 +                    return ret;
 +                cblk->lengthinc = ret;
 +                cblk->npasses += newpasses;
 +            }
 +    }
 +    j2k_flush(s);
 +
 +    if (codsty->csty & J2K_CSTY_EPH) {
 +        if (bytestream2_peek_be16(&s->g) == J2K_EPH) {
 +            bytestream2_skip(&s->g, 2);
 +        } else {
 +            av_log(s->avctx, AV_LOG_ERROR, "EPH marker not found.\n");
 +        }
 +    }
 +
 +    for (bandno = 0; bandno < rlevel->nbands; bandno++){
 +        J2kBand *band = rlevel->band + bandno;
 +        int yi, cblknw = band->prec[precno].xi1 - band->prec[precno].xi0;
 +        for (yi = band->prec[precno].yi0; yi < band->prec[precno].yi1; yi++){
 +            int xi;
 +            for (xi = band->prec[precno].xi0; xi < band->prec[precno].xi1; xi++){
 +                J2kCblk *cblk = band->cblk + yi * cblknw + xi;
 +                if (bytestream2_get_bytes_left(&s->g) < cblk->lengthinc)
 +                    return AVERROR(EINVAL);
 +                bytestream2_get_bufferu(&s->g, cblk->data, cblk->lengthinc);
 +                cblk->length += cblk->lengthinc;
 +                cblk->lengthinc = 0;
 +            }
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int decode_packets(J2kDecoderContext *s, J2kTile *tile)
 +{
 +    int layno, reslevelno, compno, precno, ok_reslevel;
 +    s->bit_index = 8;
 +    for (layno = 0; layno < tile->codsty[0].nlayers; layno++){
 +        ok_reslevel = 1;
 +        for (reslevelno = 0; ok_reslevel; reslevelno++){
 +            ok_reslevel = 0;
 +            for (compno = 0; compno < s->ncomponents; compno++){
 +                J2kCodingStyle *codsty = tile->codsty + compno;
 +                J2kQuantStyle  *qntsty = tile->qntsty + compno;
 +                if (reslevelno < codsty->nreslevels){
 +                    J2kResLevel *rlevel = tile->comp[compno].reslevel + reslevelno;
 +                    ok_reslevel = 1;
 +                    for (precno = 0; precno < rlevel->num_precincts_x * rlevel->num_precincts_y; precno++){
 +                        if (decode_packet(s, codsty, rlevel, precno, layno, qntsty->expn +
 +                                          (reslevelno ? 3*(reslevelno-1)+1 : 0), qntsty->nguardbits))
 +                            return -1;
 +                    }
 +                }
 +            }
 +        }
 +    }
 +    return 0;
 +}
 +
 +/* TIER-1 routines */
 +static void decode_sigpass(J2kT1Context *t1, int width, int height, int bpno, int bandno, int bpass_csty_symbol,
 +                           int vert_causal_ctx_csty_symbol)
 +{
 +    int mask = 3 << (bpno - 1), y0, x, y;
 +
 +    for (y0 = 0; y0 < height; y0 += 4)
 +        for (x = 0; x < width; x++)
 +            for (y = y0; y < height && y < y0+4; y++){
 +                if ((t1->flags[y+1][x+1] & J2K_T1_SIG_NB)
 +                && !(t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS))){
 +                    int vert_causal_ctx_csty_loc_symbol = vert_causal_ctx_csty_symbol && (x == 3 && y == 3);
 +                    if (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_j2k_getnbctxno(t1->flags[y+1][x+1], bandno,
 +                                      vert_causal_ctx_csty_loc_symbol))){
 +                        int xorbit, ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
 +                        if (bpass_csty_symbol)
 +                             t1->data[y][x] = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? -mask : mask;
 +                        else
 +                             t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ?
 +                                               -mask : mask;
 +
 +                        ff_j2k_set_significant(t1, x, y, t1->data[y][x] < 0);
 +                    }
 +                    t1->flags[y+1][x+1] |= J2K_T1_VIS;
 +                }
 +            }
 +}
 +
 +static void decode_refpass(J2kT1Context *t1, int width, int height, int bpno)
 +{
 +    int phalf, nhalf;
 +    int y0, x, y;
 +
 +    phalf = 1 << (bpno - 1);
 +    nhalf = -phalf;
 +
 +    for (y0 = 0; y0 < height; y0 += 4)
 +        for (x = 0; x < width; x++)
 +            for (y = y0; y < height && y < y0+4; y++){
 +                if ((t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS)) == J2K_T1_SIG){
 +                    int ctxno = ff_j2k_getrefctxno(t1->flags[y+1][x+1]);
 +                    int r = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ? phalf : nhalf;
 +                    t1->data[y][x] += t1->data[y][x] < 0 ? -r : r;
 +                    t1->flags[y+1][x+1] |= J2K_T1_REF;
 +                }
 +            }
 +}
 +
 +static void decode_clnpass(J2kDecoderContext *s, J2kT1Context *t1, int width, int height,
 +                           int bpno, int bandno, int seg_symbols)
 +{
 +    int mask = 3 << (bpno - 1), y0, x, y, runlen, dec;
 +
 +    for (y0 = 0; y0 < height; y0 += 4) {
 +        for (x = 0; x < width; x++){
 +            if (y0 + 3 < height && !(
 +            (t1->flags[y0+1][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) ||
 +            (t1->flags[y0+2][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) ||
 +            (t1->flags[y0+3][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)) ||
 +            (t1->flags[y0+4][x+1] & (J2K_T1_SIG_NB | J2K_T1_VIS | J2K_T1_SIG)))){
 +                if (!ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_RL))
 +                    continue;
 +                runlen = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
 +                runlen = (runlen << 1) | ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
 +                dec = 1;
 +            } else{
 +                runlen = 0;
 +                dec = 0;
 +            }
 +
 +            for (y = y0 + runlen; y < y0 + 4 && y < height; y++){
 +                if (!dec){
 +                    if (!(t1->flags[y+1][x+1] & (J2K_T1_SIG | J2K_T1_VIS)))
 +                        dec = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ff_j2k_getnbctxno(t1->flags[y+1][x+1],
 +                                                                                             bandno, 0));
 +                }
 +                if (dec){
 +                    int xorbit, ctxno = ff_j2k_getsgnctxno(t1->flags[y+1][x+1], &xorbit);
 +                    t1->data[y][x] = (ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + ctxno) ^ xorbit) ? -mask : mask;
 +                    ff_j2k_set_significant(t1, x, y, t1->data[y][x] < 0);
 +                }
 +                dec = 0;
 +                t1->flags[y+1][x+1] &= ~J2K_T1_VIS;
 +            }
 +        }
 +    }
 +    if (seg_symbols) {
 +        int val;
 +        val = ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
 +        val = (val << 1) + ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
 +        val = (val << 1) + ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
 +        val = (val << 1) + ff_mqc_decode(&t1->mqc, t1->mqc.cx_states + MQC_CX_UNI);
 +        if (val != 0xa) {
 +            av_log(s->avctx, AV_LOG_ERROR,"Segmentation symbol value incorrect\n");
 +        }
 +    }
 +}
 +
 +static int decode_cblk(J2kDecoderContext *s, J2kCodingStyle *codsty, J2kT1Context *t1, J2kCblk *cblk,
 +                       int width, int height, int bandpos)
 +{
 +    int passno = cblk->npasses, pass_t = 2, bpno = cblk->nonzerobits - 1, y, clnpass_cnt = 0;
 +    int bpass_csty_symbol = J2K_CBLK_BYPASS & codsty->cblk_style;
 +    int vert_causal_ctx_csty_symbol = J2K_CBLK_VSC & codsty->cblk_style;
 +
 +    for (y = 0; y < height+2; y++)
 +        memset(t1->flags[y], 0, (width+2)*sizeof(int));
 +
 +    for (y = 0; y < height; y++)
 +        memset(t1->data[y], 0, width*sizeof(int));
 +
 +    cblk->data[cblk->length] = 0xff;
 +    cblk->data[cblk->length+1] = 0xff;
 +    ff_mqc_initdec(&t1->mqc, cblk->data);
 +
 +    while(passno--){
 +        switch(pass_t){
 +            case 0: decode_sigpass(t1, width, height, bpno+1, bandpos,
 +                                  bpass_csty_symbol && (clnpass_cnt >= 4), vert_causal_ctx_csty_symbol);
 +                    break;
 +            case 1: decode_refpass(t1, width, height, bpno+1);
 +                    if (bpass_csty_symbol && clnpass_cnt >= 4)
 +                        ff_mqc_initdec(&t1->mqc, cblk->data);
 +                    break;
 +            case 2: decode_clnpass(s, t1, width, height, bpno+1, bandpos,
 +                                   codsty->cblk_style & J2K_CBLK_SEGSYM);
 +                    clnpass_cnt = clnpass_cnt + 1;
 +                    if (bpass_csty_symbol && clnpass_cnt >= 4)
 +                       ff_mqc_initdec(&t1->mqc, cblk->data);
 +                    break;
 +        }
 +
 +        pass_t++;
 +        if (pass_t == 3){
 +            bpno--;
 +            pass_t = 0;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static void mct_decode(J2kDecoderContext *s, J2kTile *tile)
 +{
 +    int i, *src[3], i0, i1, i2, csize = 1;
 +
 +    for (i = 0; i < 3; i++)
 +        src[i] = tile->comp[i].data;
 +
 +    for (i = 0; i < 2; i++)
 +        csize *= tile->comp[0].coord[i][1] - tile->comp[0].coord[i][0];
 +
 +    if (tile->codsty[0].transform == FF_DWT97){
 +        for (i = 0; i < csize; i++){
 +            i0 = *src[0] + (*src[2] * 46802 >> 16);
 +            i1 = *src[0] - (*src[1] * 22553 + *src[2] * 46802 >> 16);
 +            i2 = *src[0] + (116130 * *src[1] >> 16);
 +            *src[0]++ = i0;
 +            *src[1]++ = i1;
 +            *src[2]++ = i2;
 +        }
 +    } else{
 +        for (i = 0; i < csize; i++){
 +            i1 = *src[0] - (*src[2] + *src[1] >> 2);
 +            i0 = i1 + *src[2];
 +            i2 = i1 + *src[1];
 +            *src[0]++ = i0;
 +            *src[1]++ = i1;
 +            *src[2]++ = i2;
 +        }
 +    }
 +}
 +
 +static int decode_tile(J2kDecoderContext *s, J2kTile *tile)
 +{
 +    int compno, reslevelno, bandno;
 +    int x, y, *src[4];
 +    uint8_t *line;
 +    J2kT1Context t1;
 +
 +    for (compno = 0; compno < s->ncomponents; compno++){
 +        J2kComponent *comp = tile->comp + compno;
 +        J2kCodingStyle *codsty = tile->codsty + compno;
 +
 +        for (reslevelno = 0; reslevelno < codsty->nreslevels; reslevelno++){
 +            J2kResLevel *rlevel = comp->reslevel + reslevelno;
 +            for (bandno = 0; bandno < rlevel->nbands; bandno++){
 +                J2kBand *band = rlevel->band + bandno;
 +                int cblkx, cblky, cblkno=0, xx0, x0, xx1, y0, yy0, yy1, bandpos;
 +
 +                bandpos = bandno + (reslevelno > 0);
 +
 +                yy0 = bandno == 0 ? 0 : comp->reslevel[reslevelno-1].coord[1][1] - comp->reslevel[reslevelno-1].coord[1][0];
 +                y0 = yy0;
 +                yy1 = FFMIN(ff_j2k_ceildiv(band->coord[1][0] + 1, band->codeblock_height) * band->codeblock_height,
 +                            band->coord[1][1]) - band->coord[1][0] + yy0;
 +
 +                if (band->coord[0][0] == band->coord[0][1] || band->coord[1][0] == band->coord[1][1])
 +                    continue;
 +
 +                for (cblky = 0; cblky < band->cblkny; cblky++){
 +                    if (reslevelno == 0 || bandno == 1)
 +                        xx0 = 0;
 +                    else
 +                        xx0 = comp->reslevel[reslevelno-1].coord[0][1] - comp->reslevel[reslevelno-1].coord[0][0];
 +                    x0 = xx0;
 +                    xx1 = FFMIN(ff_j2k_ceildiv(band->coord[0][0] + 1, band->codeblock_width) * band->codeblock_width,
 +                                band->coord[0][1]) - band->coord[0][0] + xx0;
 +
 +                    for (cblkx = 0; cblkx < band->cblknx; cblkx++, cblkno++){
 +                        int y, x;
 +                        decode_cblk(s, codsty, &t1, band->cblk + cblkno, xx1 - xx0, yy1 - yy0, bandpos);
 +                        if (codsty->transform == FF_DWT53){
 +                            for (y = yy0; y < yy1; y+=s->cdy[compno]){
 +                                int *ptr = t1.data[y-yy0];
 +                                for (x = xx0; x < xx1; x+=s->cdx[compno]){
 +                                    comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] = *ptr++ >> 1;
 +                                }
 +                            }
 +                        } else{
 +                            for (y = yy0; y < yy1; y+=s->cdy[compno]){
 +                                int *ptr = t1.data[y-yy0];
 +                                for (x = xx0; x < xx1; x+=s->cdx[compno]){
 +                                    int tmp = ((int64_t)*ptr++) * ((int64_t)band->stepsize) >> 13, tmp2;
 +                                    tmp2 = FFABS(tmp>>1) + (tmp&1);
 +                                    comp->data[(comp->coord[0][1] - comp->coord[0][0]) * y + x] = tmp < 0 ? -tmp2 : tmp2;
 +                                }
 +                            }
 +                        }
 +                        xx0 = xx1;
 +                        xx1 = FFMIN(xx1 + band->codeblock_width, band->coord[0][1] - band->coord[0][0] + x0);
 +                    }
 +                    yy0 = yy1;
 +                    yy1 = FFMIN(yy1 + band->codeblock_height, band->coord[1][1] - band->coord[1][0] + y0);
 +                }
 +            }
 +        }
 +        ff_j2k_dwt_decode(&comp->dwt, comp->data);
 +        src[compno] = comp->data;
 +    }
 +    if (tile->codsty[0].mct)
 +        mct_decode(s, tile);
 +
 +    if (s->precision <= 8) {
 +        for (compno = 0; compno < s->ncomponents; compno++){
 +            y = tile->comp[compno].coord[1][0] - s->image_offset_y;
-                 line += s->picture.linesize[0];
++            line = s->picture->data[0] + y * s->picture->linesize[0];
 +            for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]){
 +                uint8_t *dst;
 +
 +                x = tile->comp[compno].coord[0][0] - s->image_offset_x;
 +                dst = line + x * s->ncomponents + compno;
 +
 +                for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s->cdx[compno]) {
 +                    *src[compno] += 1 << (s->cbps[compno]-1);
 +                    if (*src[compno] < 0)
 +                        *src[compno] = 0;
 +                    else if (*src[compno] >= (1 << s->cbps[compno]))
 +                        *src[compno] = (1 << s->cbps[compno]) - 1;
 +                    *dst = *src[compno]++;
 +                    dst += s->ncomponents;
 +                }
-             line = s->picture.data[0] + y * s->picture.linesize[0];
++                line += s->picture->linesize[0];
 +            }
 +        }
 +    } else {
 +        for (compno = 0; compno < s->ncomponents; compno++) {
 +            y = tile->comp[compno].coord[1][0] - s->image_offset_y;
-                 line += s->picture.linesize[0];
++            line = s->picture->data[0] + y * s->picture->linesize[0];
 +            for (; y < tile->comp[compno].coord[1][1] - s->image_offset_y; y += s->cdy[compno]) {
 +                uint16_t *dst;
 +
 +                x = tile->comp[compno].coord[0][0] - s->image_offset_x;
 +                dst = (uint16_t *)(line + (x * s->ncomponents + compno) * 2);
 +                for (; x < tile->comp[compno].coord[0][1] - s->image_offset_x; x += s-> cdx[compno]) {
 +                    int32_t val;
 +
 +                    val = *src[compno]++ << (16 - s->cbps[compno]);
 +                    val += 1 << 15;
 +                    val = av_clip(val, 0, (1 << 16) - 1);
 +                    *dst = val;
 +                    dst += s->ncomponents;
 +                }
-     *picture = s->picture;
++                line += s->picture->linesize[0];
 +            }
 +        }
 +    }
 +    return 0;
 +}
 +
 +static void cleanup(J2kDecoderContext *s)
 +{
 +    int tileno, compno;
 +    for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++){
 +        for (compno = 0; compno < s->ncomponents; compno++){
 +            J2kComponent *comp = s->tile[tileno].comp + compno;
 +            J2kCodingStyle *codsty = s->tile[tileno].codsty + compno;
 +
 +            ff_j2k_cleanup(comp, codsty);
 +        }
 +        av_freep(&s->tile[tileno].comp);
 +    }
 +    av_freep(&s->tile);
 +}
 +
 +static int decode_codestream(J2kDecoderContext *s)
 +{
 +    J2kCodingStyle *codsty = s->codsty;
 +    J2kQuantStyle  *qntsty = s->qntsty;
 +    uint8_t *properties = s->properties;
 +
 +    for (;;){
 +        int oldpos, marker, len, ret = 0;
 +
 +        if (bytestream2_get_bytes_left(&s->g) < 2){
 +            av_log(s->avctx, AV_LOG_ERROR, "Missing EOC\n");
 +            break;
 +        }
 +
 +        marker = bytestream2_get_be16u(&s->g);
 +        av_dlog(s->avctx, "marker 0x%.4X at pos 0x%x\n", marker, bytestream2_tell(&s->g) - 4);
 +        oldpos = bytestream2_tell(&s->g);
 +
 +        if (marker == J2K_SOD){
 +            J2kTile *tile = s->tile + s->curtileno;
 +            if (ret = init_tile(s, s->curtileno)) {
 +                av_log(s->avctx, AV_LOG_ERROR, "tile initialization failed\n");
 +                return ret;
 +            }
 +            if (ret = decode_packets(s, tile)) {
 +                av_log(s->avctx, AV_LOG_ERROR, "packets decoding failed\n");
 +                return ret;
 +            }
 +            continue;
 +        }
 +        if (marker == J2K_EOC)
 +            break;
 +
 +        if (bytestream2_get_bytes_left(&s->g) < 2)
 +            return AVERROR(EINVAL);
 +        len = bytestream2_get_be16u(&s->g);
 +        switch (marker){
 +        case J2K_SIZ:
 +            ret = get_siz(s);
 +            break;
 +        case J2K_COC:
 +            ret = get_coc(s, codsty, properties);
 +            break;
 +        case J2K_COD:
 +            ret = get_cod(s, codsty, properties);
 +            break;
 +        case J2K_QCC:
 +            ret = get_qcc(s, len, qntsty, properties);
 +            break;
 +        case J2K_QCD:
 +            ret = get_qcd(s, len, qntsty, properties);
 +            break;
 +        case J2K_SOT:
 +            if (!(ret = get_sot(s))){
 +                codsty = s->tile[s->curtileno].codsty;
 +                qntsty = s->tile[s->curtileno].qntsty;
 +                properties = s->tile[s->curtileno].properties;
 +            }
 +            break;
 +        case J2K_COM:
 +            // the comment is ignored
 +            bytestream2_skip(&s->g, len - 2);
 +            break;
 +        default:
 +            av_log(s->avctx, AV_LOG_ERROR, "unsupported marker 0x%.4X at pos 0x%x\n", marker, bytestream2_tell(&s->g) - 4);
 +            bytestream2_skip(&s->g, len - 2);
 +            break;
 +        }
 +        if (bytestream2_tell(&s->g) - oldpos != len || ret){
 +            av_log(s->avctx, AV_LOG_ERROR, "error during processing marker segment %.4x\n", marker);
 +            return ret ? ret : -1;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int jp2_find_codestream(J2kDecoderContext *s)
 +{
 +    uint32_t atom_size, atom;
 +    int found_codestream = 0, search_range = 10;
 +
 +    while(!found_codestream && search_range && bytestream2_get_bytes_left(&s->g) >= 8) {
 +        atom_size = bytestream2_get_be32u(&s->g);
 +        atom      = bytestream2_get_be32u(&s->g);
 +        if (atom == JP2_CODESTREAM) {
 +            found_codestream = 1;
 +        } else {
 +            if (bytestream2_get_bytes_left(&s->g) < atom_size - 8)
 +                return 0;
 +            bytestream2_skipu(&s->g, atom_size - 8);
 +            search_range--;
 +        }
 +    }
 +
 +    if (found_codestream)
 +        return 1;
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx,
 +                        void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    J2kDecoderContext *s = avctx->priv_data;
 +    AVFrame *picture = data;
 +    int tileno, ret;
 +
++    s->picture = picture;
++
 +    bytestream2_init(&s->g, avpkt->data, avpkt->size);
 +    s->curtileno = -1;
 +
 +    if (bytestream2_get_bytes_left(&s->g) < 2) {
 +        ret = AVERROR(EINVAL);
 +        goto err_out;
 +    }
 +
 +    // check if the image is in jp2 format
 +    if (bytestream2_get_bytes_left(&s->g) >= 12 &&
 +       (bytestream2_get_be32u(&s->g) == 12) &&
 +       (bytestream2_get_be32u(&s->g) == JP2_SIG_TYPE) &&
 +       (bytestream2_get_be32u(&s->g) == JP2_SIG_VALUE)) {
 +        if(!jp2_find_codestream(s)) {
 +            av_log(avctx, AV_LOG_ERROR, "couldn't find jpeg2k codestream atom\n");
 +            ret = -1;
 +            goto err_out;
 +        }
 +    } else {
 +        bytestream2_seek(&s->g, 0, SEEK_SET);
 +    }
 +
 +    if (bytestream2_get_be16u(&s->g) != J2K_SOC){
 +        av_log(avctx, AV_LOG_ERROR, "SOC marker not present\n");
 +        ret = -1;
 +        goto err_out;
 +    }
 +    if (ret = decode_codestream(s))
 +        goto err_out;
 +
 +    for (tileno = 0; tileno < s->numXtiles * s->numYtiles; tileno++)
 +        if (ret = decode_tile(s, s->tile + tileno))
 +            goto err_out;
 +
 +    cleanup(s);
 +
 +    *got_frame = 1;
-     avcodec_get_frame_defaults((AVFrame*)&s->picture);
-     avctx->coded_frame = (AVFrame*)&s->picture;
 +
 +    return bytestream2_tell(&s->g);
 +
 +err_out:
 +    cleanup(s);
 +    return ret;
 +}
 +
 +static av_cold int j2kdec_init(AVCodecContext *avctx)
 +{
 +    J2kDecoderContext *s = avctx->priv_data;
 +
 +    s->avctx = avctx;
-     if (s->picture.data[0])
-         avctx->release_buffer(avctx, &s->picture);
 +
 +    ff_j2k_init_tier1_luts();
 +
 +    return 0;
 +}
 +
 +static av_cold int decode_end(AVCodecContext *avctx)
 +{
 +    J2kDecoderContext *s = avctx->priv_data;
 +
 +    return 0;
 +}
 +
 +AVCodec ff_jpeg2000_decoder = {
 +    .name           = "j2k",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_JPEG2000,
 +    .priv_data_size = sizeof(J2kDecoderContext),
 +    .init           = j2kdec_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_EXPERIMENTAL,
 +    .long_name      = NULL_IF_CONFIG_SMALL("JPEG 2000"),
 +};
@@@ -133,23 -134,17 +134,23 @@@ static int decode_frame(AVCodecContext 
                          AVPacket *avpkt)
  {
      JvContext *s           = avctx->priv_data;
 -    int buf_size           = avpkt->size;
      const uint8_t *buf     = avpkt->data;
 -    const uint8_t *buf_end = buf + buf_size;
 +    const uint8_t *buf_end = buf + avpkt->size;
-     int video_size, video_type, ret, i, j;
+     int video_size, video_type, i, j, ret;
  
 +    if (avpkt->size < 6)
 +        return AVERROR_INVALIDDATA;
 +
      video_size = AV_RL32(buf);
      video_type = buf[4];
      buf += 5;
  
      if (video_size) {
-         if ((ret = avctx->reget_buffer(avctx, &s->frame)) < 0) {
 +        if (video_size < 0 || video_size > avpkt->size - 5) {
 +            av_log(avctx, AV_LOG_ERROR, "video size %d invalid\n", video_size);
 +            return AVERROR_INVALIDDATA;
 +        }
+         if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) {
              av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
              return ret;
          }
          s->palette_has_changed       = 0;
          memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
  
+         if ((ret = av_frame_ref(data, &s->frame)) < 0)
+             return ret;
          *got_frame = 1;
-         *(AVFrame*)data = s->frame;
      }
  
 -    return buf_size;
 +    return avpkt->size;
  }
  
  static av_cold int decode_close(AVCodecContext *avctx)
@@@ -72,12 -71,11 +71,11 @@@ static int decode_frame(AVCodecContext 
  
      maxcnt = w * h;
  
-     c->cur.reference = 3;
-     if ((res = ff_get_buffer(avctx, &c->cur)) < 0)
+     if ((res = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
          return res;
-     out  = c->cur.data[0];
 -    out  = (uint16_t *) frame->data[0];
++    out  = frame->data[0];
      if (c->prev.data[0]) {
 -        prev = (uint16_t *) c->prev.data[0];
 +        prev = c->prev.data[0];
      } else {
          prev = NULL;
      }
@@@ -301,10 -281,10 +297,10 @@@ static int decode_frame(AVCodecContext 
      }
  
      if (header & KMVC_PALETTE) {
-         ctx->pic.palette_has_changed = 1;
+         frame->palette_has_changed = 1;
          // palette starts from index 1 and has 127 entries
          for (i = 1; i <= ctx->palsize; i++) {
 -            ctx->pal[i] = bytestream2_get_be24(&ctx->g);
 +            ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24(&ctx->g);
          }
      }
  
@@@ -510,22 -499,16 +509,17 @@@ static int lag_decode_frame(AVCodecCont
                              void *data, int *got_frame, AVPacket *avpkt)
  {
      const uint8_t *buf = avpkt->data;
 -    int buf_size = avpkt->size;
 +    unsigned int buf_size = avpkt->size;
      LagarithContext *l = avctx->priv_data;
-     AVFrame *const p = &l->picture;
+     ThreadFrame frame = { .f = data };
+     AVFrame *const p  = data;
      uint8_t frametype = 0;
      uint32_t offset_gu = 0, offset_bv = 0, offset_ry = 9;
      uint32_t offs[4];
      uint8_t *srcs[4], *dst;
      int i, j, planes = 3;
 +    int ret;
  
-     AVFrame *picture = data;
-     if (p->data[0])
-         ff_thread_release_buffer(avctx, p);
-     p->reference = 0;
      p->key_frame = 1;
  
      frametype = buf[0];
      switch (frametype) {
      case FRAME_SOLID_RGBA:
          avctx->pix_fmt = AV_PIX_FMT_RGB32;
 +    case FRAME_SOLID_GRAY:
 +        if (frametype == FRAME_SOLID_GRAY)
 +            if (avctx->bits_per_coded_sample == 24) {
 +                avctx->pix_fmt = AV_PIX_FMT_RGB24;
 +            } else {
 +                avctx->pix_fmt = AV_PIX_FMT_0RGB32;
 +                planes = 4;
 +            }
  
-         if ((ret = ff_thread_get_buffer(avctx, p)) < 0) {
 -        if (ff_thread_get_buffer(avctx, &frame, 0) < 0) {
++        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
              av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -            return -1;
 +            return ret;
          }
  
          dst = p->data[0];
          if (frametype == FRAME_ARITH_RGB24 || frametype == FRAME_U_RGB24)
              avctx->pix_fmt = AV_PIX_FMT_RGB24;
  
-         if ((ret = ff_thread_get_buffer(avctx, p)) < 0) {
 -        if (ff_thread_get_buffer(avctx, &frame, 0) < 0) {
++        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
              av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -            return -1;
 +            return ret;
          }
  
          offs[0] = offset_bv;
      case FRAME_ARITH_YUY2:
          avctx->pix_fmt = AV_PIX_FMT_YUV422P;
  
-         if ((ret = ff_thread_get_buffer(avctx, p)) < 0) {
 -        if (ff_thread_get_buffer(avctx, &frame, 0) < 0) {
++        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
              av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -            return -1;
 +            return ret;
          }
  
          if (offset_ry >= buf_size ||
      case FRAME_ARITH_YV12:
          avctx->pix_fmt = AV_PIX_FMT_YUV420P;
  
-         if ((ret = ff_thread_get_buffer(avctx, p)) < 0) {
 -        if (ff_thread_get_buffer(avctx, &frame, 0) < 0) {
++        if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) {
              av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -            return -1;
 +            return ret;
 +        }
 +        if (buf_size <= offset_ry || buf_size <= offset_gu || buf_size <= offset_bv) {
 +            return AVERROR_INVALIDDATA;
          }
  
          if (offset_ry >= buf_size ||
      default:
          av_log(avctx, AV_LOG_ERROR,
                 "Unsupported Lagarith frame type: %#x\n", frametype);
 -        return -1;
 +        return AVERROR_PATCHWELCOME;
      }
  
-     *picture = *p;
      *got_frame = 1;
  
      return buf_size;
Simple merge
index a66f9f5,0000000..496b95a
mode 100644,000000..100644
--- /dev/null
@@@ -1,143 -1,0 +1,143 @@@
-     err = ff_get_buffer(c, frame);
 +/*
 + * Xiph CELT decoder using libcelt
 + * Copyright (c) 2011 Nicolas George
 + *
 + * 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 <celt/celt.h>
 +#include <celt/celt_header.h>
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "libavutil/intreadwrite.h"
 +
 +struct libcelt_context {
 +    CELTMode *mode;
 +    CELTDecoder *dec;
 +    int discard;
 +};
 +
 +static int ff_celt_error_to_averror(int err)
 +{
 +    switch (err) {
 +        case CELT_BAD_ARG:          return AVERROR(EINVAL);
 +#ifdef CELT_BUFFER_TOO_SMALL
 +        case CELT_BUFFER_TOO_SMALL: return AVERROR(ENOBUFS);
 +#endif
 +        case CELT_INTERNAL_ERROR:   return AVERROR(EFAULT);
 +        case CELT_CORRUPTED_DATA:   return AVERROR_INVALIDDATA;
 +        case CELT_UNIMPLEMENTED:    return AVERROR(ENOSYS);
 +#ifdef ENOTRECOVERABLE
 +        case CELT_INVALID_STATE:    return AVERROR(ENOTRECOVERABLE);
 +#endif
 +        case CELT_ALLOC_FAIL:       return AVERROR(ENOMEM);
 +        default:                    return AVERROR(EINVAL);
 +    }
 +}
 +
 +static int ff_celt_bitstream_version_hack(CELTMode *mode)
 +{
 +    CELTHeader header = { .version_id = 0 };
 +    celt_header_init(&header, mode, 960, 2);
 +    return header.version_id;
 +}
 +
 +static av_cold int libcelt_dec_init(AVCodecContext *c)
 +{
 +    struct libcelt_context *celt = c->priv_data;
 +    int err;
 +
 +    if (!c->channels || !c->frame_size ||
 +        c->frame_size > INT_MAX / sizeof(int16_t) / c->channels)
 +        return AVERROR(EINVAL);
 +    celt->mode = celt_mode_create(c->sample_rate, c->frame_size, &err);
 +    if (!celt->mode)
 +        return ff_celt_error_to_averror(err);
 +    celt->dec = celt_decoder_create_custom(celt->mode, c->channels, &err);
 +    if (!celt->dec) {
 +        celt_mode_destroy(celt->mode);
 +        return ff_celt_error_to_averror(err);
 +    }
 +    if (c->extradata_size >= 4) {
 +        celt->discard = AV_RL32(c->extradata);
 +        if (celt->discard < 0 || celt->discard >= c->frame_size) {
 +            av_log(c, AV_LOG_WARNING,
 +                   "Invalid overlap (%d), ignored.\n", celt->discard);
 +            celt->discard = 0;
 +        }
 +    }
 +    if (c->extradata_size >= 8) {
 +        unsigned version = AV_RL32(c->extradata + 4);
 +        unsigned lib_version = ff_celt_bitstream_version_hack(celt->mode);
 +        if (version != lib_version)
 +            av_log(c, AV_LOG_WARNING,
 +                   "CELT bitstream version 0x%x may be "
 +                   "improperly decoded by libcelt for version 0x%x.\n",
 +                   version, lib_version);
 +    }
 +    c->sample_fmt = AV_SAMPLE_FMT_S16;
 +    return 0;
 +}
 +
 +static av_cold int libcelt_dec_close(AVCodecContext *c)
 +{
 +    struct libcelt_context *celt = c->priv_data;
 +
 +    celt_decoder_destroy(celt->dec);
 +    celt_mode_destroy(celt->mode);
 +    return 0;
 +}
 +
 +static int libcelt_dec_decode(AVCodecContext *c, void *data,
 +                              int *got_frame_ptr, AVPacket *pkt)
 +{
 +    struct libcelt_context *celt = c->priv_data;
 +    AVFrame *frame = data;
 +    int err;
 +    int16_t *pcm;
 +
 +    frame->nb_samples = c->frame_size;
++    err = ff_get_buffer(c, frame, 0);
 +    if (err < 0) {
 +        av_log(c, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return err;
 +    }
 +    pcm = (int16_t *)frame->data[0];
 +    err = celt_decode(celt->dec, pkt->data, pkt->size, pcm, c->frame_size);
 +    if (err < 0)
 +        return ff_celt_error_to_averror(err);
 +    if (celt->discard) {
 +        frame->nb_samples -= celt->discard;
 +        memmove(pcm, pcm + celt->discard * c->channels,
 +                frame->nb_samples * c->channels * sizeof(int16_t));
 +        celt->discard = 0;
 +    }
 +    *got_frame_ptr = 1;
 +    return pkt->size;
 +}
 +
 +AVCodec ff_libcelt_decoder = {
 +    .name           = "libcelt",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_CELT,
 +    .priv_data_size = sizeof(struct libcelt_context),
 +    .init           = libcelt_dec_init,
 +    .close          = libcelt_dec_close,
 +    .decode         = libcelt_dec_decode,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Xiph CELT decoder using libcelt"),
 +};
Simple merge
Simple merge
@@@ -343,7 -344,7 +343,7 @@@ static int amr_wb_decode_frame(AVCodecC
  
      /* get output buffer */
      frame->nb_samples = 320;
--    if ((ret = ff_get_buffer(avctx, frame)) < 0) {
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
@@@ -67,7 -67,7 +67,6 @@@ static const enum AVPixelFormat libopen
  typedef struct {
      AVClass *class;
      opj_dparameters_t dec_params;
-     AVFrame image;
 -    int lowres;
      int lowqual;
  } LibOpenJPEGContext;
  
@@@ -425,11 -429,8 +402,9 @@@ AVCodec ff_libopenjpeg_decoder = 
      .id               = AV_CODEC_ID_JPEG2000,
      .priv_data_size   = sizeof(LibOpenJPEGContext),
      .init             = libopenjpeg_decode_init,
-     .close            = libopenjpeg_decode_close,
      .decode           = libopenjpeg_decode_frame,
      .capabilities     = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
 +    .max_lowres       = 31,
      .long_name        = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"),
      .priv_class       = &class,
-     .init_thread_copy = ONLY_IF_THREADS_ENABLED(libopenjpeg_decode_init_thread_copy),
  };
Simple merge
Simple merge
Simple merge
index 99fb83a,0000000..e54e4b3
mode 100644,000000..100644
--- /dev/null
@@@ -1,201 -1,0 +1,201 @@@
-     if ((ret = ff_get_buffer(avccontext, frame)) < 0) {
 +/*
 + * Copyright (c) 2002 Mark Hills <mark@pogo.org.uk>
 + *
 + * 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 <vorbis/vorbisenc.h>
 +
 +#include "avcodec.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +
 +typedef struct OggVorbisDecContext {
 +    vorbis_info vi;                     /**< vorbis_info used during init   */
 +    vorbis_dsp_state vd;                /**< DSP state used for analysis    */
 +    vorbis_block vb;                    /**< vorbis_block used for analysis */
 +    vorbis_comment vc;                  /**< VorbisComment info             */
 +    ogg_packet op;                      /**< ogg packet                     */
 +} OggVorbisDecContext;
 +
 +static int oggvorbis_decode_init(AVCodecContext *avccontext) {
 +    OggVorbisDecContext *context = avccontext->priv_data ;
 +    uint8_t *p= avccontext->extradata;
 +    int i, hsizes[3];
 +    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;
 +    }
 +
 +    if(p[0] == 0 && p[1] == 30) {
 +        for(i = 0; i < 3; i++){
 +            hsizes[i] = bytestream_get_be16((const uint8_t **)&p);
 +            headers[i] = p;
 +            p += hsizes[i];
 +        }
 +    } else if(*p == 2) {
 +        unsigned int offset = 1;
 +        p++;
 +        for(i=0; i<2; i++) {
 +            hsizes[i] = 0;
 +            while((*p == 0xFF) && (offset < avccontext->extradata_size)) {
 +                hsizes[i] += 0xFF;
 +                offset++;
 +                p++;
 +            }
 +            if(offset >= avccontext->extradata_size - 1) {
 +                av_log(avccontext, AV_LOG_ERROR,
 +                       "vorbis header sizes damaged\n");
 +                return -1;
 +            }
 +            hsizes[i] += *p;
 +            offset++;
 +            p++;
 +        }
 +        hsizes[2] = avccontext->extradata_size - hsizes[0]-hsizes[1]-offset;
 +#if 0
 +        av_log(avccontext, AV_LOG_DEBUG,
 +               "vorbis header sizes: %d, %d, %d, / extradata_len is %d \n",
 +               hsizes[0], hsizes[1], hsizes[2], avccontext->extradata_size);
 +#endif
 +        headers[0] = extradata + offset;
 +        headers[1] = extradata + offset + hsizes[0];
 +        headers[2] = extradata + offset + hsizes[0] + hsizes[1];
 +    } else {
 +        av_log(avccontext, AV_LOG_ERROR,
 +               "vorbis initial header len is wrong: %d\n", *p);
 +        return -1;
 +    }
 +
 +    for(i=0; i<3; i++){
 +        context->op.b_o_s= i==0;
 +        context->op.bytes = hsizes[i];
 +        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;
 +        }
 +    }
 +
 +    avccontext->channels = context->vi.channels;
 +    avccontext->sample_rate = context->vi.rate;
 +    avccontext->sample_fmt = AV_SAMPLE_FMT_S16;
 +    avccontext->time_base= (AVRational){1, avccontext->sample_rate};
 +
 +    vorbis_synthesis_init(&context->vd, &context->vi);
 +    vorbis_block_init(&context->vd, &context->vb);
 +
 +    return 0 ;
 +}
 +
 +
 +static inline int conv(int samples, float **pcm, char *buf, int channels) {
 +    int i, j;
 +    ogg_int16_t *ptr, *data = (ogg_int16_t*)buf ;
 +    float *mono ;
 +
 +    for(i = 0 ; i < channels ; i++){
 +        ptr = &data[i];
 +        mono = pcm[i] ;
 +
 +        for(j = 0 ; j < samples ; j++) {
 +            *ptr = av_clip_int16(mono[j] * 32767.f);
 +            ptr += channels;
 +        }
 +    }
 +
 +    return 0 ;
 +}
 +
 +static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data,
 +                        int *got_frame_ptr, AVPacket *avpkt)
 +{
 +    OggVorbisDecContext *context = avccontext->priv_data ;
 +    AVFrame *frame = data;
 +    float **pcm ;
 +    ogg_packet *op= &context->op;
 +    int samples, total_samples, total_bytes;
 +    int ret;
 +    int16_t *output;
 +
 +    if(!avpkt->size){
 +    //FIXME flush
 +        return 0;
 +    }
 +
 +    frame->nb_samples = 8192*4;
++    if ((ret = ff_get_buffer(avccontext, frame, 0)) < 0) {
 +        av_log(avccontext, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +    output = (int16_t *)frame->data[0];
 +
 +
 +    op->packet = avpkt->data;
 +    op->bytes  = avpkt->size;
 +
 +//    av_log(avccontext, AV_LOG_DEBUG, "%d %d %d %"PRId64" %"PRId64" %d %d\n", op->bytes, op->b_o_s, op->e_o_s, op->granulepos, op->packetno, buf_size, context->vi.rate);
 +
 +/*    for(i=0; i<op->bytes; i++)
 +      av_log(avccontext, AV_LOG_DEBUG, "%02X ", op->packet[i]);
 +    av_log(avccontext, AV_LOG_DEBUG, "\n");*/
 +
 +    if(vorbis_synthesis(&context->vb, op) == 0)
 +        vorbis_synthesis_blockin(&context->vd, &context->vb) ;
 +
 +    total_samples = 0 ;
 +    total_bytes = 0 ;
 +
 +    while((samples = vorbis_synthesis_pcmout(&context->vd, &pcm)) > 0) {
 +        conv(samples, pcm, (char*)output + total_bytes, context->vi.channels) ;
 +        total_bytes += samples * 2 * context->vi.channels ;
 +        total_samples += samples ;
 +        vorbis_synthesis_read(&context->vd, samples) ;
 +    }
 +
 +    frame->nb_samples = total_samples;
 +    *got_frame_ptr   = 1;
 +    return avpkt->size;
 +}
 +
 +
 +static int oggvorbis_decode_close(AVCodecContext *avccontext) {
 +    OggVorbisDecContext *context = avccontext->priv_data ;
 +
 +    vorbis_info_clear(&context->vi) ;
 +    vorbis_comment_clear(&context->vc) ;
 +
 +    return 0 ;
 +}
 +
 +
 +AVCodec ff_libvorbis_decoder = {
 +    .name           = "libvorbis",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_VORBIS,
 +    .priv_data_size = sizeof(OggVorbisDecContext),
 +    .init           = oggvorbis_decode_init,
 +    .decode         = oggvorbis_decode_frame,
 +    .close          = oggvorbis_decode_close,
 +    .capabilities   = CODEC_CAP_DELAY,
 +    .long_name      = NULL_IF_CONFIG_SMALL("libvorbis"),
 +};
Simple merge
@@@ -63,12 -61,12 +63,15 @@@ static int encode_picture_lossless(AVCo
          return ret;
      }
  
 +    if ((ret = ff_alloc_packet2(avctx, pkt, max_pkt_size)) < 0)
 +        return ret;
 +
      init_put_bits(&s->pb, pkt->data, pkt->size);
  
-     *p = *pict;
+     av_frame_unref(p);
+     ret = av_frame_ref(p, pict);
+     if (ret < 0)
+         return ret;
      p->pict_type= AV_PICTURE_TYPE_I;
      p->key_frame= 1;
  
@@@ -224,32 -230,33 +219,31 @@@ static int decode_frame(AVCodecContext 
          decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
                                      -p->linesize[0], buf, buf_size, 3);
          break;
 +    case LOCO_CRGBA:
      case LOCO_RGBA:
 -        decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
 -                                    p->linesize[0], buf, buf_size, 4);
 -        if (decoded >= buf_size)
 -            goto buf_too_small;
 -        buf += decoded; buf_size -= decoded;
 -
 -        decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height,
 -                                    p->linesize[0], buf, buf_size, 4);
 -        if (decoded >= buf_size)
 -            goto buf_too_small;
 -        buf += decoded; buf_size -= decoded;
 -
 -        decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height,
 -                                    p->linesize[0], buf, buf_size, 4);
 -        if (decoded >= buf_size)
 -            goto buf_too_small;
 -        buf += decoded; buf_size -= decoded;
 -
 -        decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height,
 -                                    p->linesize[0], buf, buf_size, 4);
 +        decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
 +                                    -p->linesize[0], buf, buf_size, 4);
 +        ADVANCE_BY_DECODED;
 +        decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
 +                                    -p->linesize[0], buf, buf_size, 4);
 +        ADVANCE_BY_DECODED;
 +        decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
 +                                    -p->linesize[0], buf, buf_size, 4);
 +        ADVANCE_BY_DECODED;
 +        decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height,
 +                                    -p->linesize[0], buf, buf_size, 4);
          break;
 +    default:
 +        av_assert0(0);
      }
  
 +    if (decoded < 0 || decoded > buf_size)
 +        goto buf_too_small;
 +    buf_size -= decoded;
 +
      *got_frame      = 1;
-     *(AVFrame*)data = l->pic;
  
 -    return buf_size;
 +    return avpkt->size - buf_size;
  buf_too_small:
      av_log(avctx, AV_LOG_ERROR, "Input data too small.\n");
      return AVERROR(EINVAL);
Simple merge
Simple merge
Simple merge
@@@ -136,22 -136,13 +136,18 @@@ read_header
  
      //XXX FIXME factorize, this looks very similar to the EOI code
  
-     *picture= *s->picture_ptr;
 +    if(!s->got_picture) {
 +        av_log(avctx, AV_LOG_WARNING, "no picture\n");
 +        return buf_size;
 +    }
 +
+     if ((ret = av_frame_ref(data, s->picture_ptr)) < 0)
+         return ret;
      *got_frame = 1;
  
-     if(!s->lossless){
-         picture->quality= FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]);
-         picture->qstride= 0;
-         picture->qscale_table= s->qscale_table;
-         memset(picture->qscale_table, picture->quality, (s->width+15)/16);
-         if(avctx->debug & FF_DEBUG_QP)
-             av_log(avctx, AV_LOG_DEBUG, "QP: %d\n", picture->quality);
-         picture->quality*= FF_QP2LAMBDA;
+     if (!s->lossless && avctx->debug & FF_DEBUG_QP) {
+         av_log(avctx, AV_LOG_DEBUG, "QP: %d\n",
+                FFMAX3(s->qscale[0], s->qscale[1], s->qscale[2]));
      }
  
      return buf_size;
@@@ -298,19 -274,15 +298,18 @@@ int ff_mjpeg_decode_sof(MJpegDecodeCont
          return AVERROR_PATCHWELCOME;
      }
  
 -    if (s->v_max == 1 && s->h_max == 1 && s->lossless == 1)
 -        s->rgb = 1;
  
      /* if different size, realloc/alloc picture */
 -    /* XXX: also check h_count and v_count */
 -    if (width != s->width || height != s->height) {
 +    if (   width != s->width || height != s->height
 +        || memcmp(s->h_count, h_count, sizeof(h_count))
 +        || memcmp(s->v_count, v_count, sizeof(v_count))) {
-         av_freep(&s->qscale_table);
 +
          s->width      = width;
          s->height     = height;
 +        memcpy(s->h_count, h_count, sizeof(h_count));
 +        memcpy(s->v_count, v_count, sizeof(v_count));
          s->interlaced = 0;
 +        s->got_picture = 0;
  
          /* test interlaced mode */
          if (s->first_picture   &&
@@@ -1638,10 -1446,9 +1634,9 @@@ int ff_mjpeg_decode_frame(AVCodecContex
      const uint8_t *unescaped_buf_ptr;
      int unescaped_buf_size;
      int start_code;
 +    int i, index;
      int ret = 0;
-     AVFrame *picture = data;
  
 -    s->got_picture = 0; // picture from previous image can not be reused
      buf_ptr = buf;
      buf_end = buf + buf_size;
      while (buf_ptr < buf_end) {
@@@ -1739,24 -1547,18 +1734,19 @@@ eoi_parser
                      s->bottom_field ^= 1;
                      /* if not bottom field, do not output image yet */
                      if (s->bottom_field == !s->interlace_polarity)
 -                        goto not_the_end;
 +                        break;
                  }
-                 *picture   = *s->picture_ptr;
+                 if ((ret = av_frame_ref(data, s->picture_ptr)) < 0)
+                     return ret;
                  *got_frame = 1;
 +                s->got_picture = 0;
  
-                 if (!s->lossless) {
-                     picture->quality      = FFMAX3(s->qscale[0],
-                                                    s->qscale[1],
-                                                    s->qscale[2]);
-                     picture->qstride      = 0;
-                     picture->qscale_table = s->qscale_table;
-                     memset(picture->qscale_table, picture->quality,
-                            (s->width + 15) / 16);
-                     if (avctx->debug & FF_DEBUG_QP)
-                         av_log(avctx, AV_LOG_DEBUG,
-                                "QP: %d\n", picture->quality);
-                     picture->quality *= FF_QP2LAMBDA;
+                 if (!s->lossless &&
+                     avctx->debug & FF_DEBUG_QP) {
+                     av_log(avctx, AV_LOG_DEBUG,
+                            "QP: %d\n", FFMAX3(s->qscale[0],
+                                               s->qscale[1],
+                                               s->qscale[2]));
                  }
  
                  goto the_end;
Simple merge
@@@ -60,9 -61,6 +61,7 @@@ static av_cold int mm_decode_init(AVCod
  
      avctx->pix_fmt = AV_PIX_FMT_PAL8;
  
-     s->frame.reference = 3;
 +    avcodec_get_frame_defaults(&s->frame);
      return 0;
  }
  
@@@ -210,10 -208,12 +209,12 @@@ static int mm_decode_frame(AVCodecConte
  
      memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
  
+     if ((res = av_frame_ref(data, &s->frame)) < 0)
+         return res;
      *got_frame      = 1;
-     *(AVFrame*)data = s->frame;
  
 -    return buf_size;
 +    return avpkt->size;
  }
  
  static av_cold int mm_decode_end(AVCodecContext *avctx)
@@@ -581,13 -576,8 +581,13 @@@ static inline int h263_mv4_search(MpegE
          const int mot_stride = s->b8_stride;
          const int mot_xy = s->block_index[block];
  
-         P_LEFT[0] = s->current_picture.f.motion_val[0][mot_xy - 1][0];
-         P_LEFT[1] = s->current_picture.f.motion_val[0][mot_xy - 1][1];
 +        if(saftey_cliping){
 +            c->xmax = - 16*s->mb_x + s->width  - 8*(block &1);
 +            c->ymax = - 16*s->mb_y + s->height - 8*(block>>1);
 +        }
 +
+         P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
+         P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
  
          if(P_LEFT[0]       > (c->xmax<<shift)) P_LEFT[0]       = (c->xmax<<shift);
  
Simple merge
@@@ -224,8 -228,8 +224,8 @@@ static int mpc7_decode_frame(AVCodecCon
      buf_size  -= 4;
  
      /* get output buffer */
 -    frame->nb_samples = last_frame ? c->lastframelen : MPC_FRAME_SIZE;
 +    frame->nb_samples = MPC_FRAME_SIZE;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
Simple merge
@@@ -768,16 -751,14 +768,17 @@@ static int mpeg_decode_mb(MpegEncContex
              int mb_type;
  
              if (s->mb_x)
-                 mb_type = s->current_picture.f.mb_type[s->mb_x + s->mb_y * s->mb_stride - 1];
+                 mb_type = s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride - 1];
              else
-                 mb_type = s->current_picture.f.mb_type[s->mb_width + (s->mb_y - 1) * s->mb_stride - 1]; // FIXME not sure if this is allowed in MPEG at all
+                 mb_type = s->current_picture.mb_type[s->mb_width + (s->mb_y - 1) * s->mb_stride - 1]; // FIXME not sure if this is allowed in MPEG at all
 -            if (IS_INTRA(mb_type))
 +            if (IS_INTRA(mb_type)) {
 +                av_log(s->avctx, AV_LOG_ERROR, "skip with previntra\n");
                  return -1;
-             s->current_picture.f.mb_type[s->mb_x + s->mb_y*s->mb_stride] =
 +            }
+             s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride] =
                  mb_type | MB_TYPE_SKIP;
- //            av_assert2(s->current_picture.f.mb_type[s->mb_x + s->mb_y * s->mb_stride - 1] & (MB_TYPE_16x16 | MB_TYPE_16x8));
++
+ //            assert(s->current_picture.mb_type[s->mb_x + s->mb_y * s->mb_stride - 1] & (MB_TYPE_16x16 | MB_TYPE_16x8));
  
              if ((s->mv[0][0][0] | s->mv[0][0][1] | s->mv[1][0][0] | s->mv[1][0][1]) == 0)
                  s->mb_skipped = 1;
@@@ -1788,13 -1761,13 +1796,13 @@@ static int mpeg_decode_slice(MpegEncCon
                          motion_y = s->mv[dir][i][1];
                      }
  
-                     s->current_picture.f.motion_val[dir][xy    ][0] = motion_x;
-                     s->current_picture.f.motion_val[dir][xy    ][1] = motion_y;
-                     s->current_picture.f.motion_val[dir][xy + 1][0] = motion_x;
-                     s->current_picture.f.motion_val[dir][xy + 1][1] = motion_y;
-                     s->current_picture.f.ref_index [dir][b8_xy    ] =
-                     s->current_picture.f.ref_index [dir][b8_xy + 1] = s->field_select[dir][i];
+                     s->current_picture.motion_val[dir][xy    ][0] = motion_x;
+                     s->current_picture.motion_val[dir][xy    ][1] = motion_y;
+                     s->current_picture.motion_val[dir][xy + 1][0] = motion_x;
+                     s->current_picture.motion_val[dir][xy + 1][1] = motion_y;
+                     s->current_picture.ref_index [dir][b8_xy    ] =
+                     s->current_picture.ref_index [dir][b8_xy + 1] = s->field_select[dir][i];
 -                    assert(s->field_select[dir][i] == 0 || s->field_select[dir][i] == 1);
 +                    av_assert2(s->field_select[dir][i] == 0 || s->field_select[dir][i] == 1);
                  }
                  xy += wrap;
                  b8_xy +=2;
@@@ -1970,11 -1931,9 +1978,9 @@@ static int slice_end(AVCodecContext *av
          ff_xvmc_field_end(s);
  
      /* end of slice reached */
 -    if (/*s->mb_y << field_pic == s->mb_height &&*/ !s->first_field) {
 +    if (/*s->mb_y << field_pic == s->mb_height &&*/ !s->first_field && !s->first_slice) {
          /* end of image */
  
-         s->current_picture_ptr->f.qscale_type = FF_QSCALE_TYPE_MPEG2;
          ff_er_frame_end(&s->er);
  
          ff_MPV_frame_end(s);
@@@ -2287,11 -2236,13 +2297,13 @@@ static int decode_chunks(AVCodecContex
                          s2->er.error_count += s2->thread_context[i]->er.error_count;
                  }
  
 -                if (CONFIG_MPEG_VDPAU_DECODER && avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
 +                if (CONFIG_VDPAU && uses_vdpau(avctx))
                      ff_vdpau_mpeg_picture_complete(s2, buf, buf_size, s->slice_count);
  
-                 if (slice_end(avctx, picture)) {
+                 ret = slice_end(avctx, picture);
+                 if (ret < 0)
+                     return ret;
+                 else if (ret) {
                      if (s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice
                          *got_output = 1;
                  }
Simple merge
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 +#define UNCHECKED_BITSTREAM_READER 1
 +
 +#include "libavutil/opt.h"
  #include "error_resilience.h"
+ #include "internal.h"
  #include "mpegvideo.h"
  #include "mpeg4video.h"
  #include "h263.h"
  
          /* per-MB end of slice check */
      if(s->codec_id==AV_CODEC_ID_MPEG4){
 -        if(mpeg4_is_resync(s)){
 -            const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1;
 +        int next= mpeg4_is_resync(s);
 +        if(next) {
 +            if        (s->mb_x + s->mb_y*s->mb_width + 1 >  next && (s->avctx->err_recognition & AV_EF_AGGRESSIVE)) {
 +                return -1;
 +            } else if (s->mb_x + s->mb_y*s->mb_width + 1 >= next)
 +                return SLICE_END;
  
 -            if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture.mbskip_table[xy + delta]) {
 +            if(s->pict_type==AV_PICTURE_TYPE_B){
 +                const int delta= s->mb_x + 1 == s->mb_width ? 2 : 1;
-                 ff_thread_await_progress(&s->next_picture_ptr->f,
+                 ff_thread_await_progress(&s->next_picture_ptr->tf,
                                          (s->mb_x + delta >= s->mb_width) ? FFMIN(s->mb_y+1, s->mb_height-1) : s->mb_y, 0);
-                 if (s->next_picture.f.mbskip_table[xy + delta])
++                if (s->next_picture.mbskip_table[xy + delta])
 +                    return SLICE_OK;
              }
  
 -            if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture.mbskip_table[xy + delta])
 -                return SLICE_OK;
              return SLICE_END;
          }
      }
@@@ -494,12 -494,12 +494,12 @@@ void ff_mpeg4_encode_mb(MpegEncContext 
                  }
              }
  
 -            assert(s->dquant>=-2 && s->dquant<=2);
 -            assert((s->dquant&1)==0);
 -            assert(mb_type>=0);
 +            av_assert2(s->dquant>=-2 && s->dquant<=2);
 +            av_assert2((s->dquant&1)==0);
 +            av_assert2(mb_type>=0);
  
              /* nothing to do if this MB was skipped in the next P Frame */
-             if (s->next_picture.f.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]) { //FIXME avoid DCT & ...
+             if (s->next_picture.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]) { //FIXME avoid DCT & ...
                  s->skip_count++;
                  s->mv[0][0][0]=
                  s->mv[0][0][1]=
                              break;
  
                          b_pic = pic->f.data[0] + offset;
-                         if (pic->f.type != FF_BUFFER_TYPE_SHARED)
+                         if (!pic->shared)
                              b_pic+= INPLACE_OFFSET;
 -                        diff= s->dsp.sad[0](NULL, p_pic, b_pic, s->linesize, 16);
 +
 +                        if(x+16 > s->width || y+16 > s->height){
 +                            int x1,y1;
 +                            int xe= FFMIN(16, s->width - x);
 +                            int ye= FFMIN(16, s->height- y);
 +                            diff=0;
 +                            for(y1=0; y1<ye; y1++){
 +                                for(x1=0; x1<xe; x1++){
 +                                    diff+= FFABS(p_pic[x1+y1*s->linesize] - b_pic[x1+y1*s->linesize]);
 +                                }
 +                            }
 +                            diff= diff*256/(xe*ye);
 +                        }else{
 +                            diff= s->dsp.sad[0](NULL, p_pic, b_pic, s->linesize, 16);
 +                        }
                          if(diff>s->qscale*70){ //FIXME check that 70 is optimal
                              s->mb_skipped=0;
                              break;
Simple merge
@@@ -232,32 -234,9 +233,9 @@@ av_cold int ff_dct_common_init(MpegEncC
      return 0;
  }
  
- void ff_copy_picture(Picture *dst, Picture *src)
- {
-     *dst = *src;
-     dst->f.type = FF_BUFFER_TYPE_COPY;
- }
- /**
-  * Release a frame buffer
-  */
- static void free_frame_buffer(MpegEncContext *s, Picture *pic)
- {
-     pic->period_since_free = 0;
-     /* WM Image / Screen codecs allocate internal buffers with different
-      * dimensions / colorspaces; ignore user-defined callbacks for these. */
-     if (s->codec_id != AV_CODEC_ID_WMV3IMAGE &&
-         s->codec_id != AV_CODEC_ID_VC1IMAGE  &&
-         s->codec_id != AV_CODEC_ID_MSS2)
-         ff_thread_release_buffer(s->avctx, &pic->f);
-     else
-         avcodec_default_release_buffer(s->avctx, &pic->f);
-     av_freep(&pic->hwaccel_picture_private);
- }
  int ff_mpv_frame_size_alloc(MpegEncContext *s, int linesize)
  {
 -    int alloc_size = FFALIGN(FFABS(linesize) + 32, 32);
 +    int alloc_size = FFALIGN(FFABS(linesize) + 64, 32);
  
      // edge emu needs blocksize + filter length - 1
      // (= 17x17 for  halfpel / 21x21 for  h264)
@@@ -431,38 -460,103 +459,104 @@@ fail
  /**
   * Deallocate a picture.
   */
static void free_picture(MpegEncContext *s, Picture *pic)
void ff_mpeg_unref_picture(MpegEncContext *s, Picture *pic)
  {
-     int i;
+     int off = offsetof(Picture, mb_mean) + sizeof(pic->mb_mean);
++    pic->period_since_free = 0;
  
-     if (pic->f.data[0] && pic->f.type != FF_BUFFER_TYPE_SHARED) {
-         free_frame_buffer(s, pic);
-     }
-     av_freep(&pic->mb_var);
-     av_freep(&pic->mc_mb_var);
-     av_freep(&pic->mb_mean);
-     av_freep(&pic->f.mbskip_table);
-     av_freep(&pic->qscale_table_base);
-     pic->f.qscale_table = NULL;
-     av_freep(&pic->mb_type_base);
-     pic->f.mb_type = NULL;
-     av_freep(&pic->f.dct_coeff);
-     av_freep(&pic->f.pan_scan);
-     pic->f.mb_type = NULL;
+     pic->tf.f = &pic->f;
+     /* WM Image / Screen codecs allocate internal buffers with different
+      * dimensions / colorspaces; ignore user-defined callbacks for these. */
+     if (s->codec_id != AV_CODEC_ID_WMV3IMAGE &&
+         s->codec_id != AV_CODEC_ID_VC1IMAGE  &&
+         s->codec_id != AV_CODEC_ID_MSS2)
+         ff_thread_release_buffer(s->avctx, &pic->tf);
+     else
+         av_frame_unref(&pic->f);
+     av_buffer_unref(&pic->hwaccel_priv_buf);
+     memset((uint8_t*)pic + off, 0, sizeof(*pic) - off);
+ }
+ static int update_picture_tables(Picture *dst, Picture *src)
+ {
+      int i;
+ #define UPDATE_TABLE(table)\
+ do {\
+     if (src->table &&\
+         (!dst->table || dst->table->buffer != src->table->buffer)) {\
+         av_buffer_unref(&dst->table);\
+         dst->table = av_buffer_ref(src->table);\
+         if (!dst->table) {\
+             free_picture_tables(dst);\
+             return AVERROR(ENOMEM);\
+         }\
+     }\
+ } while (0)
+     UPDATE_TABLE(mb_var_buf);
+     UPDATE_TABLE(mc_mb_var_buf);
+     UPDATE_TABLE(mb_mean_buf);
+     UPDATE_TABLE(mbskip_table_buf);
+     UPDATE_TABLE(qscale_table_buf);
+     UPDATE_TABLE(mb_type_buf);
      for (i = 0; i < 2; i++) {
-         av_freep(&pic->motion_val_base[i]);
-         av_freep(&pic->f.ref_index[i]);
-         pic->f.motion_val[i] = NULL;
+         UPDATE_TABLE(motion_val_buf[i]);
+         UPDATE_TABLE(ref_index_buf[i]);
      }
  
-     if (pic->f.type == FF_BUFFER_TYPE_SHARED) {
-         for (i = 0; i < 4; i++) {
-             pic->f.base[i] =
-             pic->f.data[i] = NULL;
-         }
-         pic->f.type = 0;
+     dst->mb_var        = src->mb_var;
+     dst->mc_mb_var     = src->mc_mb_var;
+     dst->mb_mean       = src->mb_mean;
+     dst->mbskip_table  = src->mbskip_table;
+     dst->qscale_table  = src->qscale_table;
+     dst->mb_type       = src->mb_type;
+     for (i = 0; i < 2; i++) {
+         dst->motion_val[i] = src->motion_val[i];
+         dst->ref_index[i]  = src->ref_index[i];
      }
+     return 0;
+ }
+ int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src)
+ {
+     int ret;
+     av_assert0(!dst->f.buf[0]);
+     av_assert0(src->f.buf[0]);
+     src->tf.f = &src->f;
+     dst->tf.f = &dst->f;
+     ret = ff_thread_ref_frame(&dst->tf, &src->tf);
+     if (ret < 0)
+         goto fail;
+     ret = update_picture_tables(dst, src);
+     if (ret < 0)
+         goto fail;
+     if (src->hwaccel_picture_private) {
+         dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
+         if (!dst->hwaccel_priv_buf)
+             goto fail;
+         dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
+     }
+     dst->field_picture           = src->field_picture;
+     dst->mb_var_sum              = src->mb_var_sum;
+     dst->mc_mb_var_sum           = src->mc_mb_var_sum;
+     dst->b_frame_score           = src->b_frame_score;
+     dst->needs_realloc           = src->needs_realloc;
+     dst->reference               = src->reference;
+     dst->shared                  = src->shared;
+     return 0;
+ fail:
+     ff_mpeg_unref_picture(s, dst);
+     return ret;
  }
  
  static int init_duplicate_context(MpegEncContext *s)
@@@ -583,15 -677,12 +677,14 @@@ int ff_update_duplicate_context(MpegEnc
  int ff_mpeg_update_thread_context(AVCodecContext *dst,
                                    const AVCodecContext *src)
  {
-     int i;
-     int err;
+     int i, ret;
      MpegEncContext *s = dst->priv_data, *s1 = src->priv_data;
  
 -    if (dst == src || !s1->context_initialized)
 +    if (dst == src)
          return 0;
  
 +    av_assert0(s != s1);
 +
      // FIXME can parameters change on I-frames?
      // in that case dst may need a reinit
      if (!s->context_initialized) {
          s->bitstream_buffer      = NULL;
          s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0;
  
 -        ff_MPV_common_init(s);
 +        if (s1->context_initialized){
-             s->picture_range_start  += MAX_PICTURE_COUNT;
-             s->picture_range_end    += MAX_PICTURE_COUNT;
-             if((err = ff_MPV_common_init(s)) < 0){
++//             s->picture_range_start  += MAX_PICTURE_COUNT;
++//             s->picture_range_end    += MAX_PICTURE_COUNT;
++            if((ret = ff_MPV_common_init(s)) < 0){
 +                memset(s, 0, sizeof(MpegEncContext));
 +                s->avctx = dst;
-                 return err;
++                return ret;
 +            }
 +        }
      }
  
      if (s->height != s1->height || s->width != s1->width || s->context_reinit) {
          s->context_reinit = 0;
          s->height = s1->height;
          s->width  = s1->width;
--        if ((err = ff_MPV_common_frame_size_change(s)) < 0)
--            return err;
++        if ((ret = ff_MPV_common_frame_size_change(s)) < 0)
++            return ret;
      }
  
      s->avctx->coded_height  = s1->avctx->coded_height;
      s->picture_number       = s1->picture_number;
      s->input_picture_number = s1->input_picture_number;
  
-     memcpy(s->picture, s1->picture, s1->picture_count * sizeof(Picture));
-     memcpy(&s->last_picture, &s1->last_picture,
-            (char *) &s1->last_picture_ptr - (char *) &s1->last_picture);
-     // reset s->picture[].f.extended_data to s->picture[].f.data
-     for (i = 0; i < s->picture_count; i++) {
-         s->picture[i].f.extended_data = s->picture[i].f.data;
 +    av_assert0(!s->picture || s->picture != s1->picture);
+     for (i = 0; i < MAX_PICTURE_COUNT; i++) {
+         ff_mpeg_unref_picture(s, &s->picture[i]);
+         if (s1->picture[i].f.data[0] &&
+             (ret = ff_mpeg_ref_picture(s, &s->picture[i], &s1->picture[i])) < 0)
+             return ret;
 +        s->picture[i].period_since_free ++;
      }
  
+ #define UPDATE_PICTURE(pic)\
+ do {\
+     ff_mpeg_unref_picture(s, &s->pic);\
+     if (s1->pic.f.data[0])\
+         ret = ff_mpeg_ref_picture(s, &s->pic, &s1->pic);\
+     else\
+         ret = update_picture_tables(&s->pic, &s1->pic);\
+     if (ret < 0)\
+         return ret;\
+ } while (0)
+     UPDATE_PICTURE(current_picture);
+     UPDATE_PICTURE(last_picture);
+     UPDATE_PICTURE(next_picture);
      s->last_picture_ptr    = REBASE_PICTURE(s1->last_picture_ptr,    s, s1);
      s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1);
      s->next_picture_ptr    = REBASE_PICTURE(s1->next_picture_ptr,    s, s1);
@@@ -978,13 -1109,19 +1081,18 @@@ av_cold int ff_MPV_common_init(MpegEncC
          }
      }
  
-     s->picture_count = MAX_PICTURE_COUNT * FFMAX(1, s->avctx->thread_count);
      FF_ALLOCZ_OR_GOTO(s->avctx, s->picture,
-                       s->picture_count * sizeof(Picture), fail);
-     for (i = 0; i < s->picture_count; i++) {
+                       MAX_PICTURE_COUNT * sizeof(Picture), fail);
+     for (i = 0; i < MAX_PICTURE_COUNT; i++) {
          avcodec_get_frame_defaults(&s->picture[i].f);
      }
+     memset(&s->next_picture, 0, sizeof(s->next_picture));
+     memset(&s->last_picture, 0, sizeof(s->last_picture));
+     memset(&s->current_picture, 0, sizeof(s->current_picture));
+     avcodec_get_frame_defaults(&s->next_picture.f);
+     avcodec_get_frame_defaults(&s->last_picture.f);
+     avcodec_get_frame_defaults(&s->current_picture.f);
  
 -    if (s->width && s->height) {
          if (init_context_frame(s))
              goto fail;
  
@@@ -1317,15 -1455,10 +1430,14 @@@ void ff_release_unused_pictures(MpegEnc
  
  static inline int pic_is_unused(MpegEncContext *s, Picture *pic)
  {
 +    if (   (s->avctx->active_thread_type & FF_THREAD_FRAME)
 +        && pic->f.qscale_table //check if the frame has anything allocated
 +        && pic->period_since_free < s->avctx->thread_count)
 +        return 0;
      if (pic->f.data[0] == NULL)
          return 1;
-     if (pic->needs_realloc && !(pic->f.reference & DELAYED_PIC_REF))
-         if (!pic->owner2 || pic->owner2 == s)
-             return 1;
+     if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF))
+         return 1;
      return 0;
  }
  
@@@ -1542,14 -1653,8 +1652,12 @@@ int ff_MPV_frame_start(MpegEncContext *
                     (avctx->height >> v_chroma_shift) *
                     s->last_picture_ptr->f.linesize[2]);
  
-             ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 0);
-             ff_thread_report_progress(&s->last_picture_ptr->f, INT_MAX, 1);
-             s->last_picture_ptr->f.reference = 3;
 +            if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){
 +                for(i=0; i<avctx->height; i++)
 +                    memset(s->last_picture_ptr->f.data[0] + s->last_picture_ptr->f.linesize[0]*i, 16, avctx->width);
 +            }
+             ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0);
+             ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1);
          }
          if ((s->next_picture_ptr == NULL ||
               s->next_picture_ptr->f.data[0] == NULL) &&
          }
      }
  
-     if (s->last_picture_ptr)
-         ff_copy_picture(&s->last_picture, s->last_picture_ptr);
-     if (s->next_picture_ptr)
-         ff_copy_picture(&s->next_picture, s->next_picture_ptr);
++#if 0 // BUFREF-FIXME
 +    memset(s->last_picture.f.data, 0, sizeof(s->last_picture.f.data));
 +    memset(s->next_picture.f.data, 0, sizeof(s->next_picture.f.data));
++#endif
+     if (s->codec_id != AV_CODEC_ID_H264) {
+         if (s->last_picture_ptr) {
+             ff_mpeg_unref_picture(s, &s->last_picture);
+             if (s->last_picture_ptr->f.data[0] &&
+                 (ret = ff_mpeg_ref_picture(s, &s->last_picture,
+                                            s->last_picture_ptr)) < 0)
+                 return ret;
+         }
+         if (s->next_picture_ptr) {
+             ff_mpeg_unref_picture(s, &s->next_picture);
+             if (s->next_picture_ptr->f.data[0] &&
+                 (ret = ff_mpeg_ref_picture(s, &s->next_picture,
+                                            s->next_picture_ptr)) < 0)
+                 return ret;
+         }
  
-     if (HAVE_THREADS && (avctx->active_thread_type & FF_THREAD_FRAME)) {
-         if (s->next_picture_ptr)
-             s->next_picture_ptr->owner2 = s;
-         if (s->last_picture_ptr)
-             s->last_picture_ptr->owner2 = s;
+         assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr &&
+                                                      s->last_picture_ptr->f.data[0]));
      }
  
-     assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr &&
-                                                  s->last_picture_ptr->f.data[0]));
      if (s->picture_structure!= PICT_FRAME && s->out_format != FMT_H264) {
          int i;
          for (i = 0; i < 4; i++) {
@@@ -1642,26 -1748,24 +1756,26 @@@ void ff_MPV_frame_end(MpegEncContext *s
                !s->avctx->hwaccel &&
                !(s->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU) &&
                s->unrestricted_mv &&
-               s->current_picture.f.reference &&
+               s->current_picture.reference &&
                !s->intra_only &&
 -              !(s->flags & CODEC_FLAG_EMU_EDGE)) {
 -       const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt);
 -       int hshift = desc->log2_chroma_w;
 -       int vshift = desc->log2_chroma_h;
 -       s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize,
 -                         s->h_edge_pos, s->v_edge_pos,
 -                         EDGE_WIDTH, EDGE_WIDTH,
 -                         EDGE_TOP | EDGE_BOTTOM);
 -       s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize,
 -                         s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
 -                         EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
 -                         EDGE_TOP | EDGE_BOTTOM);
 -       s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize,
 -                         s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
 -                         EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
 -                         EDGE_TOP | EDGE_BOTTOM);
 +              !(s->flags & CODEC_FLAG_EMU_EDGE) &&
 +              !s->avctx->lowres
 +            ) {
 +        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt);
 +        int hshift = desc->log2_chroma_w;
 +        int vshift = desc->log2_chroma_h;
 +        s->dsp.draw_edges(s->current_picture.f.data[0], s->current_picture.f.linesize[0],
 +                          s->h_edge_pos, s->v_edge_pos,
 +                          EDGE_WIDTH, EDGE_WIDTH,
 +                          EDGE_TOP | EDGE_BOTTOM);
 +        s->dsp.draw_edges(s->current_picture.f.data[1], s->current_picture.f.linesize[1],
 +                          s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
 +                          EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
 +                          EDGE_TOP | EDGE_BOTTOM);
 +        s->dsp.draw_edges(s->current_picture.f.data[2], s->current_picture.f.linesize[2],
 +                          s->h_edge_pos >> hshift, s->v_edge_pos >> vshift,
 +                          EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
 +                          EDGE_TOP | EDGE_BOTTOM);
      }
  
      emms_c();
@@@ -1795,60 -1896,77 +1906,62 @@@ static void draw_arrow(uint8_t *buf, in
  /**
   * Print debugging info for the given picture.
   */
- void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table,
 -void ff_print_debug_info(MpegEncContext *s, Picture *p)
++void ff_print_debug_info2(AVCodecContext *avctx, Picture *p, uint8_t *mbskip_table,
 +                         uint8_t *visualization_buffer[3], int *low_delay,
 +                         int mb_width, int mb_height, int mb_stride, int quarter_sample)
  {
-     if (   avctx->hwaccel || !pict || !pict->mb_type
+     AVFrame *pict;
 -    if (s->avctx->hwaccel || !p || !p->mb_type)
++    if (avctx->hwaccel || !p || !p->mb_type
 +        || (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU))
          return;
+     pict = &p->f;
  
 -    if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
 +
 +    if (avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
          int x,y;
  
 -        av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
 -        switch (pict->pict_type) {
 -        case AV_PICTURE_TYPE_I:
 -            av_log(s->avctx,AV_LOG_DEBUG,"I\n");
 -            break;
 -        case AV_PICTURE_TYPE_P:
 -            av_log(s->avctx,AV_LOG_DEBUG,"P\n");
 -            break;
 -        case AV_PICTURE_TYPE_B:
 -            av_log(s->avctx,AV_LOG_DEBUG,"B\n");
 -            break;
 -        case AV_PICTURE_TYPE_S:
 -            av_log(s->avctx,AV_LOG_DEBUG,"S\n");
 -            break;
 -        case AV_PICTURE_TYPE_SI:
 -            av_log(s->avctx,AV_LOG_DEBUG,"SI\n");
 -            break;
 -        case AV_PICTURE_TYPE_SP:
 -            av_log(s->avctx,AV_LOG_DEBUG,"SP\n");
 -            break;
 -        }
 -        for (y = 0; y < s->mb_height; y++) {
 -            for (x = 0; x < s->mb_width; x++) {
 -                if (s->avctx->debug & FF_DEBUG_SKIP) {
 -                    int count = s->mbskip_table[x + y * s->mb_stride];
 +        av_log(avctx, AV_LOG_DEBUG, "New frame, type: %c\n",
 +               av_get_picture_type_char(pict->pict_type));
 +        for (y = 0; y < mb_height; y++) {
 +            for (x = 0; x < mb_width; x++) {
 +                if (avctx->debug & FF_DEBUG_SKIP) {
 +                    int count = mbskip_table[x + y * mb_stride];
                      if (count > 9)
                          count = 9;
 -                    av_log(s->avctx, AV_LOG_DEBUG, "%1d", count);
 +                    av_log(avctx, AV_LOG_DEBUG, "%1d", count);
                  }
 -                if (s->avctx->debug & FF_DEBUG_QP) {
 -                    av_log(s->avctx, AV_LOG_DEBUG, "%2d",
 -                           p->qscale_table[x + y * s->mb_stride]);
 +                if (avctx->debug & FF_DEBUG_QP) {
 +                    av_log(avctx, AV_LOG_DEBUG, "%2d",
-                            pict->qscale_table[x + y * mb_stride]);
++                           p->qscale_table[x + y * mb_stride]);
                  }
 -                if (s->avctx->debug & FF_DEBUG_MB_TYPE) {
 -                    int mb_type = p->mb_type[x + y * s->mb_stride];
 +                if (avctx->debug & FF_DEBUG_MB_TYPE) {
-                     int mb_type = pict->mb_type[x + y * mb_stride];
++                    int mb_type = p->mb_type[x + y * mb_stride];
                      // Type & MV direction
                      if (IS_PCM(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "P");
 +                        av_log(avctx, AV_LOG_DEBUG, "P");
                      else if (IS_INTRA(mb_type) && IS_ACPRED(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "A");
 +                        av_log(avctx, AV_LOG_DEBUG, "A");
                      else if (IS_INTRA4x4(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "i");
 +                        av_log(avctx, AV_LOG_DEBUG, "i");
                      else if (IS_INTRA16x16(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "I");
 +                        av_log(avctx, AV_LOG_DEBUG, "I");
                      else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "d");
 +                        av_log(avctx, AV_LOG_DEBUG, "d");
                      else if (IS_DIRECT(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "D");
 +                        av_log(avctx, AV_LOG_DEBUG, "D");
                      else if (IS_GMC(mb_type) && IS_SKIP(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "g");
 +                        av_log(avctx, AV_LOG_DEBUG, "g");
                      else if (IS_GMC(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "G");
 +                        av_log(avctx, AV_LOG_DEBUG, "G");
                      else if (IS_SKIP(mb_type))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "S");
 +                        av_log(avctx, AV_LOG_DEBUG, "S");
                      else if (!USES_LIST(mb_type, 1))
 -                        av_log(s->avctx, AV_LOG_DEBUG, ">");
 +                        av_log(avctx, AV_LOG_DEBUG, ">");
                      else if (!USES_LIST(mb_type, 0))
 -                        av_log(s->avctx, AV_LOG_DEBUG, "<");
 +                        av_log(avctx, AV_LOG_DEBUG, "<");
                      else {
 -                        assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
 -                        av_log(s->avctx, AV_LOG_DEBUG, "X");
 +                        av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
 +                        av_log(avctx, AV_LOG_DEBUG, "X");
                      }
  
                      // segmentation
          uint8_t *ptr;
          int i;
          int h_chroma_shift, v_chroma_shift, block_height;
 -        const int width          = s->avctx->width;
 -        const int height         = s->avctx->height;
 +        const int width          = avctx->width;
 +        const int height         = avctx->height;
          const int mv_sample_log2 = 4 - pict->motion_subsample_log2;
 -        const int mv_stride      = (s->mb_width << mv_sample_log2) +
 -                                   (s->codec_id == AV_CODEC_ID_H264 ? 0 : 1);
 -        s->low_delay = 0; // needed to see the vectors without trashing the buffers
 +        const int mv_stride      = (mb_width << mv_sample_log2) +
 +                                   (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1);
 +        *low_delay = 0; // needed to see the vectors without trashing the buffers
 +
 +        avcodec_get_chroma_sub_sample(avctx->pix_fmt, &h_chroma_shift, &v_chroma_shift);
  
 -        av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt,
 -                                         &h_chroma_shift, &v_chroma_shift);
          for (i = 0; i < 3; i++) {
 -            memcpy(s->visualization_buffer[i], pict->data[i],
 -                   (i == 0) ? pict->linesize[i] * height:
 -                              pict->linesize[i] * height >> v_chroma_shift);
 -            pict->data[i] = s->visualization_buffer[i];
 +            size_t size= (i == 0) ? pict->linesize[i] * FFALIGN(height, 16):
 +                         pict->linesize[i] * FFALIGN(height, 16) >> v_chroma_shift;
 +            visualization_buffer[i]= av_realloc(visualization_buffer[i], size);
 +            memcpy(visualization_buffer[i], pict->data[i], size);
 +            pict->data[i] = visualization_buffer[i];
          }
-         pict->type   = FF_BUFFER_TYPE_COPY;
-         pict->opaque= NULL;
++        pict->opaque = NULL;
          ptr          = pict->data[0];
          block_height = 16 >> v_chroma_shift;
  
 -        for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
 +        for (mb_y = 0; mb_y < mb_height; mb_y++) {
              int mb_x;
 -            for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
 -                const int mb_index = mb_x + mb_y * s->mb_stride;
 -                if ((s->avctx->debug_mv) && p->motion_val) {
 +            for (mb_x = 0; mb_x < mb_width; mb_x++) {
 +                const int mb_index = mb_x + mb_y * mb_stride;
-                 if ((avctx->debug_mv) && pict->motion_val[0]) {
++                if ((avctx->debug_mv) && p->motion_val[0]) {
                      int type;
                      for (type = 0; type < 3; type++) {
                          int direction = 0;
                                  int sy = mb_y * 16 + 4 + 8 * (i >> 1);
                                  int xy = (mb_x * 2 + (i & 1) +
                                            (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1);
-                                 int mx = (pict->motion_val[direction][xy][0] >> shift) + sx;
-                                 int my = (pict->motion_val[direction][xy][1] >> shift) + sy;
+                                 int mx = (p->motion_val[direction][xy][0] >> shift) + sx;
+                                 int my = (p->motion_val[direction][xy][1] >> shift) + sy;
                                  draw_arrow(ptr, sx, sy, mx, my, width,
 -                                           height, s->linesize, 100);
 +                                           height, pict->linesize[0], 100);
                              }
-                         } else if (IS_16X8(pict->mb_type[mb_index])) {
+                         } else if (IS_16X8(p->mb_type[mb_index])) {
                              int i;
                              for (i = 0; i < 2; i++) {
                                  int sx = mb_x * 16 + 8;
                                      my *= 2;
  
                              draw_arrow(ptr, sx, sy, mx + sx, my + sy, width,
 -                                       height, s->linesize, 100);
 +                                       height, pict->linesize[0], 100);
                              }
-                         } else if (IS_8X16(pict->mb_type[mb_index])) {
+                         } else if (IS_8X16(p->mb_type[mb_index])) {
                              int i;
                              for (i = 0; i < 2; i++) {
                                  int sx = mb_x * 16 + 4 + 8 * i;
                                      my *= 2;
  
                                  draw_arrow(ptr, sx, sy, mx + sx, my + sy, width,
 -                                           height, s->linesize, 100);
 +                                           height, pict->linesize[0], 100);
                              }
                          } else {
 -                              int sx = mb_x * 16 + 8;
 -                              int sy = mb_y * 16 + 8;
 -                              int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2;
 -                              int mx = p->motion_val[direction][xy][0] >> shift + sx;
 -                              int my = p->motion_val[direction][xy][1] >> shift + sy;
 -                              draw_arrow(ptr, sx, sy, mx, my, width, height, s->linesize, 100);
 +                              int sx= mb_x * 16 + 8;
 +                              int sy= mb_y * 16 + 8;
 +                              int xy= (mb_x + mb_y * mv_stride) << mv_sample_log2;
-                               int mx= (pict->motion_val[direction][xy][0]>>shift) + sx;
-                               int my= (pict->motion_val[direction][xy][1]>>shift) + sy;
++                              int mx= (p->motion_val[direction][xy][0]>>shift) + sx;
++                              int my= (p->motion_val[direction][xy][1]>>shift) + sy;
 +                              draw_arrow(ptr, sx, sy, mx, my, width, height, pict->linesize[0], 100);
                          }
                      }
                  }
 -                if ((s->avctx->debug & FF_DEBUG_VIS_QP) && p->motion_val) {
 +                if ((avctx->debug & FF_DEBUG_VIS_QP)) {
-                     uint64_t c = (pict->qscale_table[mb_index] * 128 / 31) *
+                     uint64_t c = (p->qscale_table[mb_index] * 128 / 31) *
                                   0x0101010101010101ULL;
                      int y;
                      for (y = 0; y < block_height; y++) {
                                        pict->linesize[2]) = c;
                      }
                  }
 -                if ((s->avctx->debug & FF_DEBUG_VIS_MB_TYPE) &&
 -                    p->motion_val) {
 +                if ((avctx->debug & FF_DEBUG_VIS_MB_TYPE) &&
-                     pict->motion_val[0]) {
-                     int mb_type = pict->mb_type[mb_index];
++                    p->motion_val[0]) {
+                     int mb_type = p->mb_type[mb_index];
                      uint64_t u,v;
                      int y;
  #define COLOR(theta, r) \
                          // hmm
                      }
                  }
 -                s->mbskip_table[mb_index] = 0;
 +                mbskip_table[mb_index] = 0;
 +            }
 +        }
 +    }
 +}
 +
- void ff_print_debug_info(MpegEncContext *s, AVFrame *pict)
++void ff_print_debug_info(MpegEncContext *s, Picture *p)
 +{
-     ff_print_debug_info2(s->avctx, pict, s->mbskip_table, s->visualization_buffer, &s->low_delay,
-                              s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample);
++    ff_print_debug_info2(s->avctx, p, s->mbskip_table, s->visualization_buffer, &s->low_delay,
++                         s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample);
 +}
 +
 +static inline int hpel_motion_lowres(MpegEncContext *s,
 +                                     uint8_t *dest, uint8_t *src,
 +                                     int field_based, int field_select,
 +                                     int src_x, int src_y,
 +                                     int width, int height, int stride,
 +                                     int h_edge_pos, int v_edge_pos,
 +                                     int w, int h, h264_chroma_mc_func *pix_op,
 +                                     int motion_x, int motion_y)
 +{
 +    const int lowres   = s->avctx->lowres;
 +    const int op_index = FFMIN(lowres, 2);
 +    const int s_mask   = (2 << lowres) - 1;
 +    int emu = 0;
 +    int sx, sy;
 +
 +    if (s->quarter_sample) {
 +        motion_x /= 2;
 +        motion_y /= 2;
 +    }
 +
 +    sx = motion_x & s_mask;
 +    sy = motion_y & s_mask;
 +    src_x += motion_x >> lowres + 1;
 +    src_y += motion_y >> lowres + 1;
 +
 +    src   += src_y * stride + src_x;
 +
 +    if ((unsigned)src_x > FFMAX( h_edge_pos - (!!sx) - w,                 0) ||
 +        (unsigned)src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) {
 +        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1,
 +                                (h + 1) << field_based, src_x,
 +                                src_y   << field_based,
 +                                h_edge_pos,
 +                                v_edge_pos);
 +        src = s->edge_emu_buffer;
 +        emu = 1;
 +    }
 +
 +    sx = (sx << 2) >> lowres;
 +    sy = (sy << 2) >> lowres;
 +    if (field_select)
 +        src += s->linesize;
 +    pix_op[op_index](dest, src, stride, h, sx, sy);
 +    return emu;
 +}
 +
 +/* apply one mpeg motion vector to the three components */
 +static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
 +                                                uint8_t *dest_y,
 +                                                uint8_t *dest_cb,
 +                                                uint8_t *dest_cr,
 +                                                int field_based,
 +                                                int bottom_field,
 +                                                int field_select,
 +                                                uint8_t **ref_picture,
 +                                                h264_chroma_mc_func *pix_op,
 +                                                int motion_x, int motion_y,
 +                                                int h, int mb_y)
 +{
 +    uint8_t *ptr_y, *ptr_cb, *ptr_cr;
 +    int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy,
 +        uvsx, uvsy;
 +    const int lowres     = s->avctx->lowres;
 +    const int op_index   = FFMIN(lowres-1+s->chroma_x_shift, 2);
 +    const int block_s    = 8>>lowres;
 +    const int s_mask     = (2 << lowres) - 1;
 +    const int h_edge_pos = s->h_edge_pos >> lowres;
 +    const int v_edge_pos = s->v_edge_pos >> lowres;
 +    linesize   = s->current_picture.f.linesize[0] << field_based;
 +    uvlinesize = s->current_picture.f.linesize[1] << field_based;
 +
 +    // FIXME obviously not perfect but qpel will not work in lowres anyway
 +    if (s->quarter_sample) {
 +        motion_x /= 2;
 +        motion_y /= 2;
 +    }
 +
 +    if(field_based){
 +        motion_y += (bottom_field - field_select)*((1 << lowres)-1);
 +    }
 +
 +    sx = motion_x & s_mask;
 +    sy = motion_y & s_mask;
 +    src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1);
 +    src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1);
 +
 +    if (s->out_format == FMT_H263) {
 +        uvsx    = ((motion_x >> 1) & s_mask) | (sx & 1);
 +        uvsy    = ((motion_y >> 1) & s_mask) | (sy & 1);
 +        uvsrc_x = src_x >> 1;
 +        uvsrc_y = src_y >> 1;
 +    } else if (s->out_format == FMT_H261) {
 +        // even chroma mv's are full pel in H261
 +        mx      = motion_x / 4;
 +        my      = motion_y / 4;
 +        uvsx    = (2 * mx) & s_mask;
 +        uvsy    = (2 * my) & s_mask;
 +        uvsrc_x = s->mb_x * block_s + (mx >> lowres);
 +        uvsrc_y =    mb_y * block_s + (my >> lowres);
 +    } else {
 +        if(s->chroma_y_shift){
 +            mx      = motion_x / 2;
 +            my      = motion_y / 2;
 +            uvsx    = mx & s_mask;
 +            uvsy    = my & s_mask;
 +            uvsrc_x = s->mb_x * block_s                 + (mx >> lowres + 1);
 +            uvsrc_y =   (mb_y * block_s >> field_based) + (my >> lowres + 1);
 +        } else {
 +            if(s->chroma_x_shift){
 +            //Chroma422
 +                mx = motion_x / 2;
 +                uvsx = mx & s_mask;
 +                uvsy = motion_y & s_mask;
 +                uvsrc_y = src_y;
 +                uvsrc_x = s->mb_x*block_s               + (mx >> (lowres+1));
 +            } else {
 +            //Chroma444
 +                uvsx = motion_x & s_mask;
 +                uvsy = motion_y & s_mask;
 +                uvsrc_x = src_x;
 +                uvsrc_y = src_y;
 +            }
 +        }
 +    }
 +
 +    ptr_y  = ref_picture[0] + src_y   * linesize   + src_x;
 +    ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
 +    ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
 +
 +    if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s,       0) ||
 +        (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) {
 +        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
 +                                linesize >> field_based, 17, 17 + field_based,
 +                                src_x, src_y << field_based, h_edge_pos,
 +                                v_edge_pos);
 +        ptr_y = s->edge_emu_buffer;
 +        if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
 +            uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize;
 +            s->vdsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9,
 +                                    9 + field_based,
 +                                    uvsrc_x, uvsrc_y << field_based,
 +                                    h_edge_pos >> 1, v_edge_pos >> 1);
 +            s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9,
 +                                    9 + field_based,
 +                                    uvsrc_x, uvsrc_y << field_based,
 +                                    h_edge_pos >> 1, v_edge_pos >> 1);
 +            ptr_cb = uvbuf;
 +            ptr_cr = uvbuf + 16;
 +        }
 +    }
 +
 +    // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
 +    if (bottom_field) {
 +        dest_y  += s->linesize;
 +        dest_cb += s->uvlinesize;
 +        dest_cr += s->uvlinesize;
 +    }
 +
 +    if (field_select) {
 +        ptr_y   += s->linesize;
 +        ptr_cb  += s->uvlinesize;
 +        ptr_cr  += s->uvlinesize;
 +    }
 +
 +    sx = (sx << 2) >> lowres;
 +    sy = (sy << 2) >> lowres;
 +    pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy);
 +
 +    if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
 +        uvsx = (uvsx << 2) >> lowres;
 +        uvsy = (uvsy << 2) >> lowres;
 +        if (h >> s->chroma_y_shift) {
 +            pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
 +            pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
 +        }
 +    }
 +    // FIXME h261 lowres loop filter
 +}
 +
 +static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
 +                                            uint8_t *dest_cb, uint8_t *dest_cr,
 +                                            uint8_t **ref_picture,
 +                                            h264_chroma_mc_func * pix_op,
 +                                            int mx, int my)
 +{
 +    const int lowres     = s->avctx->lowres;
 +    const int op_index   = FFMIN(lowres, 2);
 +    const int block_s    = 8 >> lowres;
 +    const int s_mask     = (2 << lowres) - 1;
 +    const int h_edge_pos = s->h_edge_pos >> lowres + 1;
 +    const int v_edge_pos = s->v_edge_pos >> lowres + 1;
 +    int emu = 0, src_x, src_y, offset, sx, sy;
 +    uint8_t *ptr;
 +
 +    if (s->quarter_sample) {
 +        mx /= 2;
 +        my /= 2;
 +    }
 +
 +    /* In case of 8X8, we construct a single chroma motion vector
 +       with a special rounding */
 +    mx = ff_h263_round_chroma(mx);
 +    my = ff_h263_round_chroma(my);
 +
 +    sx = mx & s_mask;
 +    sy = my & s_mask;
 +    src_x = s->mb_x * block_s + (mx >> lowres + 1);
 +    src_y = s->mb_y * block_s + (my >> lowres + 1);
 +
 +    offset = src_y * s->uvlinesize + src_x;
 +    ptr = ref_picture[1] + offset;
 +    if (s->flags & CODEC_FLAG_EMU_EDGE) {
 +        if ((unsigned) src_x > FFMAX(h_edge_pos - (!!sx) - block_s, 0) ||
 +            (unsigned) src_y > FFMAX(v_edge_pos - (!!sy) - block_s, 0)) {
 +            s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
 +                                    9, 9, src_x, src_y, h_edge_pos, v_edge_pos);
 +            ptr = s->edge_emu_buffer;
 +            emu = 1;
 +        }
 +    }
 +    sx = (sx << 2) >> lowres;
 +    sy = (sy << 2) >> lowres;
 +    pix_op[op_index](dest_cb, ptr, s->uvlinesize, block_s, sx, sy);
 +
 +    ptr = ref_picture[2] + offset;
 +    if (emu) {
 +        s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9,
 +                                src_x, src_y, h_edge_pos, v_edge_pos);
 +        ptr = s->edge_emu_buffer;
 +    }
 +    pix_op[op_index](dest_cr, ptr, s->uvlinesize, block_s, sx, sy);
 +}
 +
 +/**
 + * motion compensation of a single macroblock
 + * @param s context
 + * @param dest_y luma destination pointer
 + * @param dest_cb chroma cb/u destination pointer
 + * @param dest_cr chroma cr/v destination pointer
 + * @param dir direction (0->forward, 1->backward)
 + * @param ref_picture array[3] of pointers to the 3 planes of the reference picture
 + * @param pix_op halfpel motion compensation function (average or put normally)
 + * the motion vectors are taken from s->mv and the MV type from s->mv_type
 + */
 +static inline void MPV_motion_lowres(MpegEncContext *s,
 +                                     uint8_t *dest_y, uint8_t *dest_cb,
 +                                     uint8_t *dest_cr,
 +                                     int dir, uint8_t **ref_picture,
 +                                     h264_chroma_mc_func *pix_op)
 +{
 +    int mx, my;
 +    int mb_x, mb_y, i;
 +    const int lowres  = s->avctx->lowres;
 +    const int block_s = 8 >>lowres;
 +
 +    mb_x = s->mb_x;
 +    mb_y = s->mb_y;
 +
 +    switch (s->mv_type) {
 +    case MV_TYPE_16X16:
 +        mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                           0, 0, 0,
 +                           ref_picture, pix_op,
 +                           s->mv[dir][0][0], s->mv[dir][0][1],
 +                           2 * block_s, mb_y);
 +        break;
 +    case MV_TYPE_8X8:
 +        mx = 0;
 +        my = 0;
 +        for (i = 0; i < 4; i++) {
 +            hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) *
 +                               s->linesize) * block_s,
 +                               ref_picture[0], 0, 0,
 +                               (2 * mb_x + (i & 1)) * block_s,
 +                               (2 * mb_y + (i >> 1)) * block_s,
 +                               s->width, s->height, s->linesize,
 +                               s->h_edge_pos >> lowres, s->v_edge_pos >> lowres,
 +                               block_s, block_s, pix_op,
 +                               s->mv[dir][i][0], s->mv[dir][i][1]);
 +
 +            mx += s->mv[dir][i][0];
 +            my += s->mv[dir][i][1];
 +        }
 +
 +        if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY))
 +            chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture,
 +                                     pix_op, mx, my);
 +        break;
 +    case MV_TYPE_FIELD:
 +        if (s->picture_structure == PICT_FRAME) {
 +            /* top field */
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               1, 0, s->field_select[dir][0],
 +                               ref_picture, pix_op,
 +                               s->mv[dir][0][0], s->mv[dir][0][1],
 +                               block_s, mb_y);
 +            /* bottom field */
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               1, 1, s->field_select[dir][1],
 +                               ref_picture, pix_op,
 +                               s->mv[dir][1][0], s->mv[dir][1][1],
 +                               block_s, mb_y);
 +        } else {
 +            if (s->picture_structure != s->field_select[dir][0] + 1 &&
 +                s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
 +                ref_picture = s->current_picture_ptr->f.data;
 +
 +            }
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               0, 0, s->field_select[dir][0],
 +                               ref_picture, pix_op,
 +                               s->mv[dir][0][0],
 +                               s->mv[dir][0][1], 2 * block_s, mb_y >> 1);
 +            }
 +        break;
 +    case MV_TYPE_16X8:
 +        for (i = 0; i < 2; i++) {
 +            uint8_t **ref2picture;
 +
 +            if (s->picture_structure == s->field_select[dir][i] + 1 ||
 +                s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
 +                ref2picture = ref_picture;
 +            } else {
 +                ref2picture = s->current_picture_ptr->f.data;
 +            }
 +
 +            mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                               0, 0, s->field_select[dir][i],
 +                               ref2picture, pix_op,
 +                               s->mv[dir][i][0], s->mv[dir][i][1] +
 +                               2 * block_s * i, block_s, mb_y >> 1);
 +
 +            dest_y  +=  2 * block_s *  s->linesize;
 +            dest_cb += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
 +            dest_cr += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
 +        }
 +        break;
 +    case MV_TYPE_DMV:
 +        if (s->picture_structure == PICT_FRAME) {
 +            for (i = 0; i < 2; i++) {
 +                int j;
 +                for (j = 0; j < 2; j++) {
 +                    mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                                       1, j, j ^ i,
 +                                       ref_picture, pix_op,
 +                                       s->mv[dir][2 * i + j][0],
 +                                       s->mv[dir][2 * i + j][1],
 +                                       block_s, mb_y);
 +                }
 +                pix_op = s->h264chroma.avg_h264_chroma_pixels_tab;
 +            }
 +        } else {
 +            for (i = 0; i < 2; i++) {
 +                mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
 +                                   0, 0, s->picture_structure != i + 1,
 +                                   ref_picture, pix_op,
 +                                   s->mv[dir][2 * i][0],s->mv[dir][2 * i][1],
 +                                   2 * block_s, mb_y >> 1);
 +
 +                // after put we make avg of the same block
 +                pix_op = s->h264chroma.avg_h264_chroma_pixels_tab;
 +
 +                // opposite parity is always in the same
 +                // frame if this is second field
 +                if (!s->first_field) {
 +                    ref_picture = s->current_picture_ptr->f.data;
 +                }
              }
          }
 +        break;
 +    default:
 +        av_assert2(0);
      }
  }
  
@@@ -2632,9 -2364,9 +2742,9 @@@ void MPV_decode_mb_internal(MpegEncCont
  
              if (s->mb_skipped) {
                  s->mb_skipped= 0;
 -                assert(s->pict_type!=AV_PICTURE_TYPE_I);
 +                av_assert2(s->pict_type!=AV_PICTURE_TYPE_I);
                  *mbskip_ptr = 1;
-             } else if(!s->current_picture.f.reference) {
+             } else if(!s->current_picture.reference) {
                  *mbskip_ptr = 1;
              } else{
                  *mbskip_ptr = 0; /* not skipped */
@@@ -139,17 -166,12 +168,13 @@@ typedef struct Picture
  
      int mb_var_sum;             ///< sum of MB variance for current frame
      int mc_mb_var_sum;          ///< motion compensated MB variance for current frame
-     uint16_t *mb_var;           ///< Table for MB variances
-     uint16_t *mc_mb_var;        ///< Table for motion compensated MB variances
-     uint8_t *mb_mean;           ///< Table for MB luminance
      int b_frame_score;          /* */
-     void *owner2;               ///< pointer to the context that allocated this picture
      int needs_realloc;          ///< Picture needs to be reallocated (eg due to a frame size change)
-     /**
-      * hardware accelerator private data
-      */
-     void *hwaccel_picture_private;
 +    int period_since_free;      ///< "cycles" since this Picture has been freed
+     int reference;
+     int shared;
  } Picture;
  
  /**
@@@ -932,4 -939,7 +954,12 @@@ void ff_wmv2_encode_mb(MpegEncContext 
                         int16_t block[6][64],
                         int motion_x, int motion_y);
  
+ int ff_mpeg_ref_picture(MpegEncContext *s, Picture *dst, Picture *src);
+ void ff_mpeg_unref_picture(MpegEncContext *s, Picture *picture);
++void ff_print_debug_info2(AVCodecContext *avctx, Picture *pict, uint8_t *mbskip_table,
++                         uint8_t *visualization_buffer[3], int *low_delay,
++                         int mb_width, int mb_height, int mb_stride, int quarter_sample);
++
++
  #endif /* AVCODEC_MPEGVIDEO_H */
@@@ -1068,12 -967,8 +1066,12 @@@ static int load_input_picture(MpegEncCo
                      int w = s->width  >> h_shift;
                      int h = s->height >> v_shift;
                      uint8_t *src = pic_arg->data[i];
-                     uint8_t *dst = pic->data[i];
+                     uint8_t *dst = pic->f.data[i];
  
 +                    if (s->codec_id == AV_CODEC_ID_AMV && !(s->avctx->flags & CODEC_FLAG_EMU_EDGE)) {
 +                        h = ((s->height + 15)/16*16) >> v_shift;
 +                    }
 +
                      if (!s->avctx->rc_buffer_size)
                          dst += INPLACE_OFFSET;
  
Simple merge
Simple merge
@@@ -407,7 -409,6 +407,7 @@@ static int msmpeg4v2_decode_motion(Mpeg
  static int msmpeg4v12_decode_mb(MpegEncContext *s, int16_t block[6][64])
  {
      int cbp, code, i;
-     uint32_t * const mb_type_ptr = &s->current_picture.f.mb_type[s->mb_x + s->mb_y*s->mb_stride];
++    uint32_t * const mb_type_ptr = &s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride];
  
      if (s->pict_type == AV_PICTURE_TYPE_P) {
          if (s->use_skip_mb_code) {
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 5131ae2,0000000..7848d32
mode 100644,000000..100644
--- /dev/null
@@@ -1,287 -1,0 +1,289 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame)
 +/*
 + * Silicon Graphics Motion Video Compressor 1 & 2 decoder
 + * Copyright (c) 2012 Peter Ross
 + *
 + * 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
 + * Silicon Graphics Motion Video Compressor 1 & 2 decoder
 + */
 +
 +#include "libavutil/intreadwrite.h"
 +#include "avcodec.h"
 +#include "bytestream.h"
++#include "internal.h"
 +
 +typedef struct MvcContext {
++    AVFrame *frame;
 +    int vflip;
 +} MvcContext;
 +
 +static av_cold int mvc_decode_init(AVCodecContext *avctx)
 +{
 +    MvcContext *s = avctx->priv_data;
 +    int width  = avctx->width;
 +    int height = avctx->height;
 +
 +    if (avctx->codec_id == AV_CODEC_ID_MVC1) {
 +        width  += 3;
 +        height += 3;
 +    }
 +    width  &= ~3;
 +    height &= ~3;
 +    if (width != avctx->width || height != avctx->height)
 +        avcodec_set_dimensions(avctx, width, height);
 +
 +    avctx->pix_fmt = (avctx->codec_id == AV_CODEC_ID_MVC1) ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_BGRA;
-     avctx->coded_frame->reference = 3;
-     avctx->coded_frame->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
-                             FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
-     ret = avctx->reget_buffer(avctx, avctx->coded_frame);
++    s->frame = av_frame_alloc();
++    if (!s->frame)
 +        return AVERROR(ENOMEM);
 +
 +    s->vflip = avctx->extradata_size >= 9 && !memcmp(avctx->extradata + avctx->extradata_size - 9, "BottomUp", 9);
 +    return 0;
 +}
 +
 +static int decode_mvc1(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_start, int width, int height, int linesize)
 +{
 +    uint8_t *dst;
 +    uint16_t v[8];
 +    int mask, x, y, i;
 +
 +    x = y= 0;
 +    while (bytestream2_get_bytes_left(gb) >= 6) {
 +        mask = bytestream2_get_be16u(gb);
 +        v[0] = bytestream2_get_be16u(gb);
 +        v[1] = bytestream2_get_be16u(gb);
 +        if ((v[0] & 0x8000)) {
 +            if (bytestream2_get_bytes_left(gb) < 12) {
 +                av_log(avctx, AV_LOG_WARNING, "buffer overflow\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +            for (i = 2; i < 8; i++)
 +                v[i] = bytestream2_get_be16u(gb);
 +        } else {
 +            v[2] = v[4] = v[6] = v[0];
 +            v[3] = v[5] = v[7] = v[1];
 +        }
 +
 +#define PIX16(target, true, false) \
 +        i = (mask & target) ? true : false; \
 +        AV_WN16A(dst, (v[i] & 0x7C00) | (v[i] & 0x3E0) | (v[i] & 0x1F)); \
 +        dst += 2;
 +
 +#define ROW16(row, a1, a0, b1, b0) \
 +        dst = dst_start + (y + row) * linesize + x * 2; \
 +        PIX16(1 << (row * 4),     a1, a0) \
 +        PIX16(1 << (row * 4 + 1), a1, a0) \
 +        PIX16(1 << (row * 4 + 2), b1, b0) \
 +        PIX16(1 << (row * 4 + 3), b1, b0)
 +
 +        ROW16(0, 0, 1, 2, 3);
 +        ROW16(1, 0, 1, 2, 3);
 +        ROW16(2, 4, 5, 6, 7);
 +        ROW16(3, 4, 5, 6, 7);
 +
 +        x += 4;
 +        if (x >= width) {
 +            y += 4;
 +            if (y >= height) {
 +                break;
 +            }
 +            x = 0;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static void set_4x4_block(uint8_t *dst, int linesize, uint32_t pixel)
 +{
 +    int i, j;
 +    for (j = 0; j < 4; j++)
 +        for (i = 0; i < 4; i++)
 +            AV_WN32A(dst + j * linesize + i * 4, pixel);
 +}
 +
 +#define PIX32(target, true, false) \
 +    AV_WN32A(dst, (mask & target) ? v[true] : v[false]); \
 +    dst += 4;
 +
 +#define ROW32(row, a1, a0, b1, b0) \
 +    dst = dst_start + (y + row) * linesize + x * 4; \
 +    PIX32(1 << (row * 4),     a1, a0) \
 +    PIX32(1 << (row * 4 + 1), a1, a0) \
 +    PIX32(1 << (row * 4 + 2), b1, b0) \
 +    PIX32(1 << (row * 4 + 3), b1, b0)
 +
 +#define MVC2_BLOCK \
 +    ROW32(0, 1, 0, 3, 2); \
 +    ROW32(1, 1, 0, 3, 2); \
 +    ROW32(2, 5, 4, 7, 6); \
 +    ROW32(3, 5, 4, 7, 6);
 +
 +static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, uint8_t *dst_start, int width, int height, int linesize, int vflip)
 +{
 +    uint8_t *dst;
 +    uint32_t color[128], v[8];
 +    int w, h, nb_colors, i, x, y, p0, p1, mask;
 +
 +    if (bytestream2_get_bytes_left(gb) < 6)
 +        return AVERROR_INVALIDDATA;
 +
 +    w = bytestream2_get_be16u(gb);
 +    h = bytestream2_get_be16u(gb);
 +    if ((w & ~3) != width || (h & ~3) != height)
 +        av_log(avctx, AV_LOG_WARNING, "dimension mismatch\n");
 +
 +    if (bytestream2_get_byteu(gb)) {
 +        av_log_ask_for_sample(avctx, "bitmap feature\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    nb_colors = bytestream2_get_byteu(gb);
 +    if (bytestream2_get_bytes_left(gb) < nb_colors * 3)
 +        return AVERROR_INVALIDDATA;
 +    for (i = 0; i < FFMIN(nb_colors, 128); i++)
 +        color[i] = 0xFF000000 | bytestream2_get_be24u(gb);
 +    if (nb_colors > 128)
 +        bytestream2_skip(gb, (nb_colors - 128) * 3);
 +
 +    if (vflip) {
 +        dst_start += (height - 1) * linesize;
 +        linesize = -linesize;
 +    }
 +    x = y = 0;
 +    while (bytestream2_get_bytes_left(gb) >= 1) {
 +        p0 = bytestream2_get_byteu(gb);
 +        if ((p0 & 0x80)) {
 +            if ((p0 & 0x40)) {
 +                p0 &= 0x3F;
 +                p0 = (p0 << 2) | (p0 >> 4);
 +                set_4x4_block(dst_start + y * linesize + x * 4, linesize, 0xFF000000 | (p0 << 16) | (p0 << 8) | p0);
 +            } else {
 +                int g, r;
 +                p0 &= 0x3F;
 +                p0 = (p0 << 2) | (p0 >> 4);
 +                if (bytestream2_get_bytes_left(gb) < 2)
 +                    return AVERROR_INVALIDDATA;
 +                g = bytestream2_get_byteu(gb);
 +                r = bytestream2_get_byteu(gb);
 +                set_4x4_block(dst_start + y * linesize + x * 4, linesize, 0xFF000000 | (r << 16) | (g << 8) | p0);
 +            }
 +        } else {
 +            if (bytestream2_get_bytes_left(gb) < 1)
 +                return AVERROR_INVALIDDATA;
 +            p1 = bytestream2_get_byteu(gb);
 +            if ((p1 & 0x80)) {
 +                if ((p0 & 0x7F) == (p1 & 0x7F)) {
 +                    set_4x4_block(dst_start + y * linesize + x * 4, linesize, color[p0 & 0x7F]);
 +                } else {
 +                    if (bytestream2_get_bytes_left(gb) < 2)
 +                        return AVERROR_INVALIDDATA;
 +                    v[0] = v[2] = v[4] = v[6] = color[p0 & 0x7F];
 +                    v[1] = v[3] = v[5] = v[7] = color[p1 & 0x7F];
 +                    mask = bytestream2_get_le16u(gb);
 +                    MVC2_BLOCK
 +                }
 +            } else {
 +                if (bytestream2_get_bytes_left(gb) < 8)
 +                    return AVERROR_INVALIDDATA;
 +                v[0] = color[p0 & 0x7F];
 +                v[1] = color[p1 & 0x7F];
 +                for (i = 2; i < 8; i++)
 +                    v[i] = color[bytestream2_get_byteu(gb) & 0x7F];
 +                mask = bytestream2_get_le16u(gb);
 +                MVC2_BLOCK
 +            }
 +        }
 +
 +        x += 4;
 +        if (x >= width) {
 +            y += 4;
 +            if (y >= height)
 +                break;
 +            x = 0;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int mvc_decode_frame(AVCodecContext *avctx,
 +                            void *data, int *got_frame,
 +                            AVPacket *avpkt)
 +{
 +    MvcContext *s = avctx->priv_data;
 +    GetByteContext gb;
 +    int ret;
 +
-         ret = decode_mvc1(avctx, &gb, avctx->coded_frame->data[0], avctx->width, avctx->height, avctx->coded_frame->linesize[0]);
++    ret = ff_reget_buffer(avctx, s->frame);
 +    if (ret < 0) {
 +        av_log (avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    bytestream2_init(&gb, avpkt->data, avpkt->size);
 +    if (avctx->codec_id == AV_CODEC_ID_MVC1)
-         ret = decode_mvc2(avctx, &gb, avctx->coded_frame->data[0], avctx->width, avctx->height, avctx->coded_frame->linesize[0], s->vflip);
++        ret = decode_mvc1(avctx, &gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0]);
 +    else
-     *got_frame      = 1;
-     *(AVFrame*)data = *avctx->coded_frame;
++        ret = decode_mvc2(avctx, &gb, s->frame->data[0], avctx->width, avctx->height, s->frame->linesize[0], s->vflip);
 +    if (ret < 0)
 +        return ret;
 +
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
++    *got_frame = 1;
++    if ((ret = av_frame_ref(data, s->frame)) < 0)
++        return ret;
++
 +    return avpkt->size;
 +}
 +
 +static av_cold int mvc_decode_end(AVCodecContext *avctx)
 +{
++    MvcContext *s = avctx->priv_data;
++
++    av_frame_free(&s->frame);
++
 +    return 0;
 +}
 +
 +#if CONFIG_MVC1_DECODER
 +AVCodec ff_mvc1_decoder = {
 +    .name           = "mvc1",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_MVC1,
 +    .priv_data_size = sizeof(MvcContext),
 +    .init           = mvc_decode_init,
 +    .close          = mvc_decode_end,
 +    .decode         = mvc_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"),
 +};
 +#endif
 +
 +#if CONFIG_MVC2_DECODER
 +AVCodec ff_mvc2_decoder = {
 +    .name           = "mvc2",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_MVC2,
 +    .priv_data_size = sizeof(MvcContext),
 +    .init           = mvc_decode_init,
 +    .close          = mvc_decode_end,
 +    .decode         = mvc_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"),
 +};
 +#endif
Simple merge
Simple merge
@@@ -240,14 -221,12 +241,12 @@@ retry
          buf_size -= RTJPEG_HEADER_SIZE;
      }
  
-     if ((size_change || keyframe) && c->pic.data[0]) {
-         avctx->release_buffer(avctx, &c->pic);
 -    if (keyframe) {
++    if (size_change || keyframe) {
+         av_frame_unref(&c->pic);
          init_frame = 1;
      }
-     c->pic.reference    = 3;
-     c->pic.buffer_hints = FF_BUFFER_HINTS_VALID    | FF_BUFFER_HINTS_READABLE |
-                           FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     result = avctx->reget_buffer(avctx, &c->pic);
+     result = ff_reget_buffer(avctx, &c->pic);
      if (result < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return result;
@@@ -102,26 -84,18 +102,24 @@@ int avcodec_get_context_defaults3(AVCod
      s->av_class = &av_codec_context_class;
  
      s->codec_type = codec ? codec->type : AVMEDIA_TYPE_UNKNOWN;
 -    s->codec      = codec;
 -    av_opt_set_defaults(s);
 +    if(s->codec_type == AVMEDIA_TYPE_AUDIO)
 +        flags= AV_OPT_FLAG_AUDIO_PARAM;
 +    else if(s->codec_type == AVMEDIA_TYPE_VIDEO)
 +        flags= AV_OPT_FLAG_VIDEO_PARAM;
 +    else if(s->codec_type == AVMEDIA_TYPE_SUBTITLE)
 +        flags= AV_OPT_FLAG_SUBTITLE_PARAM;
 +    av_opt_set_defaults2(s, flags, flags);
  
      s->time_base           = (AVRational){0,1};
-     s->get_buffer          = avcodec_default_get_buffer;
-     s->release_buffer      = avcodec_default_release_buffer;
+     s->get_buffer2         = avcodec_default_get_buffer2;
      s->get_format          = avcodec_default_get_format;
      s->execute             = avcodec_default_execute;
      s->execute2            = avcodec_default_execute2;
      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->reget_buffer        = avcodec_default_reget_buffer;
      s->reordered_opaque    = AV_NOPTS_VALUE;
      if(codec && codec->priv_data_size){
          if(!s->priv_data){
@@@ -404,13 -392,18 +404,14 @@@ static const AVOption options[]=
  {"em", "Emergency",          0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EMERGENCY },         INT_MIN, INT_MAX, A|E, "audio_service_type"},
  {"vo", "Voice Over",         0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VOICE_OVER },        INT_MIN, INT_MAX, A|E, "audio_service_type"},
  {"ka", "Karaoke",            0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_KARAOKE },           INT_MIN, INT_MAX, A|E, "audio_service_type"},
 -{"request_sample_fmt", NULL, OFFSET(request_sample_fmt), AV_OPT_TYPE_INT, {.i64 = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
 -{"u8" , "8-bit unsigned integer", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_U8  }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"s16", "16-bit signed integer",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S16 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"s32", "32-bit signed integer",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"flt", "32-bit float",           0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_FLT }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"dbl", "64-bit double",          0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_DBL }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"u8p" , "8-bit unsigned integer planar", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_U8P  }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"s16p", "16-bit signed integer planar",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S16P }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"s32p", "32-bit signed integer planar",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32P }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"fltp", "32-bit float planar",           0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_FLTP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 -{"dblp", "64-bit double planar",          0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_DBLP }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
 +{"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT, {.i64=AV_SAMPLE_FMT_NONE}, -1, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
 +{"pkt_timebase", NULL, OFFSET(pkt_timebase), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0},
 +{"sub_charenc", "set input text subtitles character encoding", OFFSET(sub_charenc), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, S|D},
 +{"sub_charenc_mode", "set input text subtitles character encoding mode", OFFSET(sub_charenc_mode), AV_OPT_TYPE_FLAGS, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC}, -1, INT_MAX, S|D, "sub_charenc_mode"},
 +{"do_nothing",  NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_DO_NOTHING},  INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
 +{"auto",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_AUTOMATIC},   INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
 +{"pre_decoder", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_SUB_CHARENC_MODE_PRE_DECODER}, INT_MIN, INT_MAX, S|D, "sub_charenc_mode"},
+ {"refcounted_frames", NULL, OFFSET(refcounted_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, A|V|D },
  {NULL},
  };
  
index 78a5d97,0000000..5ff09b9
mode 100644,000000..100644
--- /dev/null
@@@ -1,447 -1,0 +1,446 @@@
-     c->pic.reference = 3;
-     if ((ret = avctx->reget_buffer(avctx, &c->pic)) < 0)
 +/*
 + * Packed Animation File video and audio decoder
 + * Copyright (c) 2012 Paul B Mahol
 + *
 + * 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 "libavcodec/paf.h"
 +#include "bytestream.h"
 +#include "avcodec.h"
 +#include "copy_block.h"
 +#include "internal.h"
 +
 +
 +static const uint8_t block_sequences[16][8] =
 +{
 +    { 0, 0, 0, 0, 0, 0, 0, 0 },
 +    { 2, 0, 0, 0, 0, 0, 0, 0 },
 +    { 5, 7, 0, 0, 0, 0, 0, 0 },
 +    { 5, 0, 0, 0, 0, 0, 0, 0 },
 +    { 6, 0, 0, 0, 0, 0, 0, 0 },
 +    { 5, 7, 5, 7, 0, 0, 0, 0 },
 +    { 5, 7, 5, 0, 0, 0, 0, 0 },
 +    { 5, 7, 6, 0, 0, 0, 0, 0 },
 +    { 5, 5, 0, 0, 0, 0, 0, 0 },
 +    { 3, 0, 0, 0, 0, 0, 0, 0 },
 +    { 6, 6, 0, 0, 0, 0, 0, 0 },
 +    { 2, 4, 0, 0, 0, 0, 0, 0 },
 +    { 2, 4, 5, 7, 0, 0, 0, 0 },
 +    { 2, 4, 5, 0, 0, 0, 0, 0 },
 +    { 2, 4, 6, 0, 0, 0, 0, 0 },
 +    { 2, 4, 5, 7, 5, 7, 0, 0 }
 +};
 +
 +typedef struct PAFVideoDecContext {
 +    AVFrame  pic;
 +    GetByteContext gb;
 +
 +    int     current_frame;
 +    uint8_t *frame[4];
 +    int     frame_size;
 +    int     video_size;
 +
 +    uint8_t *opcodes;
 +} PAFVideoDecContext;
 +
 +static av_cold int paf_vid_init(AVCodecContext *avctx)
 +{
 +    PAFVideoDecContext *c = avctx->priv_data;
 +    int i;
 +
 +    if (avctx->height & 3 || avctx->width & 3) {
 +        av_log(avctx, AV_LOG_ERROR, "width and height must be multiplies of 4\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    avctx->pix_fmt = AV_PIX_FMT_PAL8;
 +
 +    avcodec_get_frame_defaults(&c->pic);
 +    c->frame_size = FFALIGN(avctx->height, 256) * avctx->width;
 +    c->video_size = avctx->height * avctx->width;
 +    for (i = 0; i < 4; i++) {
 +        c->frame[i] = av_mallocz(c->frame_size);
 +        if (!c->frame[i])
 +            return AVERROR(ENOMEM);
 +    }
 +
 +    return 0;
 +}
 +
 +static int get_video_page_offset(AVCodecContext *avctx, uint8_t a, uint8_t b)
 +{
 +    int x, y;
 +
 +    x = b & 0x7F;
 +    y = ((a & 0x3F) << 1) | (b >> 7 & 1);
 +
 +    return y * 2 * avctx->width + x * 2;
 +}
 +
 +static void copy4h(AVCodecContext *avctx, uint8_t *dst)
 +{
 +    PAFVideoDecContext *c = avctx->priv_data;
 +    int i;
 +
 +    for (i = 0; i < 4; i++) {
 +        bytestream2_get_buffer(&c->gb, dst, 4);
 +        dst += avctx->width;
 +    }
 +}
 +
 +static void copy_color_mask(AVCodecContext *avctx, uint8_t mask, uint8_t *dst, uint8_t color)
 +{
 +    int i;
 +
 +    for (i = 0; i < 4; i++) {
 +        if ((mask >> 4) & (1 << (3 - i)))
 +            dst[i] = color;
 +        if ((mask & 15) & (1 << (3 - i)))
 +            dst[avctx->width + i] = color;
 +    }
 +}
 +
 +static void copy_src_mask(AVCodecContext *avctx, uint8_t mask, uint8_t *dst, const uint8_t *src)
 +{
 +    int i;
 +
 +    for (i = 0; i < 4; i++) {
 +        if ((mask >> 4) & (1 << (3 - i)))
 +            dst[i] = src[i];
 +        if ((mask & 15) & (1 << (3 - i)))
 +            dst[avctx->width + i] = src[avctx->width + i];
 +    }
 +}
 +
 +static int decode_0(AVCodecContext *avctx, uint8_t code, uint8_t *pkt)
 +{
 +    PAFVideoDecContext *c = avctx->priv_data;
 +    uint32_t opcode_size, offset;
 +    uint8_t *dst, *dend, mask = 0, color = 0, a, b, p;
 +    const uint8_t *src, *send, *opcodes;
 +    int  i, j, x = 0;
 +
 +    i = bytestream2_get_byte(&c->gb);
 +    if (i) {
 +        if (code & 0x10) {
 +            int align;
 +
 +            align = bytestream2_tell(&c->gb) & 3;
 +            if (align)
 +                bytestream2_skip(&c->gb, 4 - align);
 +        }
 +        do {
 +            a      = bytestream2_get_byte(&c->gb);
 +            b      = bytestream2_get_byte(&c->gb);
 +            p      = (a & 0xC0) >> 6;
 +            dst    = c->frame[p] + get_video_page_offset(avctx, a, b);
 +            dend   = c->frame[p] + c->frame_size;
 +            offset = (b & 0x7F) * 2;
 +            j      = bytestream2_get_le16(&c->gb) + offset;
 +
 +            do {
 +                offset++;
 +                if (dst + 3 * avctx->width + 4 > dend)
 +                    return AVERROR_INVALIDDATA;
 +                copy4h(avctx, dst);
 +                if ((offset & 0x3F) == 0)
 +                    dst += avctx->width * 3;
 +                dst += 4;
 +            } while (offset < j);
 +        } while (--i);
 +    }
 +
 +    dst  = c->frame[c->current_frame];
 +    dend = c->frame[c->current_frame] + c->frame_size;
 +    do {
 +        a    = bytestream2_get_byte(&c->gb);
 +        b    = bytestream2_get_byte(&c->gb);
 +        p    = (a & 0xC0) >> 6;
 +        src  = c->frame[p] + get_video_page_offset(avctx, a, b);
 +        send = c->frame[p] + c->frame_size;
 +        if ((src + 3 * avctx->width + 4 > send) ||
 +            (dst + 3 * avctx->width + 4 > dend))
 +            return AVERROR_INVALIDDATA;
 +        copy_block4(dst, src, avctx->width, avctx->width, 4);
 +        i++;
 +        if ((i & 0x3F) == 0)
 +            dst += avctx->width * 3;
 +        dst += 4;
 +    } while (i < c->video_size / 16);
 +
 +    opcode_size = bytestream2_get_le16(&c->gb);
 +    bytestream2_skip(&c->gb, 2);
 +
 +    if (bytestream2_get_bytes_left(&c->gb) < opcode_size)
 +        return AVERROR_INVALIDDATA;
 +
 +    opcodes = pkt + bytestream2_tell(&c->gb);
 +    bytestream2_skipu(&c->gb, opcode_size);
 +
 +    dst = c->frame[c->current_frame];
 +
 +    for (i = 0; i < avctx->height; i += 4, dst += avctx->width * 3) {
 +        for (j = 0; j < avctx->width; j += 4, dst += 4) {
 +            int opcode, k = 0;
 +
 +            if (x > opcode_size)
 +                return AVERROR_INVALIDDATA;
 +            if (j & 4) {
 +                opcode = opcodes[x] & 15;
 +                x++;
 +            } else {
 +                opcode = opcodes[x] >> 4;
 +            }
 +
 +            while (block_sequences[opcode][k]) {
 +
 +                offset = avctx->width * 2;
 +                code   = block_sequences[opcode][k++];
 +
 +                switch (code) {
 +                case 2:
 +                    offset = 0;
 +                case 3:
 +                    color  = bytestream2_get_byte(&c->gb);
 +                case 4:
 +                    mask   = bytestream2_get_byte(&c->gb);
 +                    copy_color_mask(avctx, mask, dst + offset, color);
 +                    break;
 +                case 5:
 +                    offset = 0;
 +                case 6:
 +                    a    = bytestream2_get_byte(&c->gb);
 +                    b    = bytestream2_get_byte(&c->gb);
 +                    p    = (a & 0xC0) >> 6;
 +                    src  = c->frame[p] + get_video_page_offset(avctx, a, b);
 +                    send = c->frame[p] + c->frame_size;
 +                case 7:
 +                    if (src + offset + avctx->width + 4 > send)
 +                        return AVERROR_INVALIDDATA;
 +                    mask = bytestream2_get_byte(&c->gb);
 +                    copy_src_mask(avctx, mask, dst + offset, src + offset);
 +                    break;
 +                }
 +            }
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static int paf_vid_decode(AVCodecContext *avctx, void *data,
 +                          int *got_frame, AVPacket *pkt)
 +{
 +    PAFVideoDecContext *c = avctx->priv_data;
 +    uint8_t code, *dst, *src, *end;
 +    int i, frame, ret;
 +
-     *(AVFrame *)data = c->pic;
++    if ((ret =ff_reget_buffer(avctx, &c->pic)) < 0)
 +        return ret;
 +
 +    bytestream2_init(&c->gb, pkt->data, pkt->size);
 +
 +    code = bytestream2_get_byte(&c->gb);
 +    if (code & 0x20) {
 +        for (i = 0; i < 4; i++)
 +            memset(c->frame[i], 0, c->frame_size);
 +
 +        memset(c->pic.data[1], 0, AVPALETTE_SIZE);
 +        c->current_frame = 0;
 +        c->pic.key_frame = 1;
 +        c->pic.pict_type = AV_PICTURE_TYPE_I;
 +    } else {
 +        c->pic.key_frame = 0;
 +        c->pic.pict_type = AV_PICTURE_TYPE_P;
 +    }
 +
 +    if (code & 0x40) {
 +        uint32_t *out = (uint32_t *)c->pic.data[1];
 +        int index, count;
 +
 +        index = bytestream2_get_byte(&c->gb);
 +        count = bytestream2_get_byte(&c->gb) + 1;
 +
 +        if (index + count > 256)
 +            return AVERROR_INVALIDDATA;
 +        if (bytestream2_get_bytes_left(&c->gb) < 3*count)
 +            return AVERROR_INVALIDDATA;
 +
 +        out += index;
 +        for (i = 0; i < count; i++) {
 +            unsigned r, g, b;
 +
 +            r = bytestream2_get_byteu(&c->gb);
 +            r = r << 2 | r >> 4;
 +            g = bytestream2_get_byteu(&c->gb);
 +            g = g << 2 | g >> 4;
 +            b = bytestream2_get_byteu(&c->gb);
 +            b = b << 2 | b >> 4;
 +            *out++ = 0xFFU << 24 | r << 16 | g << 8 | b;
 +        }
 +        c->pic.palette_has_changed = 1;
 +    }
 +
 +    switch (code & 0x0F) {
 +    case 0:
 +        if ((ret = decode_0(avctx, code, pkt->data)) < 0)
 +            return ret;
 +        break;
 +    case 1:
 +        dst = c->frame[c->current_frame];
 +        bytestream2_skip(&c->gb, 2);
 +        if (bytestream2_get_bytes_left(&c->gb) < c->video_size)
 +            return AVERROR_INVALIDDATA;
 +        bytestream2_get_bufferu(&c->gb, dst, c->video_size);
 +        break;
 +    case 2:
 +        frame = bytestream2_get_byte(&c->gb);
 +        if (frame > 3)
 +            return AVERROR_INVALIDDATA;
 +        if (frame != c->current_frame)
 +            memcpy(c->frame[c->current_frame], c->frame[frame], c->frame_size);
 +        break;
 +    case 4:
 +        dst = c->frame[c->current_frame];
 +        end = dst + c->video_size;
 +
 +        bytestream2_skip(&c->gb, 2);
 +
 +        while (dst < end) {
 +            int8_t code;
 +            int count;
 +
 +            if (bytestream2_get_bytes_left(&c->gb) < 2)
 +                return AVERROR_INVALIDDATA;
 +
 +            code  = bytestream2_get_byteu(&c->gb);
 +            count = FFABS(code) + 1;
 +
 +            if (dst + count > end)
 +                return AVERROR_INVALIDDATA;
 +            if (code < 0)
 +                memset(dst, bytestream2_get_byteu(&c->gb), count);
 +            else
 +                bytestream2_get_buffer(&c->gb, dst, count);
 +            dst += count;
 +        }
 +        break;
 +    default:
 +        av_log_ask_for_sample(avctx, "unknown/invalid code\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    dst = c->pic.data[0];
 +    src = c->frame[c->current_frame];
 +    for (i = 0; i < avctx->height; i++) {
 +        memcpy(dst, src, avctx->width);
 +        dst += c->pic.linesize[0];
 +        src += avctx->width;
 +    }
 +
 +    c->current_frame = (c->current_frame + 1) & 3;
++    if ((ret = av_frame_ref(data, &c->pic)) < 0)
++        return ret;
 +
 +    *got_frame       = 1;
-     if (c->pic.data[0])
-         avctx->release_buffer(avctx, &c->pic);
 +
 +    return pkt->size;
 +}
 +
 +static av_cold int paf_vid_close(AVCodecContext *avctx)
 +{
 +    PAFVideoDecContext *c = avctx->priv_data;
 +    int i;
 +
-     if ((ret = ff_get_buffer(avctx, frame)) < 0)
++    av_frame_unref(&c->pic);
 +
 +    for (i = 0; i < 4; i++)
 +        av_freep(&c->frame[i]);
 +
 +    return 0;
 +}
 +
 +static av_cold int paf_aud_init(AVCodecContext *avctx)
 +{
 +    if (avctx->channels != 2) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    avctx->channel_layout = AV_CH_LAYOUT_STEREO;
 +    avctx->sample_fmt     = AV_SAMPLE_FMT_S16;
 +
 +    return 0;
 +}
 +
 +static int paf_aud_decode(AVCodecContext *avctx, void *data,
 +                          int *got_frame_ptr, AVPacket *pkt)
 +{
 +    AVFrame *frame = data;
 +    uint8_t *buf = pkt->data;
 +    int16_t *output_samples;
 +    const uint8_t *t;
 +    int frames, ret, i, j, k;
 +
 +    frames = pkt->size / PAF_SOUND_FRAME_SIZE;
 +    if (frames < 1)
 +        return AVERROR_INVALIDDATA;
 +
 +    frame->nb_samples = PAF_SOUND_SAMPLES * frames;
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
 +        return ret;
 +
 +    output_samples = (int16_t *)frame->data[0];
 +    for (i = 0; i < frames; i++) {
 +        t = buf + 256 * sizeof(uint16_t);
 +        for (j = 0; j < PAF_SOUND_SAMPLES; j++) {
 +            for (k = 0; k < 2; k++) {
 +                *output_samples++ = AV_RL16(buf + *t * 2);
 +                t++;
 +            }
 +        }
 +        buf += PAF_SOUND_FRAME_SIZE;
 +    }
 +
 +    *got_frame_ptr   = 1;
 +
 +    return pkt->size;
 +}
 +
 +AVCodec ff_paf_video_decoder = {
 +    .name           = "paf_video",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PAF_VIDEO,
 +    .priv_data_size = sizeof(PAFVideoDecContext),
 +    .init           = paf_vid_init,
 +    .close          = paf_vid_close,
 +    .decode         = paf_vid_decode,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"),
 +};
 +
 +AVCodec ff_paf_audio_decoder = {
 +    .name           = "paf_audio",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_PAF_AUDIO,
 +    .init           = paf_aud_init,
 +    .decode         = paf_aud_decode,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"),
 +};
Simple merge
Simple merge
  #include "get_bits.h"
  #include "internal.h"
  
- typedef struct PCXContext {
-     AVFrame picture;
- } PCXContext;
- static av_cold int pcx_init(AVCodecContext *avctx)
- {
-     PCXContext *s = avctx->priv_data;
-     avcodec_get_frame_defaults(&s->picture);
-     avctx->coded_frame= &s->picture;
-     return 0;
- }
 -/**
 - * @return advanced src pointer
 - */
 -static const uint8_t *pcx_rle_decode(const uint8_t *src, uint8_t *dst,
 -                            unsigned int bytes_per_scanline, int compressed) {
 +static void pcx_rle_decode(GetByteContext *gb, uint8_t *dst,
 +                           unsigned int bytes_per_scanline, int compressed)
 +{
      unsigned int i = 0;
      unsigned char run, value;
  
@@@ -76,23 -65,19 +62,20 @@@ static void pcx_palette(GetByteContext 
  }
  
  static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
-                             AVPacket *avpkt)
- {
-     PCXContext * const s = avctx->priv_data;
-     AVFrame *picture = data;
-     AVFrame * const p = &s->picture;
+                             AVPacket *avpkt) {
 -    const uint8_t *buf = avpkt->data;
 -    int buf_size = avpkt->size;
 +    GetByteContext gb;
+     AVFrame * const p = data;
 -    int compressed, xmin, ymin, xmax, ymax;
 +    int compressed, xmin, ymin, xmax, ymax, ret;
      unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x,
                   bytes_per_scanline;
 -    uint8_t *ptr;
 -    uint8_t const *bufstart = buf;
 -    uint8_t *scanline;
 -    int ret = -1;
 +    uint8_t *ptr, *scanline;
 +
 +    if (avpkt->size < 128)
 +        return AVERROR_INVALIDDATA;
 +
 +    bytestream2_init(&gb, avpkt->data, avpkt->size);
  
 -    if (buf[0] != 0x0a || buf[1] > 5) {
 +    if (bytestream2_get_byteu(&gb) != 0x0a || bytestream2_get_byteu(&gb) > 5) {
          av_log(avctx, AV_LOG_ERROR, "this is not PCX encoded data\n");
          return AVERROR_INVALIDDATA;
      }
              return AVERROR_INVALIDDATA;
      }
  
 -    buf += 128;
 +    bytestream2_skipu(&gb, 60);
  
-     if (p->data[0])
-         avctx->release_buffer(avctx, p);
      if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
          return ret;
      if (w != avctx->width || h != avctx->height)
          }
      }
  
 +    ret = bytestream2_tell(&gb);
      if (nplanes == 1 && bits_per_pixel == 8) {
 -        pcx_palette(&buf, (uint32_t *) p->data[1], 256);
 +        pcx_palette(&gb, (uint32_t *) p->data[1], 256);
 +        ret += 256 * 3;
 +    } else if (bits_per_pixel * nplanes == 1) {
 +        AV_WN32A(p->data[1]  , 0xFF000000);
 +        AV_WN32A(p->data[1]+4, 0xFFFFFFFF);
      } else if (bits_per_pixel < 8) {
 -        const uint8_t *palette = bufstart+16;
 -        pcx_palette(&palette, (uint32_t *) p->data[1], 16);
 +        bytestream2_seek(&gb, 16, SEEK_SET);
 +        pcx_palette(&gb, (uint32_t *) p->data[1], 16);
      }
  
-     *picture = s->picture;
      *got_frame = 1;
  
 -    ret = buf - bufstart;
  end:
      av_free(scanline);
      return ret;
@@@ -110,9 -102,10 +102,10 @@@ static int decode_frame(AVCodecContext 
                          AVPacket *avpkt)
  {
      PicContext *s = avctx->priv_data;
+     AVFrame *frame = data;
      uint32_t *palette;
      int bits_per_plane, bpp, etype, esize, npal, pos_after_pal;
-     int i, x, y, plane, tmp, val;
 -    int i, x, y, plane, tmp, ret;
++    int i, x, y, plane, tmp, ret, val;
  
      bytestream2_init(&s->g, avpkt->data, avpkt->size);
  
                      break;
  
                  if (bits_per_plane == 8) {
-                     picmemset_8bpp(s, val, run, &x, &y);
+                     picmemset_8bpp(s, frame, val, run, &x, &y);
 -                    if (y < 0)
 -                        break;
                  } else {
-                     picmemset(s, val, run, &x, &y, &plane, bits_per_plane);
+                     picmemset(s, frame, val, run, &x, &y, &plane, bits_per_plane);
                  }
              }
          }
-                 picmemset_8bpp(s, val, run, &x, &y);
 +
 +        if (x < avctx->width && y >= 0) {
 +            int run = (y + 1) * avctx->width - x;
 +            if (bits_per_plane == 8)
-                 picmemset(s, val, run / (8 / bits_per_plane), &x, &y, &plane, bits_per_plane);
++                picmemset_8bpp(s, frame, val, run, &x, &y);
 +            else
++                picmemset(s, frame, val, run / (8 / bits_per_plane), &x, &y, &plane, bits_per_plane);
 +        }
      } else {
 -        av_log_ask_for_sample(s, "uncompressed image\n");
 -        return avpkt->size;
 +        while (y >= 0 && bytestream2_get_bytes_left(&s->g) > 0) {
-             memcpy(s->frame.data[0] + y * s->frame.linesize[0], s->g.buffer, FFMIN(avctx->width, bytestream2_get_bytes_left(&s->g)));
++            memcpy(frame->data[0] + y * frame->linesize[0], s->g.buffer, FFMIN(avctx->width, bytestream2_get_bytes_left(&s->g)));
 +            bytestream2_skip(&s->g, avctx->width);
 +            y--;
 +        }
      }
  
      *got_frame      = 1;
  
  typedef struct PNGDecContext {
      PNGDSPContext dsp;
 +    AVCodecContext *avctx;
  
      GetByteContext gb;
-     AVFrame picture1, picture2;
-     AVFrame *current_picture, *last_picture;
+     AVFrame *prev;
  
      int state;
      int width, height;
@@@ -508,28 -391,18 +507,23 @@@ static int decode_frame(AVCodecContext 
      PNGDecContext * const s = avctx->priv_data;
      const uint8_t *buf      = avpkt->data;
      int buf_size            = avpkt->size;
-     AVFrame *picture        = data;
+     AVFrame *p              = data;
 +    AVDictionary *metadata  = NULL;
      uint8_t *crow_buf_base  = NULL;
-     AVFrame *p;
      uint32_t tag, length;
 +    int64_t sig;
      int ret;
  
-     FFSWAP(AVFrame *, s->current_picture, s->last_picture);
-     avctx->coded_frame = s->current_picture;
-     p = s->current_picture;
 +    bytestream2_init(&s->gb, buf, buf_size);
 +
      /* check signature */
 -    if (buf_size < 8 ||
 -        memcmp(buf, ff_pngsig, 8) != 0 &&
 -        memcmp(buf, ff_mngsig, 8) != 0)
 +    sig = bytestream2_get_be64(&s->gb);
 +    if (sig != PNGSIG &&
 +        sig != MNGSIG) {
 +        av_log(avctx, AV_LOG_ERROR, "Missing png signature\n");
          return -1;
 +    }
  
 -    bytestream2_init(&s->gb, buf + 8, buf_size - 8);
      s->y = s->state = 0;
  
      /* init the zlib */
                             s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
                      avctx->pix_fmt = AV_PIX_FMT_Y400A;
                  } 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 (p->data[0])
-                     avctx->release_buffer(avctx, p);
  
-                 p->reference = 3;
-                 if (ff_get_buffer(avctx, p) < 0) {
+                 if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) {
                      av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                      goto fail;
                  }
          }
      }
   exit_loop:
-         uint8_t *pd = s->current_picture->data[0];
 +
 +    if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE){
 +        int i, j, k;
-         uint8_t *pd = s->current_picture->data[0];
++        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 = s->current_picture->data[0];
++        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->data[0] != NULL) {
+      if (s->prev->data[0]) {
 -         if (!(avpkt->flags & AV_PKT_FLAG_KEY)) {
 +         if (   !(avpkt->flags & AV_PKT_FLAG_KEY)
-             && s->last_picture->width == s->current_picture->width
-             && s->last_picture->height== s->current_picture->height
-             && s->last_picture->format== s->current_picture->format
++            && s->prev->width == p->width
++            && s->prev->height== p->height
++            && s->prev->format== p->format
 +         ) {
              int i, j;
-             uint8_t *pd      = s->current_picture->data[0];
-             uint8_t *pd_last = s->last_picture->data[0];
+             uint8_t *pd      = p->data[0];
+             uint8_t *pd_last = s->prev->data[0];
  
              for (j = 0; j < s->height; j++) {
                  for (i = 0; i < s->width * s->bpp; i++) {
          }
      }
  
-     av_frame_set_metadata(&s->current_picture, metadata);
 -     av_frame_unref(s->prev);
++    av_frame_set_metadata(p, metadata);
 +    metadata   = NULL;
-     *picture   = *s->current_picture;
++
++    av_frame_unref(s->prev);
+      if ((ret = av_frame_ref(s->prev, p)) < 0)
+          goto fail;
      *got_frame = 1;
  
      ret = bytestream2_tell(&s->gb);
Simple merge
Simple merge
@@@ -31,9 -32,8 +31,8 @@@ static int pnm_decode_frame(AVCodecCont
      const uint8_t *buf   = avpkt->data;
      int buf_size         = avpkt->size;
      PNMContext * const s = avctx->priv_data;
-     AVFrame *picture     = data;
-     AVFrame * const p    = &s->picture;
+     AVFrame * const p    = data;
 -    int i, j, n, linesize, h, upgrade = 0;
 +    int i, j, n, linesize, h, upgrade = 0, is_mono = 0;
      unsigned char *ptr;
      int components, sample_len, ret;
  
              }
          }
          break;
 -    case AV_PIX_FMT_RGB32:
 -        ptr      = p->data[0];
 -        linesize = p->linesize[0];
 -        if (s->bytestream + avctx->width * avctx->height * 4 > s->bytestream_end)
 -            return AVERROR_INVALIDDATA;
 -        for (i = 0; i < avctx->height; i++) {
 -            int j, r, g, b, a;
 -
 -            for (j = 0; j < avctx->width; j++) {
 -                r = *s->bytestream++;
 -                g = *s->bytestream++;
 -                b = *s->bytestream++;
 -                a = *s->bytestream++;
 -                ((uint32_t *)ptr)[j] = (a << 24) | (r << 16) | (g << 8) | b;
 -            }
 -            ptr += linesize;
 -        }
 -        break;
      }
-     *picture   = s->picture;
      *got_frame = 1;
  
      return s->bytestream - s->bytestream_start;
index 1c56227,0000000..5a1481c
mode 100644,000000..100644
--- /dev/null
@@@ -1,54 -1,0 +1,54 @@@
-     AVFrame frame;
 +/*
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + * Copyright (c) 2010-2011 Elvis Presley
 + *
 + * 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;
 + * version 2 of the License.
 + *
 + * 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
 + */
 +
 +#ifndef AVCODEC_PRORESDEC_H
 +#define AVCODEC_PRORESDEC_H
 +
 +#include "dsputil.h"
 +#include "proresdsp.h"
 +
 +typedef struct {
 +    const uint8_t *data;
 +    unsigned mb_x;
 +    unsigned mb_y;
 +    unsigned mb_count;
 +    unsigned data_size;
 +    int ret;
 +} SliceContext;
 +
 +typedef struct {
 +    DSPContext dsp;
 +    ProresDSPContext prodsp;
++    AVFrame *frame;
 +    int frame_type;              ///< 0 = progressive, 1 = tff, 2 = bff
 +    uint8_t qmat_luma[64];
 +    uint8_t qmat_chroma[64];
 +    SliceContext *slices;
 +    int slice_count;             ///< number of slices in the current picture
 +    unsigned mb_width;           ///< width of the current picture in mb
 +    unsigned mb_height;          ///< height of the current picture in mb
 +    uint8_t progressive_scan[64];
 +    uint8_t interlaced_scan[64];
 +    const uint8_t *scan;
 +    int first_field;
 +} ProresContext;
 +
 +#endif /* AVCODEC_PRORESDEC_H */
index 4634e70,0000000..b7aef36
mode 100644,000000..100644
--- /dev/null
@@@ -1,605 -1,0 +1,595 @@@
-     avctx->coded_frame = &ctx->frame;
-     ctx->frame.type = AV_PICTURE_TYPE_I;
-     ctx->frame.key_frame = 1;
 +/*
 + * Copyright (c) 2010-2011 Maxim Poliakovski
 + * Copyright (c) 2010-2011 Elvis Presley
 + *
 + * 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
 + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy), 'ap4h' (4444)
 + */
 +
 +//#define DEBUG
 +
 +#define LONG_BITSTREAM_READER
 +
 +#include "avcodec.h"
 +#include "get_bits.h"
 +#include "internal.h"
 +#include "simple_idct.h"
 +#include "proresdec.h"
 +
 +static void permute(uint8_t *dst, const uint8_t *src, const uint8_t permutation[64])
 +{
 +    int i;
 +    for (i = 0; i < 64; i++)
 +        dst[i] = permutation[src[i]];
 +}
 +
 +static const uint8_t progressive_scan[64] = {
 +     0,  1,  8,  9,  2,  3, 10, 11,
 +    16, 17, 24, 25, 18, 19, 26, 27,
 +     4,  5, 12, 20, 13,  6,  7, 14,
 +    21, 28, 29, 22, 15, 23, 30, 31,
 +    32, 33, 40, 48, 41, 34, 35, 42,
 +    49, 56, 57, 50, 43, 36, 37, 44,
 +    51, 58, 59, 52, 45, 38, 39, 46,
 +    53, 60, 61, 54, 47, 55, 62, 63
 +};
 +
 +static const uint8_t interlaced_scan[64] = {
 +     0,  8,  1,  9, 16, 24, 17, 25,
 +     2, 10,  3, 11, 18, 26, 19, 27,
 +    32, 40, 33, 34, 41, 48, 56, 49,
 +    42, 35, 43, 50, 57, 58, 51, 59,
 +     4, 12,  5,  6, 13, 20, 28, 21,
 +    14,  7, 15, 22, 29, 36, 44, 37,
 +    30, 23, 31, 38, 45, 52, 60, 53,
 +    46, 39, 47, 54, 61, 62, 55, 63,
 +};
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    uint8_t idct_permutation[64];
 +
 +    avctx->bits_per_raw_sample = 10;
 +
 +    ff_dsputil_init(&ctx->dsp, avctx);
 +    ff_proresdsp_init(&ctx->prodsp, avctx);
 +
-         ctx->frame.interlaced_frame = 1;
-         ctx->frame.top_field_first = ctx->frame_type == 1;
 +    ff_init_scantable_permutation(idct_permutation,
 +                                  ctx->prodsp.idct_permutation_type);
 +
 +    permute(ctx->progressive_scan, progressive_scan, idct_permutation);
 +    permute(ctx->interlaced_scan, interlaced_scan, idct_permutation);
 +
 +    return 0;
 +}
 +
 +static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 +                               const int data_size, AVCodecContext *avctx)
 +{
 +    int hdr_size, width, height, flags;
 +    int version;
 +    const uint8_t *ptr;
 +
 +    hdr_size = AV_RB16(buf);
 +    av_dlog(avctx, "header size %d\n", hdr_size);
 +    if (hdr_size > data_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong header size\n");
 +        return -1;
 +    }
 +
 +    version = AV_RB16(buf + 2);
 +    av_dlog(avctx, "%.4s version %d\n", buf+4, version);
 +    if (version > 1) {
 +        av_log(avctx, AV_LOG_ERROR, "unsupported version: %d\n", version);
 +        return -1;
 +    }
 +
 +    width  = AV_RB16(buf + 8);
 +    height = AV_RB16(buf + 10);
 +    if (width != avctx->width || height != avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR, "picture resolution change: %dx%d -> %dx%d\n",
 +               avctx->width, avctx->height, width, height);
 +        return -1;
 +    }
 +
 +    ctx->frame_type = (buf[12] >> 2) & 3;
 +
 +    av_dlog(avctx, "frame type %d\n", ctx->frame_type);
 +
 +    if (ctx->frame_type == 0) {
 +        ctx->scan = ctx->progressive_scan; // permuted
 +    } else {
 +        ctx->scan = ctx->interlaced_scan; // permuted
-     AVFrame *pic = avctx->coded_frame;
++        ctx->frame->interlaced_frame = 1;
++        ctx->frame->top_field_first = ctx->frame_type == 1;
 +    }
 +
 +    avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
 +
 +    ptr   = buf + 20;
 +    flags = buf[19];
 +    av_dlog(avctx, "flags %x\n", flags);
 +
 +    if (flags & 2) {
 +        if(buf + data_size - ptr < 64) {
 +            av_log(avctx, AV_LOG_ERROR, "Header truncated\n");
 +            return -1;
 +        }
 +        permute(ctx->qmat_luma, ctx->prodsp.idct_permutation, ptr);
 +        ptr += 64;
 +    } else {
 +        memset(ctx->qmat_luma, 4, 64);
 +    }
 +
 +    if (flags & 1) {
 +        if(buf + data_size - ptr < 64) {
 +            av_log(avctx, AV_LOG_ERROR, "Header truncated\n");
 +            return -1;
 +        }
 +        permute(ctx->qmat_chroma, ctx->prodsp.idct_permutation, ptr);
 +    } else {
 +        memset(ctx->qmat_chroma, 4, 64);
 +    }
 +
 +    return hdr_size;
 +}
 +
 +static int decode_picture_header(AVCodecContext *avctx, const uint8_t *buf, const int buf_size)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i, hdr_size, slice_count;
 +    unsigned pic_data_size;
 +    int log2_slice_mb_width, log2_slice_mb_height;
 +    int slice_mb_count, mb_x, mb_y;
 +    const uint8_t *data_ptr, *index_ptr;
 +
 +    hdr_size = buf[0] >> 3;
 +    if (hdr_size < 8 || hdr_size > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong picture header size\n");
 +        return -1;
 +    }
 +
 +    pic_data_size = AV_RB32(buf + 1);
 +    if (pic_data_size > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong picture data size\n");
 +        return -1;
 +    }
 +
 +    log2_slice_mb_width  = buf[7] >> 4;
 +    log2_slice_mb_height = buf[7] & 0xF;
 +    if (log2_slice_mb_width > 3 || log2_slice_mb_height) {
 +        av_log(avctx, AV_LOG_ERROR, "unsupported slice resolution: %dx%d\n",
 +               1 << log2_slice_mb_width, 1 << log2_slice_mb_height);
 +        return -1;
 +    }
 +
 +    ctx->mb_width  = (avctx->width  + 15) >> 4;
 +    if (ctx->frame_type)
 +        ctx->mb_height = (avctx->height + 31) >> 5;
 +    else
 +        ctx->mb_height = (avctx->height + 15) >> 4;
 +
 +    slice_count = AV_RB16(buf + 5);
 +
 +    if (ctx->slice_count != slice_count || !ctx->slices) {
 +        av_freep(&ctx->slices);
 +        ctx->slices = av_mallocz(slice_count * sizeof(*ctx->slices));
 +        if (!ctx->slices)
 +            return AVERROR(ENOMEM);
 +        ctx->slice_count = slice_count;
 +    }
 +
 +    if (!slice_count)
 +        return AVERROR(EINVAL);
 +
 +    if (hdr_size + slice_count*2 > buf_size) {
 +        av_log(avctx, AV_LOG_ERROR, "error, wrong slice count\n");
 +        return -1;
 +    }
 +
 +    // parse slice information
 +    index_ptr = buf + hdr_size;
 +    data_ptr  = index_ptr + slice_count*2;
 +
 +    slice_mb_count = 1 << log2_slice_mb_width;
 +    mb_x = 0;
 +    mb_y = 0;
 +
 +    for (i = 0; i < slice_count; i++) {
 +        SliceContext *slice = &ctx->slices[i];
 +
 +        slice->data = data_ptr;
 +        data_ptr += AV_RB16(index_ptr + i*2);
 +
 +        while (ctx->mb_width - mb_x < slice_mb_count)
 +            slice_mb_count >>= 1;
 +
 +        slice->mb_x = mb_x;
 +        slice->mb_y = mb_y;
 +        slice->mb_count = slice_mb_count;
 +        slice->data_size = data_ptr - slice->data;
 +
 +        if (slice->data_size < 6) {
 +            av_log(avctx, AV_LOG_ERROR, "error, wrong slice data size\n");
 +            return -1;
 +        }
 +
 +        mb_x += slice_mb_count;
 +        if (mb_x == ctx->mb_width) {
 +            slice_mb_count = 1 << log2_slice_mb_width;
 +            mb_x = 0;
 +            mb_y++;
 +        }
 +        if (data_ptr > buf + buf_size) {
 +            av_log(avctx, AV_LOG_ERROR, "error, slice out of bounds\n");
 +            return -1;
 +        }
 +    }
 +
 +    if (mb_x || mb_y != ctx->mb_height) {
 +        av_log(avctx, AV_LOG_ERROR, "error wrong mb count y %d h %d\n",
 +               mb_y, ctx->mb_height);
 +        return -1;
 +    }
 +
 +    return pic_data_size;
 +}
 +
 +#define DECODE_CODEWORD(val, codebook)                                  \
 +    do {                                                                \
 +        unsigned int rice_order, exp_order, switch_bits;                \
 +        unsigned int q, buf, bits;                                      \
 +                                                                        \
 +        UPDATE_CACHE(re, gb);                                           \
 +        buf = GET_CACHE(re, gb);                                        \
 +                                                                        \
 +        /* number of bits to switch between rice and exp golomb */      \
 +        switch_bits =  codebook & 3;                                    \
 +        rice_order  =  codebook >> 5;                                   \
 +        exp_order   = (codebook >> 2) & 7;                              \
 +                                                                        \
 +        q = 31 - av_log2(buf);                                          \
 +                                                                        \
 +        if (q > switch_bits) { /* exp golomb */                         \
 +            bits = exp_order - switch_bits + (q<<1);                    \
 +            val = SHOW_UBITS(re, gb, bits) - (1 << exp_order) +         \
 +                ((switch_bits + 1) << rice_order);                      \
 +            SKIP_BITS(re, gb, bits);                                    \
 +        } else if (rice_order) {                                        \
 +            SKIP_BITS(re, gb, q+1);                                     \
 +            val = (q << rice_order) + SHOW_UBITS(re, gb, rice_order);   \
 +            SKIP_BITS(re, gb, rice_order);                              \
 +        } else {                                                        \
 +            val = q;                                                    \
 +            SKIP_BITS(re, gb, q+1);                                     \
 +        }                                                               \
 +    } while (0)
 +
 +#define TOSIGNED(x) (((x) >> 1) ^ (-((x) & 1)))
 +
 +#define FIRST_DC_CB 0xB8
 +
 +static const uint8_t dc_codebook[7] = { 0x04, 0x28, 0x28, 0x4D, 0x4D, 0x70, 0x70};
 +
 +static av_always_inline void decode_dc_coeffs(GetBitContext *gb, int16_t *out,
 +                                              int blocks_per_slice)
 +{
 +    int16_t prev_dc;
 +    int code, i, sign;
 +
 +    OPEN_READER(re, gb);
 +
 +    DECODE_CODEWORD(code, FIRST_DC_CB);
 +    prev_dc = TOSIGNED(code);
 +    out[0] = prev_dc;
 +
 +    out += 64; // dc coeff for the next block
 +
 +    code = 5;
 +    sign = 0;
 +    for (i = 1; i < blocks_per_slice; i++, out += 64) {
 +        DECODE_CODEWORD(code, dc_codebook[FFMIN(code, 6U)]);
 +        if(code) sign ^= -(code & 1);
 +        else     sign  = 0;
 +        prev_dc += (((code + 1) >> 1) ^ sign) - sign;
 +        out[0] = prev_dc;
 +    }
 +    CLOSE_READER(re, gb);
 +}
 +
 +// adaptive codebook switching lut according to previous run/level values
 +static const uint8_t run_to_cb[16] = { 0x06, 0x06, 0x05, 0x05, 0x04, 0x29, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +static const uint8_t lev_to_cb[10] = { 0x04, 0x0A, 0x05, 0x06, 0x04, 0x28, 0x28, 0x28, 0x28, 0x4C };
 +
 +static av_always_inline void decode_ac_coeffs(AVCodecContext *avctx, GetBitContext *gb,
 +                                              int16_t *out, int blocks_per_slice)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int block_mask, sign;
 +    unsigned pos, run, level;
 +    int max_coeffs, i, bits_left;
 +    int log2_block_count = av_log2(blocks_per_slice);
 +
 +    OPEN_READER(re, gb);
 +    UPDATE_CACHE(re, gb);                                           \
 +    run   = 4;
 +    level = 2;
 +
 +    max_coeffs = 64 << log2_block_count;
 +    block_mask = blocks_per_slice - 1;
 +
 +    for (pos = block_mask;;) {
 +        bits_left = gb->size_in_bits - re_index;
 +        if (!bits_left || (bits_left < 32 && !SHOW_UBITS(re, gb, bits_left)))
 +            break;
 +
 +        DECODE_CODEWORD(run, run_to_cb[FFMIN(run,  15)]);
 +        pos += run + 1;
 +        if (pos >= max_coeffs) {
 +            av_log(avctx, AV_LOG_ERROR, "ac tex damaged %d, %d\n", pos, max_coeffs);
 +            return;
 +        }
 +
 +        DECODE_CODEWORD(level, lev_to_cb[FFMIN(level, 9)]);
 +        level += 1;
 +
 +        i = pos >> log2_block_count;
 +
 +        sign = SHOW_SBITS(re, gb, 1);
 +        SKIP_BITS(re, gb, 1);
 +        out[((pos & block_mask) << 6) + ctx->scan[i]] = ((level ^ sign) - sign);
 +    }
 +
 +    CLOSE_READER(re, gb);
 +}
 +
 +static void decode_slice_luma(AVCodecContext *avctx, SliceContext *slice,
 +                              uint16_t *dst, int dst_stride,
 +                              const uint8_t *buf, unsigned buf_size,
 +                              const int16_t *qmat)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
 +    int16_t *block;
 +    GetBitContext gb;
 +    int i, blocks_per_slice = slice->mb_count<<2;
 +
 +    for (i = 0; i < blocks_per_slice; i++)
 +        ctx->dsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    decode_dc_coeffs(&gb, blocks, blocks_per_slice);
 +    decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice);
 +
 +    block = blocks;
 +    for (i = 0; i < slice->mb_count; i++) {
 +        ctx->prodsp.idct_put(dst, dst_stride, block+(0<<6), qmat);
 +        ctx->prodsp.idct_put(dst             +8, dst_stride, block+(1<<6), qmat);
 +        ctx->prodsp.idct_put(dst+4*dst_stride  , dst_stride, block+(2<<6), qmat);
 +        ctx->prodsp.idct_put(dst+4*dst_stride+8, dst_stride, block+(3<<6), qmat);
 +        block += 4*64;
 +        dst += 16;
 +    }
 +}
 +
 +static void decode_slice_chroma(AVCodecContext *avctx, SliceContext *slice,
 +                                uint16_t *dst, int dst_stride,
 +                                const uint8_t *buf, unsigned buf_size,
 +                                const int16_t *qmat, int log2_blocks_per_mb)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    LOCAL_ALIGNED_16(int16_t, blocks, [8*4*64]);
 +    int16_t *block;
 +    GetBitContext gb;
 +    int i, j, blocks_per_slice = slice->mb_count << log2_blocks_per_mb;
 +
 +    for (i = 0; i < blocks_per_slice; i++)
 +        ctx->dsp.clear_block(blocks+(i<<6));
 +
 +    init_get_bits(&gb, buf, buf_size << 3);
 +
 +    decode_dc_coeffs(&gb, blocks, blocks_per_slice);
 +    decode_ac_coeffs(avctx, &gb, blocks, blocks_per_slice);
 +
 +    block = blocks;
 +    for (i = 0; i < slice->mb_count; i++) {
 +        for (j = 0; j < log2_blocks_per_mb; j++) {
 +            ctx->prodsp.idct_put(dst,              dst_stride, block+(0<<6), qmat);
 +            ctx->prodsp.idct_put(dst+4*dst_stride, dst_stride, block+(1<<6), qmat);
 +            block += 2*64;
 +            dst += 8;
 +        }
 +    }
 +}
 +
 +static int decode_slice_thread(AVCodecContext *avctx, void *arg, int jobnr, int threadnr)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    SliceContext *slice = &ctx->slices[jobnr];
 +    const uint8_t *buf = slice->data;
-     if (ctx->frame_type && ctx->first_field ^ ctx->frame.top_field_first) {
++    AVFrame *pic = ctx->frame;
 +    int i, hdr_size, qscale, log2_chroma_blocks_per_mb;
 +    int luma_stride, chroma_stride;
 +    int y_data_size, u_data_size, v_data_size;
 +    uint8_t *dest_y, *dest_u, *dest_v;
 +    int16_t qmat_luma_scaled[64];
 +    int16_t qmat_chroma_scaled[64];
 +    int mb_x_shift;
 +
 +    slice->ret = -1;
 +    //av_log(avctx, AV_LOG_INFO, "slice %d mb width %d mb x %d y %d\n",
 +    //       jobnr, slice->mb_count, slice->mb_x, slice->mb_y);
 +
 +    // slice header
 +    hdr_size = buf[0] >> 3;
 +    qscale = av_clip(buf[1], 1, 224);
 +    qscale = qscale > 128 ? qscale - 96 << 2: qscale;
 +    y_data_size = AV_RB16(buf + 2);
 +    u_data_size = AV_RB16(buf + 4);
 +    v_data_size = slice->data_size - y_data_size - u_data_size - hdr_size;
 +    if (hdr_size > 7) v_data_size = AV_RB16(buf + 6);
 +
 +    if (y_data_size < 0 || u_data_size < 0 || v_data_size < 0
 +        || hdr_size+y_data_size+u_data_size+v_data_size > slice->data_size){
 +        av_log(avctx, AV_LOG_ERROR, "invalid plane data size\n");
 +        return -1;
 +    }
 +
 +    buf += hdr_size;
 +
 +    for (i = 0; i < 64; i++) {
 +        qmat_luma_scaled  [i] = ctx->qmat_luma  [i] * qscale;
 +        qmat_chroma_scaled[i] = ctx->qmat_chroma[i] * qscale;
 +    }
 +
 +    if (ctx->frame_type == 0) {
 +        luma_stride   = pic->linesize[0];
 +        chroma_stride = pic->linesize[1];
 +    } else {
 +        luma_stride   = pic->linesize[0] << 1;
 +        chroma_stride = pic->linesize[1] << 1;
 +    }
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_YUV444P10) {
 +        mb_x_shift = 5;
 +        log2_chroma_blocks_per_mb = 2;
 +    } else {
 +        mb_x_shift = 4;
 +        log2_chroma_blocks_per_mb = 1;
 +    }
 +
 +    dest_y = pic->data[0] + (slice->mb_y << 4) * luma_stride + (slice->mb_x << 5);
 +    dest_u = pic->data[1] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
 +    dest_v = pic->data[2] + (slice->mb_y << 4) * chroma_stride + (slice->mb_x << mb_x_shift);
 +
-     AVFrame *frame = avctx->coded_frame;
++    if (ctx->frame_type && ctx->first_field ^ ctx->frame->top_field_first) {
 +        dest_y += pic->linesize[0];
 +        dest_u += pic->linesize[1];
 +        dest_v += pic->linesize[2];
 +    }
 +
 +    decode_slice_luma(avctx, slice, (uint16_t*)dest_y, luma_stride,
 +                      buf, y_data_size, qmat_luma_scaled);
 +
 +    if (!(avctx->flags & CODEC_FLAG_GRAY)) {
 +        decode_slice_chroma(avctx, slice, (uint16_t*)dest_u, chroma_stride,
 +                            buf + y_data_size, u_data_size,
 +                            qmat_chroma_scaled, log2_chroma_blocks_per_mb);
 +        decode_slice_chroma(avctx, slice, (uint16_t*)dest_v, chroma_stride,
 +                            buf + y_data_size + u_data_size, v_data_size,
 +                            qmat_chroma_scaled, log2_chroma_blocks_per_mb);
 +    }
 +
 +    slice->ret = 0;
 +    return 0;
 +}
 +
 +static int decode_picture(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +    int i;
 +
 +    avctx->execute2(avctx, decode_slice_thread, NULL, NULL, ctx->slice_count);
 +
 +    for (i = 0; i < ctx->slice_count; i++)
 +        if (ctx->slices[i].ret < 0)
 +            return ctx->slices[i].ret;
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    ProresContext *ctx = avctx->priv_data;
-     if (frame->data[0])
-         avctx->release_buffer(avctx, frame);
-     if (ff_get_buffer(avctx, frame) < 0)
++    AVFrame *frame = data;
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    int frame_hdr_size, pic_size;
 +
 +    if (buf_size < 28 || AV_RL32(buf + 4) != AV_RL32("icpf")) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid frame header\n");
 +        return -1;
 +    }
 +
++    ctx->frame = frame;
 +    ctx->first_field = 1;
 +
 +    buf += 8;
 +    buf_size -= 8;
 +
 +    frame_hdr_size = decode_frame_header(ctx, buf, buf_size, avctx);
 +    if (frame_hdr_size < 0)
 +        return -1;
 +
 +    buf += frame_hdr_size;
 +    buf_size -= frame_hdr_size;
 +
-     *(AVFrame*)data = *frame;
++    if (ff_get_buffer(avctx, frame, 0) < 0)
 +        return -1;
 +
 + decode_picture:
 +    pic_size = decode_picture_header(avctx, buf, buf_size);
 +    if (pic_size < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "error decoding picture header\n");
 +        return -1;
 +    }
 +
 +    if (decode_picture(avctx)) {
 +        av_log(avctx, AV_LOG_ERROR, "error decoding picture\n");
 +        return -1;
 +    }
 +
 +    buf += pic_size;
 +    buf_size -= pic_size;
 +
 +    if (ctx->frame_type && buf_size > 0 && ctx->first_field) {
 +        ctx->first_field = 0;
 +        goto decode_picture;
 +    }
 +
 +    *got_frame      = 1;
-     AVFrame *frame = avctx->coded_frame;
-     if (frame->data[0])
-         avctx->release_buffer(avctx, frame);
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int decode_close(AVCodecContext *avctx)
 +{
 +    ProresContext *ctx = avctx->priv_data;
 +
 +    av_freep(&ctx->slices);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_prores_decoder = {
 +    .name           = "prores",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_PRORES,
 +    .priv_data_size = sizeof(ProresContext),
 +    .init           = decode_init,
 +    .close          = decode_close,
 +    .decode         = decode_frame,
 +    .long_name      = NULL_IF_CONFIG_SMALL("ProRes"),
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
 +};
@@@ -86,13 -86,8 +86,8 @@@ static av_cold int decode_init(AVCodecC
      ctx->slice_data       = NULL;
  
      avctx->bits_per_raw_sample = PRORES_BITS_PER_SAMPLE;
 -    ff_proresdsp_init(&ctx->dsp);
 +    ff_proresdsp_init(&ctx->dsp, avctx);
  
-     avctx->coded_frame = &ctx->picture;
-     avcodec_get_frame_defaults(&ctx->picture);
-     ctx->picture.type      = AV_PICTURE_TYPE_I;
-     ctx->picture.key_frame = 1;
      ctx->scantable_type = -1;   // set scantable type to uninitialized
      memset(ctx->qmat_luma, 4, 64);
      memset(ctx->qmat_chroma, 4, 64);
@@@ -396,19 -378,14 +390,21 @@@ static attribute_align_arg void *frame_
  
          if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx);
  
 +        pthread_mutex_lock(&p->progress_mutex);
++#if 0 //BUFREF-FIXME
 +        for (i = 0; i < MAX_BUFFERS; i++)
 +            if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) {
 +                p->progress[i][0] = INT_MAX;
 +                p->progress[i][1] = INT_MAX;
 +            }
++#endif
          p->state = STATE_INPUT_READY;
  
 -        pthread_mutex_lock(&p->progress_mutex);
 +        pthread_cond_broadcast(&p->progress_cond);
          pthread_cond_signal(&p->output_cond);
          pthread_mutex_unlock(&p->progress_mutex);
 -
 -        pthread_mutex_unlock(&p->mutex);
      }
 +    pthread_mutex_unlock(&p->mutex);
  
      return NULL;
  }
@@@ -681,10 -656,10 +677,10 @@@ int ff_thread_decode_frame(AVCodecConte
      return (p->result >= 0) ? avpkt->size : p->result;
  }
  
- void ff_thread_report_progress(AVFrame *f, int n, int field)
+ void ff_thread_report_progress(ThreadFrame *f, int n, int field)
  {
      PerThreadContext *p;
-     volatile int *progress = f->thread_opaque;
 -    int *progress = f->progress ? (int*)f->progress->data : NULL;
++    volatile int *progress = f->progress ? (int*)f->progress->data : NULL;
  
      if (!progress || progress[field] >= n) return;
  
      pthread_mutex_unlock(&p->progress_mutex);
  }
  
- void ff_thread_await_progress(AVFrame *f, int n, int field)
+ void ff_thread_await_progress(ThreadFrame *f, int n, int field)
  {
      PerThreadContext *p;
-     volatile int *progress = f->thread_opaque;
 -    int *progress = f->progress ? (int*)f->progress->data : NULL;
++    volatile int *progress = f->progress ? (int*)f->progress->data : NULL;
  
      if (!progress || progress[field] >= n) return;
  
@@@ -934,75 -894,46 +929,61 @@@ void ff_thread_flush(AVCodecContext *av
      }
  }
  
- static volatile int *allocate_progress(PerThreadContext *p)
- {
-     int i;
-     for (i = 0; i < MAX_BUFFERS; i++)
-         if (!p->progress_used[i]) break;
-     if (i == MAX_BUFFERS) {
-         av_log(p->avctx, AV_LOG_ERROR, "allocate_progress() overflow\n");
-         return NULL;
-     }
-     p->progress_used[i] = 1;
-     return p->progress[i];
- }
 +int ff_thread_can_start_frame(AVCodecContext *avctx)
 +{
 +    PerThreadContext *p = avctx->thread_opaque;
 +    if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP &&
 +        (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks &&
 +                avctx->get_buffer != avcodec_default_get_buffer))) {
 +        return 0;
 +    }
 +    return 1;
 +}
 +
- int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
+ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
  {
      PerThreadContext *p = avctx->thread_opaque;
      int err;
  
      f->owner = avctx;
  
-     ff_init_buffer_info(avctx, f);
++    ff_init_buffer_info(avctx, f->f);
 +
-     if (!(avctx->active_thread_type&FF_THREAD_FRAME)) {
-         f->thread_opaque = NULL;
-         return ff_get_buffer(avctx, f);
-     }
+     if (!(avctx->active_thread_type & FF_THREAD_FRAME))
+         return ff_get_buffer(avctx, f->f, flags);
  
      if (p->state != STATE_SETTING_UP &&
 -        (avctx->codec->update_thread_context || !avctx->thread_safe_callbacks)) {
 +        (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks &&
 +                avctx->get_buffer != avcodec_default_get_buffer))) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n");
          return -1;
      }
  
-     pthread_mutex_lock(&p->parent->buffer_mutex);
-     f->thread_opaque = (int*)(progress = allocate_progress(p));
+     if (avctx->internal->allocate_progress) {
+         int *progress;
+         f->progress = av_buffer_alloc(2 * sizeof(int));
+         if (!f->progress) {
+             return AVERROR(ENOMEM);
+         }
+         progress = (int*)f->progress->data;
  
-     if (!progress) {
-         pthread_mutex_unlock(&p->parent->buffer_mutex);
-         return -1;
+         progress[0] = progress[1] = -1;
      }
  
-     progress[0] =
-     progress[1] = -1;
+     pthread_mutex_lock(&p->parent->buffer_mutex);
 +
-     if (avctx->thread_safe_callbacks ||
-         avctx->get_buffer == avcodec_default_get_buffer) {
-         err = ff_get_buffer(avctx, f);
+     if (avctx->thread_safe_callbacks || (
+ #if FF_API_GET_BUFFER
+         !avctx->get_buffer &&
+ #endif
+         avctx->get_buffer2 == avcodec_default_get_buffer2)) {
+         err = ff_get_buffer(avctx, f->f, flags);
      } else {
-         p->requested_frame = f;
 +        pthread_mutex_lock(&p->progress_mutex);
+         p->requested_frame = f->f;
+         p->requested_flags = flags;
          p->state = STATE_GET_BUFFER;
 -        pthread_mutex_lock(&p->progress_mutex);
 -        pthread_cond_signal(&p->progress_cond);
 +        pthread_cond_broadcast(&p->progress_cond);
  
          while (p->state != STATE_SETTING_UP)
              pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -267,14 -257,8 +267,12 @@@ static int decode_frame(AVCodecContext 
      }
  
      bytestream2_init(&a->buffer, avpkt->data, avpkt->size);
 -    if ((ret = ff_reget_buffer(avctx, p)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 +
-     if(ref->data[0])
-         avctx->release_buffer(avctx, ref);
-     FFSWAP(AVFrame, *ref, *p);
++    av_frame_unref(ref);
++    av_frame_move_ref(ref, p);
 +
-     p->reference= 3;
-     if ((ret = ff_get_buffer(avctx, p)) < 0) {
++    if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
      outdata = a->pic.data[0];
@@@ -330,13 -301,10 +330,11 @@@ static av_cold int decode_init(AVCodecC
  static av_cold int decode_end(AVCodecContext *avctx){
      QpegContext * const a = avctx->priv_data;
      AVFrame * const p = &a->pic;
 +    AVFrame * const ref= &a->ref;
  
-     if(p->data[0])
-         avctx->release_buffer(avctx, p);
-     if(ref->data[0])
-         avctx->release_buffer(avctx, ref);
+     av_frame_unref(p);
++    av_frame_unref(ref);
  
 -    av_free(a->refdata);
      return 0;
  }
  
Simple merge
@@@ -41,15 -37,11 +37,12 @@@ static int decode_frame(AVCodecContext 
                          AVPacket *avpkt)
  {
      int h, w, ret;
-     AVFrame *pic = avctx->coded_frame;
+     AVFrame *pic = data;
      const uint32_t *src = (const uint32_t *)avpkt->data;
 -    int aligned_width = FFALIGN(avctx->width, 64);
 +    int aligned_width = FFALIGN(avctx->width,
 +                                avctx->codec_id == AV_CODEC_ID_R10K ? 1 : 64);
      uint8_t *dst_line;
  
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
      if (avpkt->size < 4 * aligned_width * avctx->height) {
          av_log(avctx, AV_LOG_ERROR, "packet too small\n");
          return AVERROR_INVALIDDATA;
@@@ -130,15 -103,3 +109,14 @@@ AVCodec ff_r10k_decoder = 
      .long_name      = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"),
  };
  #endif
-     .close          = decode_close,
 +#if CONFIG_AVRP_DECODER
 +AVCodec ff_avrp_decoder = {
 +    .name           = "avrp",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_AVRP,
 +    .init           = decode_init,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"),
 +};
 +#endif
Simple merge
Simple merge
@@@ -254,25 -208,7 +250,26 @@@ static int raw_decode(AVCodecContext *a
              frame->palette_has_changed = 1;
          }
      }
 +    if ((avctx->pix_fmt==AV_PIX_FMT_BGR24    ||
 +        avctx->pix_fmt==AV_PIX_FMT_GRAY8    ||
 +        avctx->pix_fmt==AV_PIX_FMT_RGB555LE ||
 +        avctx->pix_fmt==AV_PIX_FMT_RGB555BE ||
 +        avctx->pix_fmt==AV_PIX_FMT_RGB565LE ||
 +        avctx->pix_fmt==AV_PIX_FMT_MONOWHITE ||
 +        avctx->pix_fmt==AV_PIX_FMT_PAL8) &&
 +        FFALIGN(frame->linesize[0], linesize_align) * avctx->height <= buf_size)
 +        frame->linesize[0] = FFALIGN(frame->linesize[0], linesize_align);
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_NV12 && avctx->codec_tag == MKTAG('N', 'V', '1', '2') &&
 +        FFALIGN(frame->linesize[0], linesize_align) * avctx->height +
 +        FFALIGN(frame->linesize[1], linesize_align) * ((avctx->height + 1) / 2) <= buf_size) {
 +        int la0 = FFALIGN(frame->linesize[0], linesize_align);
 +        frame->data[1] += (la0 - frame->linesize[0]) * avctx->height;
 +        frame->linesize[0] = la0;
 +        frame->linesize[1] = FFALIGN(frame->linesize[1], linesize_align);
 +    }
 +
      if ((avctx->pix_fmt == AV_PIX_FMT_PAL8 && buf_size < context->frame_size) ||
          (desc->flags & PIX_FMT_PSEUDOPAL)) {
          frame->buf[1]  = av_buffer_ref(context->palette);
              return AVERROR(ENOMEM);
          frame->data[1] = frame->buf[1]->data;
      }
++
      if (avctx->pix_fmt == AV_PIX_FMT_BGR24 &&
          ((frame->linesize[0] + 3) & ~3) * avctx->height <= buf_size)
          frame->linesize[0] = (frame->linesize[0] + 3) & ~3;
Simple merge
   *   http://www.csse.monash.edu.au/~timf/
   */
  
 -#include <stdio.h>
 -#include <stdlib.h>
 -#include <string.h>
 -
 +#include "libavutil/avassert.h"
  #include "avcodec.h"
  #include "bytestream.h"
+ #include "internal.h"
  #include "roqvideo.h"
  
  static void roqvideo_decode_frame(RoqContext *ri)
@@@ -198,9 -193,8 +204,8 @@@ static int roq_decode_frame(AVCodecCont
      int copy= !s->current_frame->data[0];
      int ret;
  
-     s->current_frame->reference = 3;
-     if ((ret = avctx->reget_buffer(avctx, s->current_frame)) < 0) {
+     if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "  RoQ: get_buffer() failed\n");
 +        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index caeaa36,0000000..8268730
mode 100644,000000..100644
--- /dev/null
@@@ -1,1311 -1,0 +1,1302 @@@
-     AVFrame frame, *output;
 +/*
 + * LucasArts Smush video decoder
 + * Copyright (c) 2006 Cyril Zorin
 + * Copyright (c) 2011 Konstantin Shishkov
 + *
 + * 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
 + */
 +
 +// #define DEBUG 1
 +
 +#include "avcodec.h"
 +#include "copy_block.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "libavutil/bswap.h"
 +#include "libavutil/imgutils.h"
 +#include "sanm_data.h"
 +#include "libavutil/avassert.h"
 +
 +#define NGLYPHS 256
 +
 +typedef struct {
 +    AVCodecContext *avctx;
 +    GetByteContext gb;
 +
 +    int version, subversion;
 +    uint32_t pal[256];
 +    int16_t delta_pal[768];
 +
 +    int pitch;
 +    int width, height;
 +    int aligned_width, aligned_height;
 +    int prev_seq;
 +
-     ctx->output          = &ctx->frame;
-     ctx->output->data[0] = 0;
++    AVFrame *frame;
 +    uint16_t *frm0, *frm1, *frm2;
 +    uint8_t *stored_frame;
 +    uint32_t frm0_size, frm1_size, frm2_size;
 +    uint32_t stored_frame_size;
 +
 +    uint8_t *rle_buf;
 +    unsigned int rle_buf_size;
 +
 +    int rotate_code;
 +
 +    long npixels, buf_size;
 +
 +    uint16_t codebook[256];
 +    uint16_t small_codebook[4];
 +
 +    int8_t p4x4glyphs[NGLYPHS][16];
 +    int8_t p8x8glyphs[NGLYPHS][64];
 +} SANMVideoContext;
 +
 +typedef struct {
 +    int seq_num, codec, rotate_code, rle_output_size;
 +
 +    uint16_t bg_color;
 +    uint32_t width, height;
 +} SANMFrameHeader;
 +
 +enum GlyphEdge {
 +    LEFT_EDGE,
 +    TOP_EDGE,
 +    RIGHT_EDGE,
 +    BOTTOM_EDGE,
 +    NO_EDGE
 +};
 +
 +enum GlyphDir {
 +    DIR_LEFT,
 +    DIR_UP,
 +    DIR_RIGHT,
 +    DIR_DOWN,
 +    NO_DIR
 +};
 +
 +/**
 + * Return enum GlyphEdge of box where point (x, y) lies.
 + *
 + * @param x x point coordinate
 + * @param y y point coordinate
 + * @param edge_size box width/height.
 + */
 +static enum GlyphEdge which_edge(int x, int y, int edge_size)
 +{
 +    const int edge_max = edge_size - 1;
 +
 +    if (!y) {
 +        return BOTTOM_EDGE;
 +    } else if (y == edge_max) {
 +        return TOP_EDGE;
 +    } else if (!x) {
 +        return LEFT_EDGE;
 +    } else if (x == edge_max) {
 +        return RIGHT_EDGE;
 +    } else {
 +        return NO_EDGE;
 +    }
 +}
 +
 +static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
 +{
 +    if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
 +        (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
 +        (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
 +        (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE)) {
 +        return DIR_UP;
 +    } else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
 +               (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE)) {
 +        return DIR_DOWN;
 +    } else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
 +               (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE)) {
 +        return DIR_LEFT;
 +    } else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
 +               (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
 +               (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
 +               (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE)) {
 +        return DIR_RIGHT;
 +    }
 +
 +    return NO_DIR;
 +}
 +
 +/**
 + * Interpolate two points.
 + */
 +static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
 +                         int pos, int npoints)
 +{
 +    if (npoints) {
 +        points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
 +        points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
 +    } else {
 +        points[0] = x0;
 +        points[1] = y0;
 +    }
 +}
 +
 +/**
 + * Construct glyphs by iterating through vectors coordinates.
 + *
 + * @param pglyphs pointer to table where glyphs are stored
 + * @param xvec pointer to x component of vectors coordinates
 + * @param yvec pointer to y component of vectors coordinates
 + * @param side_length glyph width/height.
 + */
 +static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
 +                        const int side_length)
 +{
 +    const int glyph_size = side_length * side_length;
 +    int8_t *pglyph = pglyphs;
 +
 +    int i, j;
 +    for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
 +        int x0    = xvec[i];
 +        int y0    = yvec[i];
 +        enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
 +
 +        for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
 +            int x1      = xvec[j];
 +            int y1      = yvec[j];
 +            enum GlyphEdge edge1   = which_edge(x1, y1, side_length);
 +            enum GlyphDir  dir     = which_direction(edge0, edge1);
 +            int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
 +            int ipoint;
 +
 +            for (ipoint = 0; ipoint <= npoints; ipoint++) {
 +                int8_t point[2];
 +                int irow, icol;
 +
 +                interp_point(point, x0, y0, x1, y1, ipoint, npoints);
 +
 +                switch (dir) {
 +                case DIR_UP:
 +                    for (irow = point[1]; irow >= 0; irow--)
 +                        pglyph[point[0] + irow * side_length] = 1;
 +                    break;
 +
 +                case DIR_DOWN:
 +                    for (irow = point[1]; irow < side_length; irow++)
 +                        pglyph[point[0] + irow * side_length] = 1;
 +                    break;
 +
 +                case DIR_LEFT:
 +                    for (icol = point[0]; icol >= 0; icol--)
 +                        pglyph[icol + point[1] * side_length] = 1;
 +                    break;
 +
 +                case DIR_RIGHT:
 +                    for (icol = point[0]; icol < side_length; icol++)
 +                        pglyph[icol + point[1] * side_length] = 1;
 +                    break;
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +static void init_sizes(SANMVideoContext *ctx, int width, int height)
 +{
 +    ctx->width   = width;
 +    ctx->height  = height;
 +    ctx->npixels = width * height;
 +
 +    ctx->aligned_width  = FFALIGN(width,  8);
 +    ctx->aligned_height = FFALIGN(height, 8);
 +
 +    ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
 +    ctx->pitch    = width;
 +}
 +
 +static void destroy_buffers(SANMVideoContext *ctx)
 +{
 +    av_freep(&ctx->frm0);
 +    av_freep(&ctx->frm1);
 +    av_freep(&ctx->frm2);
 +    av_freep(&ctx->stored_frame);
 +    av_freep(&ctx->rle_buf);
 +    ctx->frm0_size =
 +    ctx->frm1_size =
 +    ctx->frm2_size = 0;
 +}
 +
 +static av_cold int init_buffers(SANMVideoContext *ctx)
 +{
 +    av_fast_padded_malloc(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
 +    av_fast_padded_malloc(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
 +    av_fast_padded_malloc(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
 +    if (!ctx->version)
 +        av_fast_padded_malloc(&ctx->stored_frame, &ctx->stored_frame_size, ctx->buf_size);
 +
 +    if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || (!ctx->stored_frame && !ctx->version)) {
 +        destroy_buffers(ctx);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    return 0;
 +}
 +
 +static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
 +{
 +    av_dlog(ctx->avctx, "rotate %d\n", rotate_code);
 +    if (rotate_code == 2)
 +        FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
 +    FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
 +}
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    SANMVideoContext *ctx = avctx->priv_data;
 +
 +    ctx->avctx     = avctx;
 +    ctx->version   = !avctx->extradata_size;
 +
 +    avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
 +
 +    init_sizes(ctx, avctx->width, avctx->height);
 +    if (init_buffers(ctx)) {
 +        av_log(avctx, AV_LOG_ERROR, "error allocating buffers\n");
 +        return AVERROR(ENOMEM);
 +    }
-     if (ctx->frame.data[0]) {
-         avctx->release_buffer(avctx, &ctx->frame);
-         ctx->frame.data[0] = 0;
-     }
 +
 +    make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
 +    make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
 +
 +    if (!ctx->version) {
 +        int i;
 +
 +        if (avctx->extradata_size < 1026) {
 +            av_log(avctx, AV_LOG_ERROR, "not enough extradata\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        ctx->subversion = AV_RL16(avctx->extradata);
 +        for (i = 0; i < 256; i++)
 +            ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold int decode_end(AVCodecContext *avctx)
 +{
 +    SANMVideoContext *ctx = avctx->priv_data;
 +
 +    destroy_buffers(ctx);
 +
-     if ((ret = ff_get_buffer(ctx->avctx, ctx->output)) < 0) {
 +    return 0;
 +}
 +
 +static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
 +{
 +    int opcode, color, run_len, left = out_size;
 +
 +    while (left > 0) {
 +        opcode = bytestream2_get_byte(&ctx->gb);
 +        run_len = (opcode >> 1) + 1;
 +        if (run_len > left || bytestream2_get_bytes_left(&ctx->gb) <= 0)
 +            return AVERROR_INVALIDDATA;
 +
 +        if (opcode & 1) {
 +            color = bytestream2_get_byte(&ctx->gb);
 +            memset(dst, color, run_len);
 +        } else {
 +            if (bytestream2_get_bytes_left(&ctx->gb) < run_len)
 +                return AVERROR_INVALIDDATA;
 +            bytestream2_get_bufferu(&ctx->gb, dst, run_len);
 +        }
 +
 +        dst  += run_len;
 +        left -= run_len;
 +    }
 +
 +    return 0;
 +}
 +
 +static int old_codec1(SANMVideoContext *ctx, int top,
 +                      int left, int width, int height)
 +{
 +    uint8_t *dst = ((uint8_t*)ctx->frm0) + left + top * ctx->pitch;
 +    int i, j, len, flag, code, val, pos, end;
 +
 +    for (i = 0; i < height; i++) {
 +        pos = 0;
 +
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 2)
 +            return AVERROR_INVALIDDATA;
 +
 +        len = bytestream2_get_le16u(&ctx->gb);
 +        end = bytestream2_tell(&ctx->gb) + len;
 +
 +        while (bytestream2_tell(&ctx->gb) < end) {
 +            if (bytestream2_get_bytes_left(&ctx->gb) < 2)
 +                return AVERROR_INVALIDDATA;
 +
 +            code = bytestream2_get_byteu(&ctx->gb);
 +            flag = code & 1;
 +            code = (code >> 1) + 1;
 +            if (pos + code > width)
 +                return AVERROR_INVALIDDATA;
 +            if (flag) {
 +                val = bytestream2_get_byteu(&ctx->gb);
 +                if (val)
 +                    memset(dst + pos, val, code);
 +                pos += code;
 +            } else {
 +                if (bytestream2_get_bytes_left(&ctx->gb) < code)
 +                    return AVERROR_INVALIDDATA;
 +                for (j = 0; j < code; j++) {
 +                    val = bytestream2_get_byteu(&ctx->gb);
 +                    if (val)
 +                        dst[pos] = val;
 +                    pos++;
 +                }
 +            }
 +        }
 +        dst += ctx->pitch;
 +    }
 +    ctx->rotate_code = 0;
 +
 +    return 0;
 +}
 +
 +static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
 +                              int height, int stride, int x, int y)
 +{
 +    int pos, i, j;
 +
 +    pos = x + y * stride;
 +    for (j = 0; j < 4; j++) {
 +        for (i = 0; i < 4; i++) {
 +            if ((pos + i) < 0 || (pos + i) >= height * stride)
 +                dst[i] = 0;
 +            else
 +                dst[i] = src[i];
 +        }
 +        dst += stride;
 +        src += stride;
 +        pos += stride;
 +    }
 +}
 +
 +static int old_codec37(SANMVideoContext *ctx, int top,
 +                       int left, int width, int height)
 +{
 +    int stride = ctx->pitch;
 +    int i, j, k, t;
 +    int skip_run = 0;
 +    int compr, mvoff, seq, flags;
 +    uint32_t decoded_size;
 +    uint8_t *dst, *prev;
 +
 +    compr        = bytestream2_get_byte(&ctx->gb);
 +    mvoff        = bytestream2_get_byte(&ctx->gb);
 +    seq          = bytestream2_get_le16(&ctx->gb);
 +    decoded_size = bytestream2_get_le32(&ctx->gb);
 +    bytestream2_skip(&ctx->gb, 4);
 +    flags        = bytestream2_get_byte(&ctx->gb);
 +    bytestream2_skip(&ctx->gb, 3);
 +
 +    if (decoded_size > ctx->height * stride - left - top * stride) {
 +        decoded_size = ctx->height * stride - left - top * stride;
 +        av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n");
 +    }
 +
 +    ctx->rotate_code = 0;
 +
 +    if (((seq & 1) || !(flags & 1)) && (compr && compr != 2))
 +        rotate_bufs(ctx, 1);
 +
 +    dst  = ((uint8_t*)ctx->frm0) + left + top * stride;
 +    prev = ((uint8_t*)ctx->frm2) + left + top * stride;
 +
 +    if (mvoff > 2) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "invalid motion base value %d\n", mvoff);
 +        return AVERROR_INVALIDDATA;
 +    }
 +    av_dlog(ctx->avctx, "compression %d\n", compr);
 +    switch (compr) {
 +    case 0:
 +        for (i = 0; i < height; i++) {
 +            bytestream2_get_buffer(&ctx->gb, dst, width);
 +            dst += stride;
 +        }
 +        memset(ctx->frm1, 0, ctx->height * stride);
 +        memset(ctx->frm2, 0, ctx->height * stride);
 +        break;
 +    case 2:
 +        if (rle_decode(ctx, dst, decoded_size))
 +            return AVERROR_INVALIDDATA;
 +        memset(ctx->frm1, 0, ctx->frm1_size);
 +        memset(ctx->frm2, 0, ctx->frm2_size);
 +        break;
 +    case 3:
 +    case 4:
 +        if (flags & 4) {
 +            for (j = 0; j < height; j += 4) {
 +                for (i = 0; i < width; i += 4) {
 +                    int code;
 +                    if (skip_run) {
 +                        skip_run--;
 +                        copy_block4(dst + i, prev + i, stride, stride, 4);
 +                        continue;
 +                    }
 +                    if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +                        return AVERROR_INVALIDDATA;
 +                    code = bytestream2_get_byteu(&ctx->gb);
 +                    switch (code) {
 +                    case 0xFF:
 +                        if (bytestream2_get_bytes_left(&ctx->gb) < 16)
 +                            return AVERROR_INVALIDDATA;
 +                        for (k = 0; k < 4; k++)
 +                            bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
 +                        break;
 +                    case 0xFE:
 +                        if (bytestream2_get_bytes_left(&ctx->gb) < 4)
 +                            return AVERROR_INVALIDDATA;
 +                        for (k = 0; k < 4; k++)
 +                            memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
 +                        break;
 +                    case 0xFD:
 +                        if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +                            return AVERROR_INVALIDDATA;
 +                        t = bytestream2_get_byteu(&ctx->gb);
 +                        for (k = 0; k < 4; k++)
 +                            memset(dst + i + k * stride, t, 4);
 +                        break;
 +                    default:
 +                        if (compr == 4 && !code) {
 +                            if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +                                return AVERROR_INVALIDDATA;
 +                            skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
 +                            i -= 4;
 +                        } else {
 +                            int mx, my;
 +
 +                            mx = c37_mv[(mvoff * 255 + code) * 2    ];
 +                            my = c37_mv[(mvoff * 255 + code) * 2 + 1];
 +                            codec37_mv(dst + i, prev + i + mx + my * stride,
 +                                       ctx->height, stride, i + mx, j + my);
 +                        }
 +                    }
 +                }
 +                dst  += stride * 4;
 +                prev += stride * 4;
 +            }
 +        } else {
 +            for (j = 0; j < height; j += 4) {
 +                for (i = 0; i < width; i += 4) {
 +                    int code;
 +                    if (skip_run) {
 +                        skip_run--;
 +                        copy_block4(dst + i, prev + i, stride, stride, 4);
 +                        continue;
 +                    }
 +                    code = bytestream2_get_byte(&ctx->gb);
 +                    if (code == 0xFF) {
 +                        if (bytestream2_get_bytes_left(&ctx->gb) < 16)
 +                            return AVERROR_INVALIDDATA;
 +                        for (k = 0; k < 4; k++)
 +                            bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
 +                    } else if (compr == 4 && !code) {
 +                        if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +                            return AVERROR_INVALIDDATA;
 +                        skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
 +                        i -= 4;
 +                    } else {
 +                        int mx, my;
 +
 +                        mx = c37_mv[(mvoff * 255 + code) * 2];
 +                        my = c37_mv[(mvoff * 255 + code) * 2 + 1];
 +                        codec37_mv(dst + i, prev + i + mx + my * stride,
 +                                   ctx->height, stride, i + mx, j + my);
 +                    }
 +                }
 +                dst  += stride * 4;
 +                prev += stride * 4;
 +            }
 +        }
 +        break;
 +    default:
 +        av_log(ctx->avctx, AV_LOG_ERROR,
 +               "subcodec 37 compression %d not implemented\n", compr);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    return 0;
 +}
 +
 +static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1,
 +                         uint8_t *prev2, int stride, int tbl, int size)
 +{
 +    int code, k, t;
 +    uint8_t colors[2];
 +    int8_t *pglyph;
 +
 +    if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +        return AVERROR_INVALIDDATA;
 +
 +    code = bytestream2_get_byteu(&ctx->gb);
 +    if (code >= 0xF8) {
 +        switch (code) {
 +        case 0xFF:
 +            if (size == 2) {
 +                if (bytestream2_get_bytes_left(&ctx->gb) < 4)
 +                    return AVERROR_INVALIDDATA;
 +                dst[0]        = bytestream2_get_byteu(&ctx->gb);
 +                dst[1]        = bytestream2_get_byteu(&ctx->gb);
 +                dst[0+stride] = bytestream2_get_byteu(&ctx->gb);
 +                dst[1+stride] = bytestream2_get_byteu(&ctx->gb);
 +            } else {
 +                size >>= 1;
 +                if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
 +                    return AVERROR_INVALIDDATA;
 +                if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
 +                                  stride, tbl, size))
 +                    return AVERROR_INVALIDDATA;
 +                dst   += size * stride;
 +                prev1 += size * stride;
 +                prev2 += size * stride;
 +                if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
 +                    return AVERROR_INVALIDDATA;
 +                if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
 +                                  stride, tbl, size))
 +                    return AVERROR_INVALIDDATA;
 +            }
 +            break;
 +        case 0xFE:
 +            if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +                return AVERROR_INVALIDDATA;
 +
 +            t = bytestream2_get_byteu(&ctx->gb);
 +            for (k = 0; k < size; k++)
 +                memset(dst + k * stride, t, size);
 +            break;
 +        case 0xFD:
 +            if (bytestream2_get_bytes_left(&ctx->gb) < 3)
 +                return AVERROR_INVALIDDATA;
 +
 +            code = bytestream2_get_byteu(&ctx->gb);
 +            pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
 +            bytestream2_get_bufferu(&ctx->gb, colors, 2);
 +
 +            for (k = 0; k < size; k++)
 +                for (t = 0; t < size; t++)
 +                    dst[t + k * stride] = colors[!*pglyph++];
 +            break;
 +        case 0xFC:
 +            for (k = 0; k < size; k++)
 +                memcpy(dst + k * stride, prev1 + k * stride, size);
 +            break;
 +        default:
 +            k = bytestream2_tell(&ctx->gb);
 +            bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
 +            t = bytestream2_get_byte(&ctx->gb);
 +            bytestream2_seek(&ctx->gb, k, SEEK_SET);
 +            for (k = 0; k < size; k++)
 +                memset(dst + k * stride, t, size);
 +        }
 +    } else {
 +        int mx = motion_vectors[code][0];
 +        int my = motion_vectors[code][1];
 +        int index = prev2 - (const uint8_t*)ctx->frm2;
 +
 +        av_assert2(index >= 0 && index < (ctx->buf_size>>1));
 +
 +        if (index < - mx - my*stride ||
 +            (ctx->buf_size>>1) - index < mx + size + (my + size - 1)*stride) {
 +            av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid \n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        for (k = 0; k < size; k++)
 +            memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
 +    }
 +
 +    return 0;
 +}
 +
 +static int old_codec47(SANMVideoContext *ctx, int top,
 +                       int left, int width, int height)
 +{
 +    int i, j, seq, compr, new_rot, tbl_pos, skip;
 +    int stride     = ctx->pitch;
 +    uint8_t *dst   = ((uint8_t*)ctx->frm0) + left + top * stride;
 +    uint8_t *prev1 = (uint8_t*)ctx->frm1;
 +    uint8_t *prev2 = (uint8_t*)ctx->frm2;
 +    uint32_t decoded_size;
 +
 +    tbl_pos = bytestream2_tell(&ctx->gb);
 +    seq     = bytestream2_get_le16(&ctx->gb);
 +    compr   = bytestream2_get_byte(&ctx->gb);
 +    new_rot = bytestream2_get_byte(&ctx->gb);
 +    skip    = bytestream2_get_byte(&ctx->gb);
 +    bytestream2_skip(&ctx->gb, 9);
 +    decoded_size = bytestream2_get_le32(&ctx->gb);
 +    bytestream2_skip(&ctx->gb, 8);
 +
 +    if (decoded_size > ctx->height * stride - left - top * stride) {
 +        decoded_size = ctx->height * stride - left - top * stride;
 +        av_log(ctx->avctx, AV_LOG_WARNING, "decoded size is too large\n");
 +    }
 +
 +    if (skip & 1)
 +        bytestream2_skip(&ctx->gb, 0x8080);
 +    if (!seq) {
 +        ctx->prev_seq = -1;
 +        memset(prev1, 0, ctx->height * stride);
 +        memset(prev2, 0, ctx->height * stride);
 +    }
 +    av_dlog(ctx->avctx, "compression %d\n", compr);
 +    switch (compr) {
 +    case 0:
 +        if (bytestream2_get_bytes_left(&ctx->gb) < width * height)
 +            return AVERROR_INVALIDDATA;
 +        for (j = 0; j < height; j++) {
 +            bytestream2_get_bufferu(&ctx->gb, dst, width);
 +            dst += stride;
 +        }
 +        break;
 +    case 1:
 +        if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
 +            return AVERROR_INVALIDDATA;
 +        for (j = 0; j < height; j += 2) {
 +            for (i = 0; i < width; i += 2) {
 +                dst[i] = dst[i + 1] =
 +                dst[stride + i] = dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb);
 +            }
 +            dst += stride * 2;
 +        }
 +        break;
 +    case 2:
 +        if (seq == ctx->prev_seq + 1) {
 +            for (j = 0; j < height; j += 8) {
 +                for (i = 0; i < width; i += 8) {
 +                    if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
 +                                      tbl_pos + 8, 8))
 +                        return AVERROR_INVALIDDATA;
 +                }
 +                dst   += stride * 8;
 +                prev1 += stride * 8;
 +                prev2 += stride * 8;
 +            }
 +        }
 +        break;
 +    case 3:
 +        memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
 +        break;
 +    case 4:
 +        memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
 +        break;
 +    case 5:
 +        if (rle_decode(ctx, dst, decoded_size))
 +            return AVERROR_INVALIDDATA;
 +        break;
 +    default:
 +        av_log(ctx->avctx, AV_LOG_ERROR,
 +               "subcodec 47 compression %d not implemented\n", compr);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +    if (seq == ctx->prev_seq + 1)
 +        ctx->rotate_code = new_rot;
 +    else
 +        ctx->rotate_code = 0;
 +    ctx->prev_seq = seq;
 +
 +    return 0;
 +}
 +
 +static int process_frame_obj(SANMVideoContext *ctx)
 +{
 +    uint16_t codec, top, left, w, h;
 +
 +    codec = bytestream2_get_le16u(&ctx->gb);
 +    left  = bytestream2_get_le16u(&ctx->gb);
 +    top   = bytestream2_get_le16u(&ctx->gb);
 +    w     = bytestream2_get_le16u(&ctx->gb);
 +    h     = bytestream2_get_le16u(&ctx->gb);
 +
 +    if (ctx->width < left + w || ctx->height < top + h) {
 +        if (av_image_check_size(FFMAX(left + w, ctx->width),
 +                                FFMAX(top  + h, ctx->height), 0, ctx->avctx) < 0)
 +            return AVERROR_INVALIDDATA;
 +        avcodec_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
 +                                           FFMAX(top  + h, ctx->height));
 +        init_sizes(ctx, FFMAX(left + w, ctx->width),
 +                        FFMAX(top  + h, ctx->height));
 +        if (init_buffers(ctx)) {
 +            av_log(ctx->avctx, AV_LOG_ERROR, "error resizing buffers\n");
 +            return AVERROR(ENOMEM);
 +        }
 +    }
 +    bytestream2_skip(&ctx->gb, 4);
 +
 +    av_dlog(ctx->avctx, "subcodec %d\n", codec);
 +    switch (codec) {
 +    case 1:
 +    case 3:
 +        return old_codec1(ctx, top, left, w, h);
 +        break;
 +    case 37:
 +        return old_codec37(ctx, top, left, w, h);
 +        break;
 +    case 47:
 +        return old_codec47(ctx, top, left, w, h);
 +        break;
 +    default:
 +        av_log_ask_for_sample(ctx->avctx, "unknown subcodec %d\n", codec);
 +        return AVERROR_PATCHWELCOME;
 +    }
 +}
 +
 +static int decode_0(SANMVideoContext *ctx)
 +{
 +    uint16_t *frm = ctx->frm0;
 +    int x, y;
 +
 +    if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for raw frame\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +    for (y = 0; y < ctx->height; y++) {
 +        for (x = 0; x < ctx->width; x++)
 +            frm[x] = bytestream2_get_le16u(&ctx->gb);
 +        frm += ctx->pitch;
 +    }
 +    return 0;
 +}
 +
 +static int decode_nop(SANMVideoContext *ctx)
 +{
 +    av_log_ask_for_sample(ctx->avctx, "unknown/unsupported compression type\n");
 +    return AVERROR_PATCHWELCOME;
 +}
 +
 +static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, int pitch)
 +{
 +    uint8_t *dst = (uint8_t *)pdest;
 +    uint8_t *src = (uint8_t *)psrc;
 +    int stride = pitch * 2;
 +
 +    switch (block_size) {
 +    case 2:
 +        copy_block4(dst, src, stride, stride, 2);
 +        break;
 +    case 4:
 +        copy_block8(dst, src, stride, stride, 4);
 +        break;
 +    case 8:
 +        copy_block16(dst, src, stride, stride, 8);
 +        break;
 +    }
 +}
 +
 +static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitch)
 +{
 +    int x, y;
 +
 +    pitch -= block_size;
 +    for (y = 0; y < block_size; y++, pdest += pitch)
 +        for (x = 0; x < block_size; x++)
 +            *pdest++ = color;
 +}
 +
 +static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index, uint16_t fg_color,
 +                      uint16_t bg_color, int block_size, int pitch)
 +{
 +    int8_t *pglyph;
 +    uint16_t colors[2] = { fg_color, bg_color };
 +    int x, y;
 +
 +    if (index >= NGLYPHS) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "ignoring nonexistent glyph #%u\n", index);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
 +    pitch -= block_size;
 +
 +    for (y = 0; y < block_size; y++, dst += pitch)
 +        for (x = 0; x < block_size; x++)
 +            *dst++ = colors[*pglyph++];
 +    return 0;
 +}
 +
 +static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
 +{
 +    uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
 +
 +    if (block_size == 2) {
 +        uint32_t indices;
 +
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 4)
 +            return AVERROR_INVALIDDATA;
 +
 +        indices        = bytestream2_get_le32u(&ctx->gb);
 +        dst[0]         = ctx->codebook[indices & 0xFF]; indices >>= 8;
 +        dst[1]         = ctx->codebook[indices & 0xFF]; indices >>= 8;
 +        dst[pitch]     = ctx->codebook[indices & 0xFF]; indices >>= 8;
 +        dst[pitch + 1] = ctx->codebook[indices & 0xFF];
 +    } else {
 +        uint16_t fgcolor, bgcolor;
 +        int glyph;
 +
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 3)
 +            return AVERROR_INVALIDDATA;
 +
 +        glyph   = bytestream2_get_byteu(&ctx->gb);
 +        bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
 +        fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
 +
 +        draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
 +    }
 +    return 0;
 +}
 +
 +static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
 +{
 +    uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
 +
 +    if (block_size == 2) {
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 8)
 +            return AVERROR_INVALIDDATA;
 +
 +        dst[0]         = bytestream2_get_le16u(&ctx->gb);
 +        dst[1]         = bytestream2_get_le16u(&ctx->gb);
 +        dst[pitch]     = bytestream2_get_le16u(&ctx->gb);
 +        dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
 +    } else {
 +        uint16_t fgcolor, bgcolor;
 +        int glyph;
 +
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 5)
 +            return AVERROR_INVALIDDATA;
 +
 +        glyph   = bytestream2_get_byteu(&ctx->gb);
 +        bgcolor = bytestream2_get_le16u(&ctx->gb);
 +        fgcolor = bytestream2_get_le16u(&ctx->gb);
 +
 +        draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
 +    }
 +    return 0;
 +}
 +
 +static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
 +                     int block_size)
 +{
 +    int start_pos = cx + mx + (cy + my) * ctx->pitch;
 +    int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
 +
 +    int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
 +
 +    if (!good) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
 +               cx + mx, cy + my, cx, cy, block_size);
 +    }
 +
 +    return good;
 +}
 +
 +static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
 +{
 +    int16_t mx, my, index;
 +    int opcode;
 +
 +    if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +        return AVERROR_INVALIDDATA;
 +
 +    opcode = bytestream2_get_byteu(&ctx->gb);
 +
 +    av_dlog(ctx->avctx, "opcode 0x%0X cx %d cy %d blk %d\n", opcode, cx, cy, blk_size);
 +    switch (opcode) {
 +    default:
 +        mx = motion_vectors[opcode][0];
 +        my = motion_vectors[opcode][1];
 +
 +        if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
 +            copy_block(ctx->frm0 + cx      + ctx->pitch *  cy,
 +                       ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
 +                       blk_size, ctx->pitch);
 +        }
 +        break;
 +    case 0xF5:
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 2)
 +            return AVERROR_INVALIDDATA;
 +        index = bytestream2_get_le16u(&ctx->gb);
 +
 +        mx = index % ctx->width;
 +        my = index / ctx->width;
 +
 +        if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
 +            copy_block(ctx->frm0 + cx      + ctx->pitch *  cy,
 +                       ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
 +                       blk_size, ctx->pitch);
 +        }
 +        break;
 +    case 0xF6:
 +        copy_block(ctx->frm0 + cx + ctx->pitch * cy,
 +                   ctx->frm1 + cx + ctx->pitch * cy,
 +                   blk_size, ctx->pitch);
 +        break;
 +    case 0xF7:
 +        opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
 +        break;
 +
 +    case 0xF8:
 +        opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
 +        break;
 +    case 0xF9:
 +    case 0xFA:
 +    case 0xFB:
 +    case 0xFC:
 +        fill_block(ctx->frm0 + cx + cy * ctx->pitch,
 +                   ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
 +        break;
 +    case 0xFD:
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 1)
 +            return AVERROR_INVALIDDATA;
 +        fill_block(ctx->frm0 + cx + cy * ctx->pitch,
 +                   ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
 +        break;
 +    case 0xFE:
 +        if (bytestream2_get_bytes_left(&ctx->gb) < 2)
 +            return AVERROR_INVALIDDATA;
 +        fill_block(ctx->frm0 + cx + cy * ctx->pitch,
 +                   bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
 +        break;
 +    case 0xFF:
 +        if (blk_size == 2) {
 +            opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
 +        } else {
 +            blk_size >>= 1;
 +            if (codec2subblock(ctx, cx           , cy           , blk_size))
 +                return AVERROR_INVALIDDATA;
 +            if (codec2subblock(ctx, cx + blk_size, cy           , blk_size))
 +                return AVERROR_INVALIDDATA;
 +            if (codec2subblock(ctx, cx           , cy + blk_size, blk_size))
 +                return AVERROR_INVALIDDATA;
 +            if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
 +                return AVERROR_INVALIDDATA;
 +        }
 +        break;
 +    }
 +    return 0;
 +}
 +
 +static int decode_2(SANMVideoContext *ctx)
 +{
 +    int cx, cy, ret;
 +
 +    for (cy = 0; cy < ctx->aligned_height; cy += 8) {
 +        for (cx = 0; cx < ctx->aligned_width; cx += 8) {
 +            if (ret = codec2subblock(ctx, cx, cy, 8))
 +                return ret;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_3(SANMVideoContext *ctx)
 +{
 +    memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
 +    return 0;
 +}
 +
 +static int decode_4(SANMVideoContext *ctx)
 +{
 +    memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
 +    return 0;
 +}
 +
 +static int decode_5(SANMVideoContext *ctx)
 +{
 +#if HAVE_BIGENDIAN
 +    uint16_t *frm;
 +    int npixels;
 +#endif
 +    uint8_t *dst = (uint8_t*)ctx->frm0;
 +
 +    if (rle_decode(ctx, dst, ctx->buf_size))
 +        return AVERROR_INVALIDDATA;
 +
 +#if HAVE_BIGENDIAN
 +    npixels = ctx->npixels;
 +    frm = ctx->frm0;
 +    while (npixels--)
 +        *frm++ = av_bswap16(*frm);
 +#endif
 +
 +    return 0;
 +}
 +
 +static int decode_6(SANMVideoContext *ctx)
 +{
 +    int npixels = ctx->npixels;
 +    uint16_t *frm = ctx->frm0;
 +
 +    if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "insufficient data for frame\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +    while (npixels--)
 +        *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
 +
 +    return 0;
 +}
 +
 +static int decode_8(SANMVideoContext *ctx)
 +{
 +    uint16_t *pdest = ctx->frm0;
 +    uint8_t *rsrc;
 +    long npixels = ctx->npixels;
 +
 +    av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
 +    if (!ctx->rle_buf) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed\n");
 +        return AVERROR(ENOMEM);
 +    }
 +    rsrc = ctx->rle_buf;
 +
 +    if (rle_decode(ctx, rsrc, npixels))
 +        return AVERROR_INVALIDDATA;
 +
 +    while (npixels--)
 +        *pdest++ = ctx->codebook[*rsrc++];
 +
 +    return 0;
 +}
 +
 +typedef int (*frm_decoder)(SANMVideoContext *ctx);
 +
 +static const frm_decoder v1_decoders[] = {
 +    decode_0, decode_nop, decode_2, decode_3, decode_4, decode_5,
 +    decode_6, decode_nop, decode_8
 +};
 +
 +static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr)
 +{
 +    int i, ret;
 +
 +    if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "too short input frame (%d bytes)\n",
 +               ret);
 +        return AVERROR_INVALIDDATA;
 +    }
 +    bytestream2_skip(&ctx->gb, 8); // skip pad
 +
 +    hdr->width  = bytestream2_get_le32u(&ctx->gb);
 +    hdr->height = bytestream2_get_le32u(&ctx->gb);
 +
 +    if (hdr->width != ctx->width || hdr->height != ctx->height) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "variable size frames are not implemented\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
 +
 +    hdr->seq_num     = bytestream2_get_le16u(&ctx->gb);
 +    hdr->codec       = bytestream2_get_byteu(&ctx->gb);
 +    hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
 +
 +    bytestream2_skip(&ctx->gb, 4); // skip pad
 +
 +    for (i = 0; i < 4; i++)
 +        ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
 +    hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
 +
 +    bytestream2_skip(&ctx->gb, 2); // skip pad
 +
 +    hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
 +    for (i = 0; i < 256; i++)
 +        ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
 +
 +    bytestream2_skip(&ctx->gb, 8); // skip pad
 +
 +    av_dlog(ctx->avctx, "subcodec %d\n", hdr->codec);
 +    return 0;
 +}
 +
 +static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
 +{
 +    while (buf_size--)
 +        *pbuf++ = color;
 +}
 +
 +static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
 +{
 +    uint8_t *dst;
 +    const uint8_t *src = (uint8_t*) ctx->frm0;
 +    int ret, dstpitch, height = ctx->height;
 +    int srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
 +
-     dst      = ctx->output->data[0];
-     dstpitch = ctx->output->linesize[0];
++    if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0) {
 +        av_log(ctx->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +
-     if (ctx->output->data[0])
-         avctx->release_buffer(avctx, ctx->output);
++    dst      = ctx->frame->data[0];
++    dstpitch = ctx->frame->linesize[0];
 +
 +    while (height--) {
 +        memcpy(dst, src, srcpitch);
 +        src += srcpitch;
 +        dst += dstpitch;
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data,
 +                        int *got_frame_ptr, AVPacket *pkt)
 +{
 +    SANMVideoContext *ctx = avctx->priv_data;
 +    int i, ret;
 +
++    ctx->frame = data;
 +    bytestream2_init(&ctx->gb, pkt->data, pkt->size);
-         memcpy(ctx->output->data[1], ctx->pal, 1024);
 +
 +    if (!ctx->version) {
 +        int to_store = 0;
 +
 +        while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
 +            uint32_t sig, size;
 +            int pos;
 +
 +            sig  = bytestream2_get_be32u(&ctx->gb);
 +            size = bytestream2_get_be32u(&ctx->gb);
 +            pos  = bytestream2_tell(&ctx->gb);
 +
 +            if (bytestream2_get_bytes_left(&ctx->gb) < size) {
 +                av_log(avctx, AV_LOG_ERROR, "incorrect chunk size %d\n", size);
 +                break;
 +            }
 +            switch (sig) {
 +            case MKBETAG('N', 'P', 'A', 'L'):
 +                if (size != 256 * 3) {
 +                    av_log(avctx, AV_LOG_ERROR, "incorrect palette block size %d\n",
 +                           size);
 +                    return AVERROR_INVALIDDATA;
 +                }
 +                for (i = 0; i < 256; i++)
 +                    ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
 +                break;
 +            case MKBETAG('F', 'O', 'B', 'J'):
 +                if (size < 16)
 +                    return AVERROR_INVALIDDATA;
 +                if (ret = process_frame_obj(ctx))
 +                    return ret;
 +                break;
 +            case MKBETAG('X', 'P', 'A', 'L'):
 +                if (size == 6 || size == 4) {
 +                    uint8_t tmp[3];
 +                    int j;
 +
 +                    for (i = 0; i < 256; i++) {
 +                        for (j = 0; j < 3; j++) {
 +                            int t = (ctx->pal[i] >> (16 - j * 8)) & 0xFF;
 +                            tmp[j] = av_clip_uint8((t * 129 + ctx->delta_pal[i * 3 + j]) >> 7);
 +                        }
 +                        ctx->pal[i] = 0xFFU << 24 | AV_RB24(tmp);
 +                    }
 +                } else {
 +                    if (size < 768 * 2 + 4) {
 +                        av_log(avctx, AV_LOG_ERROR, "incorrect palette change block size %d\n",
 +                               size);
 +                        return AVERROR_INVALIDDATA;
 +                    }
 +                    bytestream2_skipu(&ctx->gb, 4);
 +                    for (i = 0; i < 768; i++)
 +                        ctx->delta_pal[i] = bytestream2_get_le16u(&ctx->gb);
 +                    if (size >= 768 * 5 + 4) {
 +                        for (i = 0; i < 256; i++)
 +                            ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
 +                    } else {
 +                        memset(ctx->pal, 0, sizeof(ctx->pal));
 +                    }
 +                }
 +                break;
 +            case MKBETAG('S', 'T', 'O', 'R'):
 +                to_store = 1;
 +                break;
 +            case MKBETAG('F', 'T', 'C', 'H'):
 +                memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
 +                break;
 +            default:
 +                bytestream2_skip(&ctx->gb, size);
 +                av_log(avctx, AV_LOG_DEBUG, "unknown/unsupported chunk %x\n", sig);
 +                break;
 +            }
 +
 +            bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
 +            if (size & 1)
 +                bytestream2_skip(&ctx->gb, 1);
 +        }
 +        if (to_store)
 +            memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
 +        if ((ret = copy_output(ctx, NULL)))
 +            return ret;
-         if ((ctx->output->key_frame = !header.seq_num)) {
-             ctx->output->pict_type = AV_PICTURE_TYPE_I;
++        memcpy(ctx->frame->data[1], ctx->pal, 1024);
 +    } else {
 +        SANMFrameHeader header;
 +
 +        if ((ret = read_frame_header(ctx, &header)))
 +            return ret;
 +
 +        ctx->rotate_code = header.rotate_code;
-             ctx->output->pict_type = AV_PICTURE_TYPE_P;
++        if ((ctx->frame->key_frame = !header.seq_num)) {
++            ctx->frame->pict_type = AV_PICTURE_TYPE_I;
 +            fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
 +            fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
 +        } else {
-     *(AVFrame*)data = *ctx->output;
++            ctx->frame->pict_type = AV_PICTURE_TYPE_P;
 +        }
 +
 +        if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
 +            if ((ret = v1_decoders[header.codec](ctx))) {
 +                av_log(avctx, AV_LOG_ERROR,
 +                       "subcodec %d: error decoding frame\n", header.codec);
 +                return ret;
 +            }
 +        } else {
 +            av_log_ask_for_sample(avctx, "subcodec %d is not implemented\n",
 +                   header.codec);
 +            return AVERROR_PATCHWELCOME;
 +        }
 +
 +        if ((ret = copy_output(ctx, &header)))
 +            return ret;
 +    }
 +    if (ctx->rotate_code)
 +        rotate_bufs(ctx, ctx->rotate_code);
 +
 +    *got_frame_ptr  = 1;
 +
 +    return pkt->size;
 +}
 +
 +AVCodec ff_sanm_decoder = {
 +    .name           = "sanm",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_SANM,
 +    .priv_data_size = sizeof(SANMVideoContext),
 +    .init           = decode_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("LucasArts SMUSH video"),
 +};
Simple merge
index 0ce6afd,0000000..59f8e31
mode 100644,000000..100644
--- /dev/null
@@@ -1,148 -1,0 +1,154 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame)
 +/*
 + * SGI RLE 8-bit decoder
 + * Copyright (c) 2012 Peter Ross
 + *
 + * 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
 + * SGI RLE 8-bit decoder
 + */
 +
 +#include "libavutil/intreadwrite.h"
 +#include "avcodec.h"
 +#include "bytestream.h"
++#include "internal.h"
++
++typedef struct SGIRLEContext {
++    AVFrame *frame;
++} SGIRLEContext;
 +
 +static av_cold int sgirle_decode_init(AVCodecContext *avctx)
 +{
++    SGIRLEContext *s = avctx->priv_data;
 +    avctx->pix_fmt = AV_PIX_FMT_BGR8;
-     AVFrame *frame = avctx->coded_frame;
++    s->frame = av_frame_alloc();
++    if (!s->frame)
 +        return AVERROR(ENOMEM);
 +    return 0;
 +}
 +
 +/**
 + * Convert SGI RGB332 pixel into PIX_FMT_BGR8
 + * SGI RGB332 is packed RGB 3:3:2, 8bpp, (msb)3R 2B 3G(lsb)
 + */
 +#define RGB332_TO_BGR8(x) (((x << 3) & 0xC0) | ((x << 3) & 0x38) | ((x >> 5) & 7))
 +
 +static av_always_inline void memcpy_rgb332_to_bgr8(uint8_t *dst, const uint8_t *src, int size)
 +{
 +    int i;
 +    for (i = 0; i < size; i++)
 +        dst[i] = RGB332_TO_BGR8(src[i]);
 +}
 +
 +/**
 + * @param[out] dst Destination buffer
 + * @param[in] src Source buffer
 + * @param src_size Source buffer size (bytes)
 + * @param width Width of destination buffer (pixels)
 + * @param height Height of destination buffer (pixels)
 + * @param linesize Line size of destination buffer (bytes)
 + * @return <0 on error
 + */
 +static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, const uint8_t *src, int src_size, int width, int height, int linesize)
 +{
 +    const uint8_t *src_end = src + src_size;
 +    int x = 0, y = 0;
 +
 +#define INC_XY(n) \
 +    x += n; \
 +    if (x >= width) { \
 +        y++; \
 +        if (y >= height) \
 +            return 0; \
 +        x = 0; \
 +    }
 +
 +    while (src_end - src >= 2) {
 +        uint8_t v = *src++;
 +        if (v > 0 && v < 0xC0) {
 +            do {
 +                int length = FFMIN(v, width - x);
 +                memset(dst + y*linesize + x, RGB332_TO_BGR8(*src), length);
 +                INC_XY(length);
 +                v   -= length;
 +            } while (v > 0);
 +            src++;
 +        } else if (v >= 0xC1) {
 +            v -= 0xC0;
 +            do {
 +                int length = FFMIN3(v, width - x, src_end - src);
 +                if (src_end - src < length)
 +                    break;
 +                memcpy_rgb332_to_bgr8(dst + y*linesize + x, src, length);
 +                INC_XY(length);
 +                src += length;
 +                v   -= length;
 +            } while (v > 0);
 +        } else {
 +            av_log_ask_for_sample(avctx, "unknown opcode\n");
 +            return AVERROR_PATCHWELCOME;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int sgirle_decode_frame(AVCodecContext *avctx,
 +                            void *data, int *got_frame,
 +                            AVPacket *avpkt)
 +{
-     frame->reference = 3;
-     frame->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE |
-                           FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE;
-     ret = avctx->reget_buffer(avctx, frame);
++    SGIRLEContext *s = avctx->priv_data;
 +    int ret;
 +
-     ret = decode_sgirle8(avctx, frame->data[0], avpkt->data, avpkt->size, avctx->width, avctx->height, frame->linesize[0]);
++    ret = ff_reget_buffer(avctx, s->frame);
 +    if (ret < 0) {
 +        av_log (avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
 +        return ret;
 +    }
 +
-     *(AVFrame*)data = *frame;
++    ret = decode_sgirle8(avctx, s->frame->data[0], avpkt->data, avpkt->size, avctx->width, avctx->height, s->frame->linesize[0]);
 +    if (ret < 0)
 +        return ret;
 +
 +    *got_frame      = 1;
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
++    if ((ret = av_frame_ref(data, s->frame)) < 0)
++        return ret;
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int sgirle_decode_end(AVCodecContext *avctx)
 +{
++    SGIRLEContext *s = avctx->priv_data;
++
++    av_frame_free(&s->frame);
++
 +    return 0;
 +}
 +
 +AVCodec ff_sgirle_decoder = {
 +    .name           = "sgirle",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_SGIRLE,
++    .priv_data_size = sizeof(SGIRLEContext),
 +    .init           = sgirle_decode_init,
 +    .close          = sgirle_decode_end,
 +    .decode         = sgirle_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("SGI RLE 8-bit"),
 +};
@@@ -590,13 -591,9 +590,13 @@@ static int shorten_decode_frame(AVCodec
              /* if this is the last channel in the block, output the samples */
              s->cur_chan++;
              if (s->cur_chan == s->channels) {
 +                uint8_t *samples_u8;
 +                int16_t *samples_s16;
 +                int chan;
 +
                  /* get output buffer */
                  frame->nb_samples = s->blocksize;
-                 if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+                 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
                      av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
                      return ret;
                  }
Simple merge
@@@ -379,11 -363,9 +379,9 @@@ static int decode_frame(AVCodecContext 
      int flags;
  
      if (avpkt->size <= 769)
 -        return 0;
 +        return AVERROR_INVALIDDATA;
  
-     smk->pic.reference = 3;
-     smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     if((ret = avctx->reget_buffer(avctx, &smk->pic)) < 0){
+     if ((ret = ff_reget_buffer(avctx, &smk->pic)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
Simple merge
index b2c6714,0000000..126acf3
mode 100644,000000..100644
--- /dev/null
@@@ -1,690 -1,0 +1,689 @@@
-         if ((ret = ff_get_buffer(s->avctx, &s->mconly_picture)) < 0) {
 +/*
 + * Copyright (C) 2004 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 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/intmath.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "dsputil.h"
 +#include "snow_dwt.h"
 +#include "internal.h"
 +#include "snow.h"
 +#include "snowdata.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +#include "h263.h"
 +
 +
 +void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h,
 +                              int src_x, int src_y, int src_stride, slice_buffer * sb, int add, uint8_t * dst8){
 +    int y, x;
 +    IDWTELEM * dst;
 +    for(y=0; y<b_h; y++){
 +        //FIXME ugly misuse of obmc_stride
 +        const uint8_t *obmc1= obmc + y*obmc_stride;
 +        const uint8_t *obmc2= obmc1+ (obmc_stride>>1);
 +        const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
 +        const uint8_t *obmc4= obmc3+ (obmc_stride>>1);
 +        dst = slice_buffer_get_line(sb, src_y + y);
 +        for(x=0; x<b_w; x++){
 +            int v=   obmc1[x] * block[3][x + y*src_stride]
 +                    +obmc2[x] * block[2][x + y*src_stride]
 +                    +obmc3[x] * block[1][x + y*src_stride]
 +                    +obmc4[x] * block[0][x + y*src_stride];
 +
 +            v <<= 8 - LOG2_OBMC_MAX;
 +            if(FRAC_BITS != 8){
 +                v >>= 8 - FRAC_BITS;
 +            }
 +            if(add){
 +                v += dst[x + src_x];
 +                v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS;
 +                if(v&(~255)) v= ~(v>>31);
 +                dst8[x + y*src_stride] = v;
 +            }else{
 +                dst[x + src_x] -= v;
 +            }
 +        }
 +    }
 +}
 +
 +void ff_snow_reset_contexts(SnowContext *s){ //FIXME better initial contexts
 +    int plane_index, level, orientation;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        for(level=0; level<MAX_DECOMPOSITIONS; level++){
 +            for(orientation=level ? 1:0; orientation<4; orientation++){
 +                memset(s->plane[plane_index].band[level][orientation].state, MID_STATE, sizeof(s->plane[plane_index].band[level][orientation].state));
 +            }
 +        }
 +    }
 +    memset(s->header_state, MID_STATE, sizeof(s->header_state));
 +    memset(s->block_state, MID_STATE, sizeof(s->block_state));
 +}
 +
 +int ff_snow_alloc_blocks(SnowContext *s){
 +    int w= -((-s->avctx->width )>>LOG2_MB_SIZE);
 +    int h= -((-s->avctx->height)>>LOG2_MB_SIZE);
 +
 +    s->b_width = w;
 +    s->b_height= h;
 +
 +    av_free(s->block);
 +    s->block= av_mallocz(w * h * sizeof(BlockNode) << (s->block_max_depth*2));
 +    return 0;
 +}
 +
 +static void init_qexp(void){
 +    int i;
 +    double v=128;
 +
 +    for(i=0; i<QROOT; i++){
 +        ff_qexp[i]= lrintf(v);
 +        v *= pow(2, 1.0 / QROOT);
 +    }
 +}
 +static void mc_block(Plane *p, uint8_t *dst, const uint8_t *src, int stride, int b_w, int b_h, int dx, int dy){
 +    static const uint8_t weight[64]={
 +    8,7,6,5,4,3,2,1,
 +    7,7,0,0,0,0,0,1,
 +    6,0,6,0,0,0,2,0,
 +    5,0,0,5,0,3,0,0,
 +    4,0,0,0,4,0,0,0,
 +    3,0,0,5,0,3,0,0,
 +    2,0,6,0,0,0,2,0,
 +    1,7,0,0,0,0,0,1,
 +    };
 +
 +    static const uint8_t brane[256]={
 +    0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
 +    0x04,0x05,0xcc,0xcc,0xcc,0xcc,0xcc,0x41,0x15,0x16,0xcc,0xcc,0xcc,0xcc,0xcc,0x52,
 +    0x04,0xcc,0x05,0xcc,0xcc,0xcc,0x41,0xcc,0x15,0xcc,0x16,0xcc,0xcc,0xcc,0x52,0xcc,
 +    0x04,0xcc,0xcc,0x05,0xcc,0x41,0xcc,0xcc,0x15,0xcc,0xcc,0x16,0xcc,0x52,0xcc,0xcc,
 +    0x04,0xcc,0xcc,0xcc,0x41,0xcc,0xcc,0xcc,0x15,0xcc,0xcc,0xcc,0x16,0xcc,0xcc,0xcc,
 +    0x04,0xcc,0xcc,0x41,0xcc,0x05,0xcc,0xcc,0x15,0xcc,0xcc,0x52,0xcc,0x16,0xcc,0xcc,
 +    0x04,0xcc,0x41,0xcc,0xcc,0xcc,0x05,0xcc,0x15,0xcc,0x52,0xcc,0xcc,0xcc,0x16,0xcc,
 +    0x04,0x41,0xcc,0xcc,0xcc,0xcc,0xcc,0x05,0x15,0x52,0xcc,0xcc,0xcc,0xcc,0xcc,0x16,
 +    0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x55,0x56,0x56,0x56,0x56,0x56,0x56,0x56,
 +    0x48,0x49,0xcc,0xcc,0xcc,0xcc,0xcc,0x85,0x59,0x5A,0xcc,0xcc,0xcc,0xcc,0xcc,0x96,
 +    0x48,0xcc,0x49,0xcc,0xcc,0xcc,0x85,0xcc,0x59,0xcc,0x5A,0xcc,0xcc,0xcc,0x96,0xcc,
 +    0x48,0xcc,0xcc,0x49,0xcc,0x85,0xcc,0xcc,0x59,0xcc,0xcc,0x5A,0xcc,0x96,0xcc,0xcc,
 +    0x48,0xcc,0xcc,0xcc,0x49,0xcc,0xcc,0xcc,0x59,0xcc,0xcc,0xcc,0x96,0xcc,0xcc,0xcc,
 +    0x48,0xcc,0xcc,0x85,0xcc,0x49,0xcc,0xcc,0x59,0xcc,0xcc,0x96,0xcc,0x5A,0xcc,0xcc,
 +    0x48,0xcc,0x85,0xcc,0xcc,0xcc,0x49,0xcc,0x59,0xcc,0x96,0xcc,0xcc,0xcc,0x5A,0xcc,
 +    0x48,0x85,0xcc,0xcc,0xcc,0xcc,0xcc,0x49,0x59,0x96,0xcc,0xcc,0xcc,0xcc,0xcc,0x5A,
 +    };
 +
 +    static const uint8_t needs[16]={
 +    0,1,0,0,
 +    2,4,2,0,
 +    0,1,0,0,
 +    15
 +    };
 +
 +    int x, y, b, r, l;
 +    int16_t tmpIt   [64*(32+HTAPS_MAX)];
 +    uint8_t tmp2t[3][64*(32+HTAPS_MAX)];
 +    int16_t *tmpI= tmpIt;
 +    uint8_t *tmp2= tmp2t[0];
 +    const uint8_t *hpel[11];
 +    av_assert2(dx<16 && dy<16);
 +    r= brane[dx + 16*dy]&15;
 +    l= brane[dx + 16*dy]>>4;
 +
 +    b= needs[l] | needs[r];
 +    if(p && !p->diag_mc)
 +        b= 15;
 +
 +    if(b&5){
 +        for(y=0; y < b_h+HTAPS_MAX-1; y++){
 +            for(x=0; x < b_w; x++){
 +                int a_1=src[x + HTAPS_MAX/2-4];
 +                int a0= src[x + HTAPS_MAX/2-3];
 +                int a1= src[x + HTAPS_MAX/2-2];
 +                int a2= src[x + HTAPS_MAX/2-1];
 +                int a3= src[x + HTAPS_MAX/2+0];
 +                int a4= src[x + HTAPS_MAX/2+1];
 +                int a5= src[x + HTAPS_MAX/2+2];
 +                int a6= src[x + HTAPS_MAX/2+3];
 +                int am=0;
 +                if(!p || p->fast_mc){
 +                    am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
 +                    tmpI[x]= am;
 +                    am= (am+16)>>5;
 +                }else{
 +                    am= p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6);
 +                    tmpI[x]= am;
 +                    am= (am+32)>>6;
 +                }
 +
 +                if(am&(~255)) am= ~(am>>31);
 +                tmp2[x]= am;
 +            }
 +            tmpI+= 64;
 +            tmp2+= 64;
 +            src += stride;
 +        }
 +        src -= stride*y;
 +    }
 +    src += HTAPS_MAX/2 - 1;
 +    tmp2= tmp2t[1];
 +
 +    if(b&2){
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w+1; x++){
 +                int a_1=src[x + (HTAPS_MAX/2-4)*stride];
 +                int a0= src[x + (HTAPS_MAX/2-3)*stride];
 +                int a1= src[x + (HTAPS_MAX/2-2)*stride];
 +                int a2= src[x + (HTAPS_MAX/2-1)*stride];
 +                int a3= src[x + (HTAPS_MAX/2+0)*stride];
 +                int a4= src[x + (HTAPS_MAX/2+1)*stride];
 +                int a5= src[x + (HTAPS_MAX/2+2)*stride];
 +                int a6= src[x + (HTAPS_MAX/2+3)*stride];
 +                int am=0;
 +                if(!p || p->fast_mc)
 +                    am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 16)>>5;
 +                else
 +                    am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 32)>>6;
 +
 +                if(am&(~255)) am= ~(am>>31);
 +                tmp2[x]= am;
 +            }
 +            src += stride;
 +            tmp2+= 64;
 +        }
 +        src -= stride*y;
 +    }
 +    src += stride*(HTAPS_MAX/2 - 1);
 +    tmp2= tmp2t[2];
 +    tmpI= tmpIt;
 +    if(b&4){
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w; x++){
 +                int a_1=tmpI[x + (HTAPS_MAX/2-4)*64];
 +                int a0= tmpI[x + (HTAPS_MAX/2-3)*64];
 +                int a1= tmpI[x + (HTAPS_MAX/2-2)*64];
 +                int a2= tmpI[x + (HTAPS_MAX/2-1)*64];
 +                int a3= tmpI[x + (HTAPS_MAX/2+0)*64];
 +                int a4= tmpI[x + (HTAPS_MAX/2+1)*64];
 +                int a5= tmpI[x + (HTAPS_MAX/2+2)*64];
 +                int a6= tmpI[x + (HTAPS_MAX/2+3)*64];
 +                int am=0;
 +                if(!p || p->fast_mc)
 +                    am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 512)>>10;
 +                else
 +                    am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 2048)>>12;
 +                if(am&(~255)) am= ~(am>>31);
 +                tmp2[x]= am;
 +            }
 +            tmpI+= 64;
 +            tmp2+= 64;
 +        }
 +    }
 +
 +    hpel[ 0]= src;
 +    hpel[ 1]= tmp2t[0] + 64*(HTAPS_MAX/2-1);
 +    hpel[ 2]= src + 1;
 +
 +    hpel[ 4]= tmp2t[1];
 +    hpel[ 5]= tmp2t[2];
 +    hpel[ 6]= tmp2t[1] + 1;
 +
 +    hpel[ 8]= src + stride;
 +    hpel[ 9]= hpel[1] + 64;
 +    hpel[10]= hpel[8] + 1;
 +
 +#define MC_STRIDE(x) (needs[x] ? 64 : stride)
 +
 +    if(b==15){
 +        int dxy = dx / 8 + dy / 8 * 4;
 +        const uint8_t *src1 = hpel[dxy    ];
 +        const uint8_t *src2 = hpel[dxy + 1];
 +        const uint8_t *src3 = hpel[dxy + 4];
 +        const uint8_t *src4 = hpel[dxy + 5];
 +        int stride1 = MC_STRIDE(dxy);
 +        int stride2 = MC_STRIDE(dxy + 1);
 +        int stride3 = MC_STRIDE(dxy + 4);
 +        int stride4 = MC_STRIDE(dxy + 5);
 +        dx&=7;
 +        dy&=7;
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w; x++){
 +                dst[x]= ((8-dx)*(8-dy)*src1[x] + dx*(8-dy)*src2[x]+
 +                         (8-dx)*   dy *src3[x] + dx*   dy *src4[x]+32)>>6;
 +            }
 +            src1+=stride1;
 +            src2+=stride2;
 +            src3+=stride3;
 +            src4+=stride4;
 +            dst +=stride;
 +        }
 +    }else{
 +        const uint8_t *src1= hpel[l];
 +        const uint8_t *src2= hpel[r];
 +        int stride1 = MC_STRIDE(l);
 +        int stride2 = MC_STRIDE(r);
 +        int a= weight[((dx&7) + (8*(dy&7)))];
 +        int b= 8-a;
 +        for(y=0; y < b_h; y++){
 +            for(x=0; x < b_w; x++){
 +                dst[x]= (a*src1[x] + b*src2[x] + 4)>>3;
 +            }
 +            src1+=stride1;
 +            src2+=stride2;
 +            dst +=stride;
 +        }
 +    }
 +}
 +
 +void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){
 +    if(block->type & BLOCK_INTRA){
 +        int x, y;
 +        const unsigned color  = block->color[plane_index];
 +        const unsigned color4 = color*0x01010101;
 +        if(b_w==32){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +                *(uint32_t*)&dst[4 + y*stride]= color4;
 +                *(uint32_t*)&dst[8 + y*stride]= color4;
 +                *(uint32_t*)&dst[12+ y*stride]= color4;
 +                *(uint32_t*)&dst[16+ y*stride]= color4;
 +                *(uint32_t*)&dst[20+ y*stride]= color4;
 +                *(uint32_t*)&dst[24+ y*stride]= color4;
 +                *(uint32_t*)&dst[28+ y*stride]= color4;
 +            }
 +        }else if(b_w==16){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +                *(uint32_t*)&dst[4 + y*stride]= color4;
 +                *(uint32_t*)&dst[8 + y*stride]= color4;
 +                *(uint32_t*)&dst[12+ y*stride]= color4;
 +            }
 +        }else if(b_w==8){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +                *(uint32_t*)&dst[4 + y*stride]= color4;
 +            }
 +        }else if(b_w==4){
 +            for(y=0; y < b_h; y++){
 +                *(uint32_t*)&dst[0 + y*stride]= color4;
 +            }
 +        }else{
 +            for(y=0; y < b_h; y++){
 +                for(x=0; x < b_w; x++){
 +                    dst[x + y*stride]= color;
 +                }
 +            }
 +        }
 +    }else{
 +        uint8_t *src= s->last_picture[block->ref].data[plane_index];
 +        const int scale= plane_index ?  (2*s->mv_scale)>>s->chroma_h_shift : 2*s->mv_scale;
 +        int mx= block->mx*scale;
 +        int my= block->my*scale;
 +        const int dx= mx&15;
 +        const int dy= my&15;
 +        const int tab_index= 3 - (b_w>>2) + (b_w>>4);
 +        sx += (mx>>4) - (HTAPS_MAX/2-1);
 +        sy += (my>>4) - (HTAPS_MAX/2-1);
 +        src += sx + sy*stride;
 +        if(   (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)
 +           || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){
 +            s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
 +            src= tmp + MB_SIZE;
 +        }
 +
 +        av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale
 +
 +//        assert(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h);
 +//        assert(!(b_w&(b_w-1)));
 +        av_assert2(b_w>1 && b_h>1);
 +        av_assert2((tab_index>=0 && tab_index<4) || b_w==32);
 +        if((dx&3) || (dy&3) || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) || (b_w&(b_w-1)) || !s->plane[plane_index].fast_mc )
 +            mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);
 +        else if(b_w==32){
 +            int y;
 +            for(y=0; y<b_h; y+=16){
 +                s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 3 + (y+3)*stride,stride);
 +                s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 19 + (y+3)*stride,stride);
 +            }
 +        }else if(b_w==b_h)
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst,src + 3 + 3*stride,stride);
 +        else if(b_w==2*b_h){
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst    ,src + 3       + 3*stride,stride);
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 3 + b_h + 3*stride,stride);
 +        }else{
 +            av_assert2(2*b_w==b_h);
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst           ,src + 3 + 3*stride           ,stride);
 +            s->h264qpel.put_h264_qpel_pixels_tab[tab_index  ][dy+(dx>>2)](dst+b_w*stride,src + 3 + 3*stride+b_w*stride,stride);
 +        }
 +    }
 +}
 +
 +#define mca(dx,dy,b_w)\
 +static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int h){\
 +    av_assert2(h==b_w);\
 +    mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, stride, b_w, b_w, dx, dy);\
 +}
 +
 +mca( 0, 0,16)
 +mca( 8, 0,16)
 +mca( 0, 8,16)
 +mca( 8, 8,16)
 +mca( 0, 0,8)
 +mca( 8, 0,8)
 +mca( 0, 8,8)
 +mca( 8, 8,8)
 +
 +av_cold int ff_snow_common_init(AVCodecContext *avctx){
 +    SnowContext *s = avctx->priv_data;
 +    int width, height;
 +    int i, j;
 +
 +    s->avctx= avctx;
 +    s->max_ref_frames=1; //just make sure it's not an invalid value in case of no initial keyframe
 +
 +    ff_dsputil_init(&s->dsp, avctx);
 +    ff_videodsp_init(&s->vdsp, 8);
 +    ff_dwt_init(&s->dwt);
 +    ff_h264qpel_init(&s->h264qpel, 8);
 +
 +#define mcf(dx,dy)\
 +    s->dsp.put_qpel_pixels_tab       [0][dy+dx/4]=\
 +    s->dsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\
 +        s->h264qpel.put_h264_qpel_pixels_tab[0][dy+dx/4];\
 +    s->dsp.put_qpel_pixels_tab       [1][dy+dx/4]=\
 +    s->dsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\
 +        s->h264qpel.put_h264_qpel_pixels_tab[1][dy+dx/4];
 +
 +    mcf( 0, 0)
 +    mcf( 4, 0)
 +    mcf( 8, 0)
 +    mcf(12, 0)
 +    mcf( 0, 4)
 +    mcf( 4, 4)
 +    mcf( 8, 4)
 +    mcf(12, 4)
 +    mcf( 0, 8)
 +    mcf( 4, 8)
 +    mcf( 8, 8)
 +    mcf(12, 8)
 +    mcf( 0,12)
 +    mcf( 4,12)
 +    mcf( 8,12)
 +    mcf(12,12)
 +
 +#define mcfh(dx,dy)\
 +    s->dsp.put_pixels_tab       [0][dy/4+dx/8]=\
 +    s->dsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
 +        mc_block_hpel ## dx ## dy ## 16;\
 +    s->dsp.put_pixels_tab       [1][dy/4+dx/8]=\
 +    s->dsp.put_no_rnd_pixels_tab[1][dy/4+dx/8]=\
 +        mc_block_hpel ## dx ## dy ## 8;
 +
 +    mcfh(0, 0)
 +    mcfh(8, 0)
 +    mcfh(0, 8)
 +    mcfh(8, 8)
 +
 +    init_qexp();
 +
 +//    dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift);
 +
 +    width= s->avctx->width;
 +    height= s->avctx->height;
 +
 +    FF_ALLOCZ_OR_GOTO(avctx, s->spatial_idwt_buffer, width * height * sizeof(IDWTELEM), fail);
 +    FF_ALLOCZ_OR_GOTO(avctx, s->spatial_dwt_buffer,  width * height * sizeof(DWTELEM),  fail); //FIXME this does not belong here
 +    FF_ALLOCZ_OR_GOTO(avctx, s->temp_dwt_buffer,     width * sizeof(DWTELEM),  fail);
 +    FF_ALLOCZ_OR_GOTO(avctx, s->temp_idwt_buffer,    width * sizeof(IDWTELEM), fail);
 +    FF_ALLOC_OR_GOTO(avctx,  s->run_buffer,          ((width + 1) >> 1) * ((height + 1) >> 1) * sizeof(*s->run_buffer), fail);
 +
 +    for(i=0; i<MAX_REF_FRAMES; i++)
 +        for(j=0; j<MAX_REF_FRAMES; j++)
 +            ff_scale_mv_ref[i][j] = 256*(i+1)/(j+1);
 +
 +    return 0;
 +fail:
 +    return AVERROR(ENOMEM);
 +}
 +
 +int ff_snow_common_init_after_header(AVCodecContext *avctx) {
 +    SnowContext *s = avctx->priv_data;
 +    int plane_index, level, orientation;
 +    int ret, emu_buf_size;
 +
 +    if(!s->scratchbuf) {
-         avctx->release_buffer(avctx, &s->last_picture[s->max_ref_frames-1]);
++        if ((ret = ff_get_buffer(s->avctx, &s->mconly_picture, AV_GET_BUFFER_FLAG_REF)) < 0) {
 +            av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +            return ret;
 +        }
 +        FF_ALLOCZ_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture.linesize[0], 2*avctx->width+256)*7*MB_SIZE, fail);
 +        emu_buf_size = FFMAX(s->mconly_picture.linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1);
 +        FF_ALLOC_OR_GOTO(avctx, s->emu_edge_buffer, emu_buf_size, fail);
 +    }
 +
 +    if(s->mconly_picture.format != avctx->pix_fmt) {
 +        av_log(avctx, AV_LOG_ERROR, "pixel format changed\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        int w= s->avctx->width;
 +        int h= s->avctx->height;
 +
 +        if(plane_index){
 +            w>>= s->chroma_h_shift;
 +            h>>= s->chroma_v_shift;
 +        }
 +        s->plane[plane_index].width = w;
 +        s->plane[plane_index].height= h;
 +
 +        for(level=s->spatial_decomposition_count-1; level>=0; level--){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &s->plane[plane_index].band[level][orientation];
 +
 +                b->buf= s->spatial_dwt_buffer;
 +                b->level= level;
 +                b->stride= s->plane[plane_index].width << (s->spatial_decomposition_count - level);
 +                b->width = (w + !(orientation&1))>>1;
 +                b->height= (h + !(orientation>1))>>1;
 +
 +                b->stride_line = 1 << (s->spatial_decomposition_count - level);
 +                b->buf_x_offset = 0;
 +                b->buf_y_offset = 0;
 +
 +                if(orientation&1){
 +                    b->buf += (w+1)>>1;
 +                    b->buf_x_offset = (w+1)>>1;
 +                }
 +                if(orientation>1){
 +                    b->buf += b->stride>>1;
 +                    b->buf_y_offset = b->stride_line >> 1;
 +                }
 +                b->ibuf= s->spatial_idwt_buffer + (b->buf - s->spatial_dwt_buffer);
 +
 +                if(level)
 +                    b->parent= &s->plane[plane_index].band[level-1][orientation];
 +                //FIXME avoid this realloc
 +                av_freep(&b->x_coeff);
 +                b->x_coeff=av_mallocz(((b->width+1) * b->height+1)*sizeof(x_and_coeff));
 +            }
 +            w= (w+1)>>1;
 +            h= (h+1)>>1;
 +        }
 +    }
 +
 +    return 0;
 +fail:
 +    return AVERROR(ENOMEM);
 +}
 +
 +#define USE_HALFPEL_PLANE 0
 +
 +static void halfpel_interpol(SnowContext *s, uint8_t *halfpel[4][4], AVFrame *frame){
 +    int p,x,y;
 +
 +    for(p=0; p<3; p++){
 +        int is_chroma= !!p;
 +        int w= is_chroma ? s->avctx->width >>s->chroma_h_shift : s->avctx->width;
 +        int h= is_chroma ? s->avctx->height>>s->chroma_v_shift : s->avctx->height;
 +        int ls= frame->linesize[p];
 +        uint8_t *src= frame->data[p];
 +
 +        halfpel[1][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);
 +        halfpel[2][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);
 +        halfpel[3][p] = (uint8_t*) av_malloc(ls * (h + 2 * EDGE_WIDTH)) + EDGE_WIDTH * (1 + ls);
 +
 +        halfpel[0][p]= src;
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= y*ls + x;
 +
 +                halfpel[1][p][i]= (20*(src[i] + src[i+1]) - 5*(src[i-1] + src[i+2]) + (src[i-2] + src[i+3]) + 16 )>>5;
 +            }
 +        }
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= y*ls + x;
 +
 +                halfpel[2][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;
 +            }
 +        }
 +        src= halfpel[1][p];
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= y*ls + x;
 +
 +                halfpel[3][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;
 +            }
 +        }
 +
 +//FIXME border!
 +    }
 +}
 +
 +void ff_snow_release_buffer(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +    int i;
 +
 +    if(s->last_picture[s->max_ref_frames-1].data[0]){
-     tmp= s->last_picture[s->max_ref_frames-1];
-     memmove(s->last_picture+1, s->last_picture, (s->max_ref_frames-1)*sizeof(AVFrame));
++        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])
 +                av_free(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] - EDGE_WIDTH*(1+s->current_picture.linesize[i%3]));
 +    }
 +}
 +
 +int ff_snow_frame_start(SnowContext *s){
 +   AVFrame tmp;
++   int i;
 +   int w= s->avctx->width; //FIXME round up to x16 ?
 +   int h= s->avctx->height;
 +
 +    if (s->current_picture.data[0] && !(s->avctx->flags&CODEC_FLAG_EMU_EDGE)) {
 +        s->dsp.draw_edges(s->current_picture.data[0],
 +                          s->current_picture.linesize[0], w   , h   ,
 +                          EDGE_WIDTH  , EDGE_WIDTH  , EDGE_TOP | EDGE_BOTTOM);
 +        s->dsp.draw_edges(s->current_picture.data[1],
 +                          s->current_picture.linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
 +                          EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
 +        s->dsp.draw_edges(s->current_picture.data[2],
 +                          s->current_picture.linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
 +                          EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
 +    }
 +
 +    ff_snow_release_buffer(s->avctx);
 +
-     s->last_picture[0]= s->current_picture;
-     s->current_picture= tmp;
++    av_frame_move_ref(&tmp, &s->last_picture[s->max_ref_frames-1]);
++    for(i=s->max_ref_frames-1; i>0; i--)
++        av_frame_move_ref(&s->last_picture[i+1], &s->last_picture[i]);
 +    memmove(s->halfpel_plane+1, s->halfpel_plane, (s->max_ref_frames-1)*sizeof(void*)*4*4);
 +    if(USE_HALFPEL_PLANE && s->current_picture.data[0])
 +        halfpel_interpol(s, s->halfpel_plane[0], &s->current_picture);
-     s->current_picture.reference= 3;
-     if(ff_get_buffer(s->avctx, &s->current_picture) < 0){
++    av_frame_move_ref(&s->last_picture[0], &s->current_picture);
++    av_frame_move_ref(&s->current_picture, &tmp);
 +
 +    if(s->keyframe){
 +        s->ref_frames= 0;
 +    }else{
 +        int i;
 +        for(i=0; i<s->max_ref_frames && s->last_picture[i].data[0]; i++)
 +            if(i && s->last_picture[i-1].key_frame)
 +                break;
 +        s->ref_frames= i;
 +        if(s->ref_frames==0){
 +            av_log(s->avctx,AV_LOG_ERROR, "No reference frames\n");
 +            return -1;
 +        }
 +    }
 +
-             s->avctx->release_buffer(s->avctx, &s->last_picture[i]);
++    if(ff_get_buffer(s->avctx, &s->current_picture, AV_GET_BUFFER_FLAG_REF) < 0){
 +        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return -1;
 +    }
 +
 +    s->current_picture.key_frame= s->keyframe;
 +
 +    return 0;
 +}
 +
 +av_cold void ff_snow_common_end(SnowContext *s)
 +{
 +    int plane_index, level, orientation, i;
 +
 +    av_freep(&s->spatial_dwt_buffer);
 +    av_freep(&s->temp_dwt_buffer);
 +    av_freep(&s->spatial_idwt_buffer);
 +    av_freep(&s->temp_idwt_buffer);
 +    av_freep(&s->run_buffer);
 +
 +    s->m.me.temp= NULL;
 +    av_freep(&s->m.me.scratchpad);
 +    av_freep(&s->m.me.map);
 +    av_freep(&s->m.me.score_map);
 +    av_freep(&s->m.obmc_scratchpad);
 +
 +    av_freep(&s->block);
 +    av_freep(&s->scratchbuf);
 +    av_freep(&s->emu_edge_buffer);
 +
 +    for(i=0; i<MAX_REF_FRAMES; i++){
 +        av_freep(&s->ref_mvs[i]);
 +        av_freep(&s->ref_scores[i]);
 +        if(s->last_picture[i].data[0]) {
 +            av_assert0(s->last_picture[i].data[0] != s->current_picture.data[0]);
-     if (s->mconly_picture.data[0])
-         s->avctx->release_buffer(s->avctx, &s->mconly_picture);
-     if (s->current_picture.data[0])
-         s->avctx->release_buffer(s->avctx, &s->current_picture);
++            av_frame_unref(&s->last_picture[i]);
 +        }
 +    }
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        for(level=s->spatial_decomposition_count-1; level>=0; level--){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &s->plane[plane_index].band[level][orientation];
 +
 +                av_freep(&b->x_coeff);
 +            }
 +        }
 +    }
++    av_frame_unref(&s->mconly_picture);
++    av_frame_unref(&s->current_picture);
 +}
index 1bfd096,0000000..c8a0327
mode 100644,000000..100644
--- /dev/null
@@@ -1,587 -1,0 +1,587 @@@
-         *picture= s->current_picture;
 +/*
 + * Copyright (C) 2004 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 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/intmath.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "dsputil.h"
 +#include "snow_dwt.h"
 +#include "internal.h"
 +#include "snow.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +
 +#include "mpegvideo.h"
 +#include "h263.h"
 +
 +#undef NDEBUG
 +#include <assert.h>
 +
 +static av_always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){
 +    Plane *p= &s->plane[plane_index];
 +    const int mb_w= s->b_width  << s->block_max_depth;
 +    const int mb_h= s->b_height << s->block_max_depth;
 +    int x, y, mb_x;
 +    int block_size = MB_SIZE >> s->block_max_depth;
 +    int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    int ref_stride= s->current_picture.linesize[plane_index];
 +    uint8_t *dst8= s->current_picture.data[plane_index];
 +    int w= p->width;
 +    int h= p->height;
 +
 +    if(s->keyframe || (s->avctx->debug&512)){
 +        if(mb_y==mb_h)
 +            return;
 +
 +        if(add){
 +            for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
 +//                DWTELEM * line = slice_buffer_get_line(sb, y);
 +                IDWTELEM * line = sb->line[y];
 +                for(x=0; x<w; x++){
 +//                    int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
 +                    int v= line[x] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
 +                    v >>= FRAC_BITS;
 +                    if(v&(~255)) v= ~(v>>31);
 +                    dst8[x + y*ref_stride]= v;
 +                }
 +            }
 +        }else{
 +            for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
 +//                DWTELEM * line = slice_buffer_get_line(sb, y);
 +                IDWTELEM * line = sb->line[y];
 +                for(x=0; x<w; x++){
 +                    line[x] -= 128 << FRAC_BITS;
 +//                    buf[x + y*w]-= 128<<FRAC_BITS;
 +                }
 +            }
 +        }
 +
 +        return;
 +    }
 +
 +    for(mb_x=0; mb_x<=mb_w; mb_x++){
 +        add_yblock(s, 1, sb, old_buffer, dst8, obmc,
 +                   block_w*mb_x - block_w/2,
 +                   block_h*mb_y - block_h/2,
 +                   block_w, block_h,
 +                   w, h,
 +                   w, ref_stride, obmc_stride,
 +                   mb_x - 1, mb_y - 1,
 +                   add, 0, plane_index);
 +    }
 +}
 +
 +static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){
 +    const int w= b->width;
 +    int y;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +    int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
 +    int new_index = 0;
 +
 +    if(b->ibuf == s->spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){
 +        qadd= 0;
 +        qmul= 1<<QEXPSHIFT;
 +    }
 +
 +    /* If we are on the second or later slice, restore our index. */
 +    if (start_y != 0)
 +        new_index = save_state[0];
 +
 +
 +    for(y=start_y; y<h; y++){
 +        int x = 0;
 +        int v;
 +        IDWTELEM * line = slice_buffer_get_line(sb, y * b->stride_line + b->buf_y_offset) + b->buf_x_offset;
 +        memset(line, 0, b->width*sizeof(IDWTELEM));
 +        v = b->x_coeff[new_index].coeff;
 +        x = b->x_coeff[new_index++].x;
 +        while(x < w){
 +            register int t= ( (v>>1)*qmul + qadd)>>QEXPSHIFT;
 +            register int u= -(v&1);
 +            line[x] = (t^u) - u;
 +
 +            v = b->x_coeff[new_index].coeff;
 +            x = b->x_coeff[new_index++].x;
 +        }
 +    }
 +
 +    /* Save our variables for the next slice. */
 +    save_state[0] = new_index;
 +
 +    return;
 +}
 +
 +static int decode_q_branch(SnowContext *s, int level, int x, int y){
 +    const int w= s->b_width << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    int trx= (x+1)<<rem_depth;
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
 +    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
 +    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
 +    int res;
 +
 +    if(s->keyframe){
 +        set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA);
 +        return 0;
 +    }
 +
 +    if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){
 +        int type, mx, my;
 +        int l = left->color[0];
 +        int cb= left->color[1];
 +        int cr= left->color[2];
 +        int ref = 0;
 +        int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
 +        int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 0*av_log2(2*FFABS(tr->mx - top->mx));
 +        int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my));
 +
 +        type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0;
 +
 +        if(type){
 +            pred_mv(s, &mx, &my, 0, left, top, tr);
 +            l += get_symbol(&s->c, &s->block_state[32], 1);
 +            cb+= get_symbol(&s->c, &s->block_state[64], 1);
 +            cr+= get_symbol(&s->c, &s->block_state[96], 1);
 +        }else{
 +            if(s->ref_frames > 1)
 +                ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);
 +            if (ref >= s->ref_frames) {
 +                av_log(s->avctx, AV_LOG_ERROR, "Invalid ref\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +            pred_mv(s, &mx, &my, ref, left, top, tr);
 +            mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);
 +            my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1);
 +        }
 +        set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type);
 +    }else{
 +        if ((res = decode_q_branch(s, level+1, 2*x+0, 2*y+0)) < 0 ||
 +            (res = decode_q_branch(s, level+1, 2*x+1, 2*y+0)) < 0 ||
 +            (res = decode_q_branch(s, level+1, 2*x+0, 2*y+1)) < 0 ||
 +            (res = decode_q_branch(s, level+1, 2*x+1, 2*y+1)) < 0)
 +            return res;
 +    }
 +    return 0;
 +}
 +
 +static void dequantize_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int start_y, int end_y){
 +    const int w= b->width;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +    const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
 +    int x,y;
 +
 +    if(s->qlog == LOSSLESS_QLOG) return;
 +
 +    for(y=start_y; y<end_y; y++){
 +//        DWTELEM * line = slice_buffer_get_line_from_address(sb, src + (y * stride));
 +        IDWTELEM * line = slice_buffer_get_line(sb, (y * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
 +        for(x=0; x<w; x++){
 +            int i= line[x];
 +            if(i<0){
 +                line[x]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
 +            }else if(i>0){
 +                line[x]=  (( i*qmul + qadd)>>(QEXPSHIFT));
 +            }
 +        }
 +    }
 +}
 +
 +static void correlate_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median, int start_y, int end_y){
 +    const int w= b->width;
 +    int x,y;
 +
 +    IDWTELEM * line=0; // silence silly "could be used without having been initialized" warning
 +    IDWTELEM * prev;
 +
 +    if (start_y != 0)
 +        line = slice_buffer_get_line(sb, ((start_y - 1) * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
 +
 +    for(y=start_y; y<end_y; y++){
 +        prev = line;
 +//        line = slice_buffer_get_line_from_address(sb, src + (y * stride));
 +        line = slice_buffer_get_line(sb, (y * b->stride_line) + b->buf_y_offset) + b->buf_x_offset;
 +        for(x=0; x<w; x++){
 +            if(x){
 +                if(use_median){
 +                    if(y && x+1<w) line[x] += mid_pred(line[x - 1], prev[x], prev[x + 1]);
 +                    else  line[x] += line[x - 1];
 +                }else{
 +                    if(y) line[x] += mid_pred(line[x - 1], prev[x], line[x - 1] + prev[x] - prev[x - 1]);
 +                    else  line[x] += line[x - 1];
 +                }
 +            }else{
 +                if(y) line[x] += prev[x];
 +            }
 +        }
 +    }
 +}
 +
 +static void decode_qlogs(SnowContext *s){
 +    int plane_index, level, orientation;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1:0; orientation<4; orientation++){
 +                int q;
 +                if     (plane_index==2) q= s->plane[1].band[level][orientation].qlog;
 +                else if(orientation==2) q= s->plane[plane_index].band[level][1].qlog;
 +                else                    q= get_symbol(&s->c, s->header_state, 1);
 +                s->plane[plane_index].band[level][orientation].qlog= q;
 +            }
 +        }
 +    }
 +}
 +
 +#define GET_S(dst, check) \
 +    tmp= get_symbol(&s->c, s->header_state, 0);\
 +    if(!(check)){\
 +        av_log(s->avctx, AV_LOG_ERROR, "Error " #dst " is %d\n", tmp);\
 +        return -1;\
 +    }\
 +    dst= tmp;
 +
 +static int decode_header(SnowContext *s){
 +    int plane_index, tmp;
 +    uint8_t kstate[32];
 +
 +    memset(kstate, MID_STATE, sizeof(kstate));
 +
 +    s->keyframe= get_rac(&s->c, kstate);
 +    if(s->keyframe || s->always_reset){
 +        ff_snow_reset_contexts(s);
 +        s->spatial_decomposition_type=
 +        s->qlog=
 +        s->qbias=
 +        s->mv_scale=
 +        s->block_max_depth= 0;
 +    }
 +    if(s->keyframe){
 +        GET_S(s->version, tmp <= 0U)
 +        s->always_reset= get_rac(&s->c, s->header_state);
 +        s->temporal_decomposition_type= get_symbol(&s->c, s->header_state, 0);
 +        s->temporal_decomposition_count= get_symbol(&s->c, s->header_state, 0);
 +        GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS)
 +        s->colorspace_type= get_symbol(&s->c, s->header_state, 0);
 +        s->chroma_h_shift= get_symbol(&s->c, s->header_state, 0);
 +        s->chroma_v_shift= get_symbol(&s->c, s->header_state, 0);
 +
 +        if(s->chroma_h_shift == 1 && s->chroma_v_shift==1){
 +            s->avctx->pix_fmt= AV_PIX_FMT_YUV420P;
 +        }else if(s->chroma_h_shift == 0 && s->chroma_v_shift==0){
 +            s->avctx->pix_fmt= AV_PIX_FMT_YUV444P;
 +        }else if(s->chroma_h_shift == 2 && s->chroma_v_shift==2){
 +            s->avctx->pix_fmt= AV_PIX_FMT_YUV410P;
 +        } else {
 +            av_log(s, AV_LOG_ERROR, "unsupported color subsample mode %d %d\n", s->chroma_h_shift, s->chroma_v_shift);
 +            s->chroma_h_shift = s->chroma_v_shift = 1;
 +            s->avctx->pix_fmt= AV_PIX_FMT_YUV420P;
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        s->spatial_scalability= get_rac(&s->c, s->header_state);
 +//        s->rate_scalability= get_rac(&s->c, s->header_state);
 +        GET_S(s->max_ref_frames, tmp < (unsigned)MAX_REF_FRAMES)
 +        s->max_ref_frames++;
 +
 +        decode_qlogs(s);
 +    }
 +
 +    if(!s->keyframe){
 +        if(get_rac(&s->c, s->header_state)){
 +            for(plane_index=0; plane_index<2; plane_index++){
 +                int htaps, i, sum=0;
 +                Plane *p= &s->plane[plane_index];
 +                p->diag_mc= get_rac(&s->c, s->header_state);
 +                htaps= get_symbol(&s->c, s->header_state, 0)*2 + 2;
 +                if((unsigned)htaps > HTAPS_MAX || htaps==0)
 +                    return -1;
 +                p->htaps= htaps;
 +                for(i= htaps/2; i; i--){
 +                    p->hcoeff[i]= get_symbol(&s->c, s->header_state, 0) * (1-2*(i&1));
 +                    sum += p->hcoeff[i];
 +                }
 +                p->hcoeff[0]= 32-sum;
 +            }
 +            s->plane[2].diag_mc= s->plane[1].diag_mc;
 +            s->plane[2].htaps  = s->plane[1].htaps;
 +            memcpy(s->plane[2].hcoeff, s->plane[1].hcoeff, sizeof(s->plane[1].hcoeff));
 +        }
 +        if(get_rac(&s->c, s->header_state)){
 +            GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS)
 +            decode_qlogs(s);
 +        }
 +    }
 +
 +    s->spatial_decomposition_type+= get_symbol(&s->c, s->header_state, 1);
 +    if(s->spatial_decomposition_type > 1U){
 +        av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_type %d not supported\n", s->spatial_decomposition_type);
 +        return -1;
 +    }
 +    if(FFMIN(s->avctx-> width>>s->chroma_h_shift,
 +             s->avctx->height>>s->chroma_v_shift) >> (s->spatial_decomposition_count-1) <= 1){
 +        av_log(s->avctx, AV_LOG_ERROR, "spatial_decomposition_count %d too large for size\n", s->spatial_decomposition_count);
 +        return -1;
 +    }
 +
 +
 +    s->qlog           += get_symbol(&s->c, s->header_state, 1);
 +    s->mv_scale       += get_symbol(&s->c, s->header_state, 1);
 +    s->qbias          += get_symbol(&s->c, s->header_state, 1);
 +    s->block_max_depth+= get_symbol(&s->c, s->header_state, 1);
 +    if(s->block_max_depth > 1 || s->block_max_depth < 0){
 +        av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth);
 +        s->block_max_depth= 0;
 +        return -1;
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    int ret;
 +
 +    if ((ret = ff_snow_common_init(avctx)) < 0) {
 +        ff_snow_common_end(avctx->priv_data);
 +        return ret;
 +    }
 +
 +    return 0;
 +}
 +
 +static int decode_blocks(SnowContext *s){
 +    int x, y;
 +    int w= s->b_width;
 +    int h= s->b_height;
 +    int res;
 +
 +    for(y=0; y<h; y++){
 +        for(x=0; x<w; x++){
 +            if ((res = decode_q_branch(s, 0, x, y)) < 0)
 +                return res;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
 +                        AVPacket *avpkt)
 +{
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    SnowContext *s = avctx->priv_data;
 +    RangeCoder * const c= &s->c;
 +    int bytes_read;
 +    AVFrame *picture = data;
 +    int level, orientation, plane_index;
 +    int res;
 +
 +    ff_init_range_decoder(c, buf, buf_size);
 +    ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
 +
 +    s->current_picture.pict_type= AV_PICTURE_TYPE_I; //FIXME I vs. P
 +    if(decode_header(s)<0)
 +        return -1;
 +    if ((res=ff_snow_common_init_after_header(avctx)) < 0)
 +        return res;
 +
 +    // realloc slice buffer for the case that spatial_decomposition_count changed
 +    ff_slice_buffer_destroy(&s->sb);
 +    if ((res = ff_slice_buffer_init(&s->sb, s->plane[0].height,
 +                                    (MB_SIZE >> s->block_max_depth) +
 +                                    s->spatial_decomposition_count * 11 + 1,
 +                                    s->plane[0].width,
 +                                    s->spatial_idwt_buffer)) < 0)
 +        return res;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        Plane *p= &s->plane[plane_index];
 +        p->fast_mc= p->diag_mc && p->htaps==6 && p->hcoeff[0]==40
 +                                              && p->hcoeff[1]==-10
 +                                              && p->hcoeff[2]==2;
 +    }
 +
 +    ff_snow_alloc_blocks(s);
 +
 +    if(ff_snow_frame_start(s) < 0)
 +        return -1;
 +    //keyframe flag duplication mess FIXME
 +    if(avctx->debug&FF_DEBUG_PICT_INFO)
 +        av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog);
 +
 +    if ((res = decode_blocks(s)) < 0)
 +        return res;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        Plane *p= &s->plane[plane_index];
 +        int w= p->width;
 +        int h= p->height;
 +        int x, y;
 +        int decode_state[MAX_DECOMPOSITIONS][4][1]; /* Stored state info for unpack_coeffs. 1 variable per instance. */
 +
 +        if(s->avctx->debug&2048){
 +            memset(s->spatial_dwt_buffer, 0, sizeof(DWTELEM)*w*h);
 +            predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
 +
 +            for(y=0; y<h; y++){
 +                for(x=0; x<w; x++){
 +                    int v= s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x];
 +                    s->mconly_picture.data[plane_index][y*s->mconly_picture.linesize[plane_index] + x]= v;
 +                }
 +            }
 +        }
 +
 +        {
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &p->band[level][orientation];
 +                unpack_coeffs(s, b, b->parent, orientation);
 +            }
 +        }
 +        }
 +
 +        {
 +        const int mb_h= s->b_height << s->block_max_depth;
 +        const int block_size = MB_SIZE >> s->block_max_depth;
 +        const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +        int mb_y;
 +        DWTCompose cs[MAX_DECOMPOSITIONS];
 +        int yd=0, yq=0;
 +        int y;
 +        int end_y;
 +
 +        ff_spatial_idwt_buffered_init(cs, &s->sb, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count);
 +        for(mb_y=0; mb_y<=mb_h; mb_y++){
 +
 +            int slice_starty = block_h*mb_y;
 +            int slice_h = block_h*(mb_y+1);
 +
 +            if (!(s->keyframe || s->avctx->debug&512)){
 +                slice_starty = FFMAX(0, slice_starty - (block_h >> 1));
 +                slice_h -= (block_h >> 1);
 +            }
 +
 +            for(level=0; level<s->spatial_decomposition_count; level++){
 +                for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                    SubBand *b= &p->band[level][orientation];
 +                    int start_y;
 +                    int end_y;
 +                    int our_mb_start = mb_y;
 +                    int our_mb_end = (mb_y + 1);
 +                    const int extra= 3;
 +                    start_y = (mb_y ? ((block_h * our_mb_start) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra: 0);
 +                    end_y = (((block_h * our_mb_end) >> (s->spatial_decomposition_count - level)) + s->spatial_decomposition_count - level + extra);
 +                    if (!(s->keyframe || s->avctx->debug&512)){
 +                        start_y = FFMAX(0, start_y - (block_h >> (1+s->spatial_decomposition_count - level)));
 +                        end_y = FFMAX(0, end_y - (block_h >> (1+s->spatial_decomposition_count - level)));
 +                    }
 +                    start_y = FFMIN(b->height, start_y);
 +                    end_y = FFMIN(b->height, end_y);
 +
 +                    if (start_y != end_y){
 +                        if (orientation == 0){
 +                            SubBand * correlate_band = &p->band[0][0];
 +                            int correlate_end_y = FFMIN(b->height, end_y + 1);
 +                            int correlate_start_y = FFMIN(b->height, (start_y ? start_y + 1 : 0));
 +                            decode_subband_slice_buffered(s, correlate_band, &s->sb, correlate_start_y, correlate_end_y, decode_state[0][0]);
 +                            correlate_slice_buffered(s, &s->sb, correlate_band, correlate_band->ibuf, correlate_band->stride, 1, 0, correlate_start_y, correlate_end_y);
 +                            dequantize_slice_buffered(s, &s->sb, correlate_band, correlate_band->ibuf, correlate_band->stride, start_y, end_y);
 +                        }
 +                        else
 +                            decode_subband_slice_buffered(s, b, &s->sb, start_y, end_y, decode_state[level][orientation]);
 +                    }
 +                }
 +            }
 +
 +            for(; yd<slice_h; yd+=4){
 +                ff_spatial_idwt_buffered_slice(&s->dwt, cs, &s->sb, s->temp_idwt_buffer, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count, yd);
 +            }
 +
 +            if(s->qlog == LOSSLESS_QLOG){
 +                for(; yq<slice_h && yq<h; yq++){
 +                    IDWTELEM * line = slice_buffer_get_line(&s->sb, yq);
 +                    for(x=0; x<w; x++){
 +                        line[x] <<= FRAC_BITS;
 +                    }
 +                }
 +            }
 +
 +            predict_slice_buffered(s, &s->sb, s->spatial_idwt_buffer, plane_index, 1, mb_y);
 +
 +            y = FFMIN(p->height, slice_starty);
 +            end_y = FFMIN(p->height, slice_h);
 +            while(y < end_y)
 +                ff_slice_buffer_release(&s->sb, y++);
 +        }
 +
 +        ff_slice_buffer_flush(&s->sb);
 +        }
 +
 +    }
 +
 +    emms_c();
 +
 +    ff_snow_release_buffer(avctx);
 +
 +    if(!(s->avctx->debug&2048))
-         *picture= s->mconly_picture;
++        av_frame_ref(picture, &s->current_picture);
 +    else
++        av_frame_ref(picture, &s->mconly_picture);
 +
 +    *got_frame = 1;
 +
 +    bytes_read= c->bytestream - c->bytestream_start;
 +    if(bytes_read ==0) av_log(s->avctx, AV_LOG_ERROR, "error at end of frame\n"); //FIXME
 +
 +    return bytes_read;
 +}
 +
 +static av_cold int decode_end(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +
 +    ff_slice_buffer_destroy(&s->sb);
 +
 +    ff_snow_common_end(s);
 +
 +    return 0;
 +}
 +
 +AVCodec ff_snow_decoder = {
 +    .name           = "snow",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_SNOW,
 +    .priv_data_size = sizeof(SnowContext),
 +    .init           = decode_init,
 +    .close          = decode_end,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
 +    .long_name      = NULL_IF_CONFIG_SMALL("Snow"),
 +};
index c0c847a,0000000..624278b
mode 100644,000000..100644
--- /dev/null
@@@ -1,2111 -1,0 +1,2110 @@@
-     if ((ret = ff_get_buffer(s->avctx, &s->input_picture)) < 0)
 +/*
 + * Copyright (C) 2004 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 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/intmath.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "dsputil.h"
 +#include "internal.h"
 +#include "snow_dwt.h"
 +#include "snow.h"
 +
 +#include "rangecoder.h"
 +#include "mathops.h"
 +
 +#include "mpegvideo.h"
 +#include "h263.h"
 +
 +#undef NDEBUG
 +#include <assert.h>
 +
 +#define QUANTIZE2 0
 +
 +#if QUANTIZE2==1
 +#define Q2_STEP 8
 +
 +static void find_sse(SnowContext *s, Plane *p, int *score, int score_stride, IDWTELEM *r0, IDWTELEM *r1, int level, int orientation){
 +    SubBand *b= &p->band[level][orientation];
 +    int x, y;
 +    int xo=0;
 +    int yo=0;
 +    int step= 1 << (s->spatial_decomposition_count - level);
 +
 +    if(orientation&1)
 +        xo= step>>1;
 +    if(orientation&2)
 +        yo= step>>1;
 +
 +    //FIXME bias for nonzero ?
 +    //FIXME optimize
 +    memset(score, 0, sizeof(*score)*score_stride*((p->height + Q2_STEP-1)/Q2_STEP));
 +    for(y=0; y<p->height; y++){
 +        for(x=0; x<p->width; x++){
 +            int sx= (x-xo + step/2) / step / Q2_STEP;
 +            int sy= (y-yo + step/2) / step / Q2_STEP;
 +            int v= r0[x + y*p->width] - r1[x + y*p->width];
 +            assert(sx>=0 && sy>=0 && sx < score_stride);
 +            v= ((v+8)>>4)<<4;
 +            score[sx + sy*score_stride] += v*v;
 +            assert(score[sx + sy*score_stride] >= 0);
 +        }
 +    }
 +}
 +
 +static void dequantize_all(SnowContext *s, Plane *p, IDWTELEM *buffer, int width, int height){
 +    int level, orientation;
 +
 +    for(level=0; level<s->spatial_decomposition_count; level++){
 +        for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +            SubBand *b= &p->band[level][orientation];
 +            IDWTELEM *dst= buffer + (b->ibuf - s->spatial_idwt_buffer);
 +
 +            dequantize(s, b, dst, b->stride);
 +        }
 +    }
 +}
 +
 +static void dwt_quantize(SnowContext *s, Plane *p, DWTELEM *buffer, int width, int height, int stride, int type){
 +    int level, orientation, ys, xs, x, y, pass;
 +    IDWTELEM best_dequant[height * stride];
 +    IDWTELEM idwt2_buffer[height * stride];
 +    const int score_stride= (width + 10)/Q2_STEP;
 +    int best_score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size
 +    int score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size
 +    int threshold= (s->m.lambda * s->m.lambda) >> 6;
 +
 +    //FIXME pass the copy cleanly ?
 +
 +//    memcpy(dwt_buffer, buffer, height * stride * sizeof(DWTELEM));
 +    ff_spatial_dwt(buffer, s->temp_dwt_buffer, width, height, stride, type, s->spatial_decomposition_count);
 +
 +    for(level=0; level<s->spatial_decomposition_count; level++){
 +        for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +            SubBand *b= &p->band[level][orientation];
 +            IDWTELEM *dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer);
 +             DWTELEM *src=       buffer + (b-> buf - s->spatial_dwt_buffer);
 +            assert(src == b->buf); // code does not depend on this but it is true currently
 +
 +            quantize(s, b, dst, src, b->stride, s->qbias);
 +        }
 +    }
 +    for(pass=0; pass<1; pass++){
 +        if(s->qbias == 0) //keyframe
 +            continue;
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                SubBand *b= &p->band[level][orientation];
 +                IDWTELEM *dst= idwt2_buffer + (b->ibuf - s->spatial_idwt_buffer);
 +                IDWTELEM *best_dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer);
 +
 +                for(ys= 0; ys<Q2_STEP; ys++){
 +                    for(xs= 0; xs<Q2_STEP; xs++){
 +                        memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM));
 +                        dequantize_all(s, p, idwt2_buffer, width, height);
 +                        ff_spatial_idwt(idwt2_buffer, s->temp_idwt_buffer, width, height, stride, type, s->spatial_decomposition_count);
 +                        find_sse(s, p, best_score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation);
 +                        memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM));
 +                        for(y=ys; y<b->height; y+= Q2_STEP){
 +                            for(x=xs; x<b->width; x+= Q2_STEP){
 +                                if(dst[x + y*b->stride]<0) dst[x + y*b->stride]++;
 +                                if(dst[x + y*b->stride]>0) dst[x + y*b->stride]--;
 +                                //FIXME try more than just --
 +                            }
 +                        }
 +                        dequantize_all(s, p, idwt2_buffer, width, height);
 +                        ff_spatial_idwt(idwt2_buffer, s->temp_idwt_buffer, width, height, stride, type, s->spatial_decomposition_count);
 +                        find_sse(s, p, score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation);
 +                        for(y=ys; y<b->height; y+= Q2_STEP){
 +                            for(x=xs; x<b->width; x+= Q2_STEP){
 +                                int score_idx= x/Q2_STEP + (y/Q2_STEP)*score_stride;
 +                                if(score[score_idx] <= best_score[score_idx] + threshold){
 +                                    best_score[score_idx]= score[score_idx];
 +                                    if(best_dst[x + y*b->stride]<0) best_dst[x + y*b->stride]++;
 +                                    if(best_dst[x + y*b->stride]>0) best_dst[x + y*b->stride]--;
 +                                    //FIXME copy instead
 +                                }
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +    }
 +    memcpy(s->spatial_idwt_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); //FIXME work with that directly instead of copy at the end
 +}
 +
 +#endif /* QUANTIZE2==1 */
 +
 +static av_cold int encode_init(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +    int plane_index, ret;
 +
 +    if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){
 +        av_log(avctx, AV_LOG_ERROR, "This codec is under development, files encoded with it may not be decodable with future versions!!!\n"
 +               "Use vstrict=-2 / -strict -2 to use it anyway.\n");
 +        return -1;
 +    }
 +
 +    if(avctx->prediction_method == DWT_97
 +       && (avctx->flags & CODEC_FLAG_QSCALE)
 +       && avctx->global_quality == 0){
 +        av_log(avctx, AV_LOG_ERROR, "The 9/7 wavelet is incompatible with lossless mode.\n");
 +        return -1;
 +    }
 +
 +    s->spatial_decomposition_type= avctx->prediction_method; //FIXME add decorrelator type r transform_type
 +
 +    s->mv_scale       = (avctx->flags & CODEC_FLAG_QPEL) ? 2 : 4;
 +    s->block_max_depth= (avctx->flags & CODEC_FLAG_4MV ) ? 1 : 0;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        s->plane[plane_index].diag_mc= 1;
 +        s->plane[plane_index].htaps= 6;
 +        s->plane[plane_index].hcoeff[0]=  40;
 +        s->plane[plane_index].hcoeff[1]= -10;
 +        s->plane[plane_index].hcoeff[2]=   2;
 +        s->plane[plane_index].fast_mc= 1;
 +    }
 +
 +    if ((ret = ff_snow_common_init(avctx)) < 0) {
 +        ff_snow_common_end(avctx->priv_data);
 +        return ret;
 +    }
 +    ff_snow_alloc_blocks(s);
 +
 +    s->version=0;
 +
 +    s->m.avctx   = avctx;
 +    s->m.flags   = avctx->flags;
 +    s->m.bit_rate= avctx->bit_rate;
 +
 +    s->m.me.temp      =
 +    s->m.me.scratchpad= av_mallocz((avctx->width+64)*2*16*2*sizeof(uint8_t));
 +    s->m.me.map       = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
 +    s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
 +    s->m.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t));
 +    ff_h263_encode_init(&s->m); //mv_penalty
 +
 +    s->max_ref_frames = FFMAX(FFMIN(avctx->refs, MAX_REF_FRAMES), 1);
 +
 +    if(avctx->flags&CODEC_FLAG_PASS1){
 +        if(!avctx->stats_out)
 +            avctx->stats_out = av_mallocz(256);
 +    }
 +    if((avctx->flags&CODEC_FLAG_PASS2) || !(avctx->flags&CODEC_FLAG_QSCALE)){
 +        if(ff_rate_control_init(&s->m) < 0)
 +            return -1;
 +    }
 +    s->pass1_rc= !(avctx->flags & (CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2));
 +
 +    avctx->coded_frame= &s->current_picture;
 +    switch(avctx->pix_fmt){
 +    case AV_PIX_FMT_YUV444P:
 +//    case AV_PIX_FMT_YUV422P:
 +    case AV_PIX_FMT_YUV420P:
 +//     case AV_PIX_FMT_GRAY8:
 +//    case AV_PIX_FMT_YUV411P:
 +    case AV_PIX_FMT_YUV410P:
 +        s->colorspace_type= 0;
 +        break;
 +/*    case AV_PIX_FMT_RGB32:
 +        s->colorspace= 1;
 +        break;*/
 +    default:
 +        av_log(avctx, AV_LOG_ERROR, "pixel format not supported\n");
 +        return -1;
 +    }
 +    avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift);
 +
 +    ff_set_cmp(&s->dsp, s->dsp.me_cmp, s->avctx->me_cmp);
 +    ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, s->avctx->me_sub_cmp);
 +
-     if (s->input_picture.data[0])
-         avctx->release_buffer(avctx, &s->input_picture);
++    if ((ret = ff_get_buffer(s->avctx, &s->input_picture, AV_GET_BUFFER_FLAG_REF)) < 0)
 +        return ret;
 +
 +    if(s->avctx->me_method == ME_ITER){
 +        int i;
 +        int size= s->b_width * s->b_height << 2*s->block_max_depth;
 +        for(i=0; i<s->max_ref_frames; i++){
 +            s->ref_mvs[i]= av_mallocz(size*sizeof(int16_t[2]));
 +            s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t));
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +//near copy & paste from dsputil, FIXME
 +static int pix_sum(uint8_t * pix, int line_size, int w, int h)
 +{
 +    int s, i, j;
 +
 +    s = 0;
 +    for (i = 0; i < h; i++) {
 +        for (j = 0; j < w; j++) {
 +            s += pix[0];
 +            pix ++;
 +        }
 +        pix += line_size - w;
 +    }
 +    return s;
 +}
 +
 +//near copy & paste from dsputil, FIXME
 +static int pix_norm1(uint8_t * pix, int line_size, int w)
 +{
 +    int s, i, j;
 +    uint32_t *sq = ff_squareTbl + 256;
 +
 +    s = 0;
 +    for (i = 0; i < w; i++) {
 +        for (j = 0; j < w; j ++) {
 +            s += sq[pix[0]];
 +            pix ++;
 +        }
 +        pix += line_size - w;
 +    }
 +    return s;
 +}
 +
 +static inline int get_penalty_factor(int lambda, int lambda2, int type){
 +    switch(type&0xFF){
 +    default:
 +    case FF_CMP_SAD:
 +        return lambda>>FF_LAMBDA_SHIFT;
 +    case FF_CMP_DCT:
 +        return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
 +    case FF_CMP_W53:
 +        return (4*lambda)>>(FF_LAMBDA_SHIFT);
 +    case FF_CMP_W97:
 +        return (2*lambda)>>(FF_LAMBDA_SHIFT);
 +    case FF_CMP_SATD:
 +    case FF_CMP_DCT264:
 +        return (2*lambda)>>FF_LAMBDA_SHIFT;
 +    case FF_CMP_RD:
 +    case FF_CMP_PSNR:
 +    case FF_CMP_SSE:
 +    case FF_CMP_NSSE:
 +        return lambda2>>FF_LAMBDA_SHIFT;
 +    case FF_CMP_BIT:
 +        return 1;
 +    }
 +}
 +
 +//FIXME copy&paste
 +#define P_LEFT P[1]
 +#define P_TOP P[2]
 +#define P_TOPRIGHT P[3]
 +#define P_MEDIAN P[4]
 +#define P_MV1 P[9]
 +#define FLAG_QPEL   1 //must be 1
 +
 +static int encode_q_branch(SnowContext *s, int level, int x, int y){
 +    uint8_t p_buffer[1024];
 +    uint8_t i_buffer[1024];
 +    uint8_t p_state[sizeof(s->block_state)];
 +    uint8_t i_state[sizeof(s->block_state)];
 +    RangeCoder pc, ic;
 +    uint8_t *pbbak= s->c.bytestream;
 +    uint8_t *pbbak_start= s->c.bytestream_start;
 +    int score, score2, iscore, i_len, p_len, block_s, sum, base_bits;
 +    const int w= s->b_width  << s->block_max_depth;
 +    const int h= s->b_height << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    const int block_w= 1<<(LOG2_MB_SIZE - level);
 +    int trx= (x+1)<<rem_depth;
 +    int try= (y+1)<<rem_depth;
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
 +    const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
 +    const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
 +    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
 +    int pl = left->color[0];
 +    int pcb= left->color[1];
 +    int pcr= left->color[2];
 +    int pmx, pmy;
 +    int mx=0, my=0;
 +    int l,cr,cb;
 +    const int stride= s->current_picture.linesize[0];
 +    const int uvstride= s->current_picture.linesize[1];
 +    uint8_t *current_data[3]= { s->input_picture.data[0] + (x + y*  stride)*block_w,
 +                                s->input_picture.data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift),
 +                                s->input_picture.data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)};
 +    int P[10][2];
 +    int16_t last_mv[3][2];
 +    int qpel= !!(s->avctx->flags & CODEC_FLAG_QPEL); //unused
 +    const int shift= 1+qpel;
 +    MotionEstContext *c= &s->m.me;
 +    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
 +    int mx_context= av_log2(2*FFABS(left->mx - top->mx));
 +    int my_context= av_log2(2*FFABS(left->my - top->my));
 +    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
 +    int ref, best_ref, ref_score, ref_mx, ref_my;
 +
 +    assert(sizeof(s->block_state) >= 256);
 +    if(s->keyframe){
 +        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
 +        return 0;
 +    }
 +
 +//    clip predictors / edge ?
 +
 +    P_LEFT[0]= left->mx;
 +    P_LEFT[1]= left->my;
 +    P_TOP [0]= top->mx;
 +    P_TOP [1]= top->my;
 +    P_TOPRIGHT[0]= tr->mx;
 +    P_TOPRIGHT[1]= tr->my;
 +
 +    last_mv[0][0]= s->block[index].mx;
 +    last_mv[0][1]= s->block[index].my;
 +    last_mv[1][0]= right->mx;
 +    last_mv[1][1]= right->my;
 +    last_mv[2][0]= bottom->mx;
 +    last_mv[2][1]= bottom->my;
 +
 +    s->m.mb_stride=2;
 +    s->m.mb_x=
 +    s->m.mb_y= 0;
 +    c->skip= 0;
 +
 +    assert(c->  stride ==   stride);
 +    assert(c->uvstride == uvstride);
 +
 +    c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
 +    c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
 +    c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
 +    c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_MV;
 +
 +    c->xmin = - x*block_w - 16+3;
 +    c->ymin = - y*block_w - 16+3;
 +    c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
 +    c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
 +
 +    if(P_LEFT[0]     > (c->xmax<<shift)) P_LEFT[0]    = (c->xmax<<shift);
 +    if(P_LEFT[1]     > (c->ymax<<shift)) P_LEFT[1]    = (c->ymax<<shift);
 +    if(P_TOP[0]      > (c->xmax<<shift)) P_TOP[0]     = (c->xmax<<shift);
 +    if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);
 +    if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
 +    if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
 +    if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
 +
 +    P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
 +    P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
 +
 +    if (!y) {
 +        c->pred_x= P_LEFT[0];
 +        c->pred_y= P_LEFT[1];
 +    } else {
 +        c->pred_x = P_MEDIAN[0];
 +        c->pred_y = P_MEDIAN[1];
 +    }
 +
 +    score= INT_MAX;
 +    best_ref= 0;
 +    for(ref=0; ref<s->ref_frames; ref++){
 +        init_ref(c, current_data, s->last_picture[ref].data, NULL, block_w*x, block_w*y, 0);
 +
 +        ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv,
 +                                         (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w);
 +
 +        assert(ref_mx >= c->xmin);
 +        assert(ref_mx <= c->xmax);
 +        assert(ref_my >= c->ymin);
 +        assert(ref_my <= c->ymax);
 +
 +        ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
 +        ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
 +        ref_score+= 2*av_log2(2*ref)*c->penalty_factor;
 +        if(s->ref_mvs[ref]){
 +            s->ref_mvs[ref][index][0]= ref_mx;
 +            s->ref_mvs[ref][index][1]= ref_my;
 +            s->ref_scores[ref][index]= ref_score;
 +        }
 +        if(score > ref_score){
 +            score= ref_score;
 +            best_ref= ref;
 +            mx= ref_mx;
 +            my= ref_my;
 +        }
 +    }
 +    //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2
 +
 +  //  subpel search
 +    base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start);
 +    pc= s->c;
 +    pc.bytestream_start=
 +    pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo
 +    memcpy(p_state, s->block_state, sizeof(s->block_state));
 +
 +    if(level!=s->block_max_depth)
 +        put_rac(&pc, &p_state[4 + s_context], 1);
 +    put_rac(&pc, &p_state[1 + left->type + top->type], 0);
 +    if(s->ref_frames > 1)
 +        put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);
 +    pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);
 +    put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1);
 +    put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1);
 +    p_len= pc.bytestream - pc.bytestream_start;
 +    score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT;
 +
 +    block_s= block_w*block_w;
 +    sum = pix_sum(current_data[0], stride, block_w, block_w);
 +    l= (sum + block_s/2)/block_s;
 +    iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
 +
 +    block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift);
 +    sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
 +    cb= (sum + block_s/2)/block_s;
 +//    iscore += pix_norm1(&current_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
 +    sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
 +    cr= (sum + block_s/2)/block_s;
 +//    iscore += pix_norm1(&current_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;
 +
 +    ic= s->c;
 +    ic.bytestream_start=
 +    ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo
 +    memcpy(i_state, s->block_state, sizeof(s->block_state));
 +    if(level!=s->block_max_depth)
 +        put_rac(&ic, &i_state[4 + s_context], 1);
 +    put_rac(&ic, &i_state[1 + left->type + top->type], 1);
 +    put_symbol(&ic, &i_state[32],  l-pl , 1);
 +    put_symbol(&ic, &i_state[64], cb-pcb, 1);
 +    put_symbol(&ic, &i_state[96], cr-pcr, 1);
 +    i_len= ic.bytestream - ic.bytestream_start;
 +    iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT;
 +
 +//    assert(score==256*256*256*64-1);
 +    assert(iscore < 255*255*256 + s->lambda2*10);
 +    assert(iscore >= 0);
 +    assert(l>=0 && l<=255);
 +    assert(pl>=0 && pl<=255);
 +
 +    if(level==0){
 +        int varc= iscore >> 8;
 +        int vard= score >> 8;
 +        if (vard <= 64 || vard < varc)
 +            c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
 +        else
 +            c->scene_change_score+= s->m.qscale;
 +    }
 +
 +    if(level!=s->block_max_depth){
 +        put_rac(&s->c, &s->block_state[4 + s_context], 0);
 +        score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);
 +        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);
 +        score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);
 +        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);
 +        score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead
 +
 +        if(score2 < score && score2 < iscore)
 +            return score2;
 +    }
 +
 +    if(iscore < score){
 +        pred_mv(s, &pmx, &pmy, 0, left, top, tr);
 +        memcpy(pbbak, i_buffer, i_len);
 +        s->c= ic;
 +        s->c.bytestream_start= pbbak_start;
 +        s->c.bytestream= pbbak + i_len;
 +        set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);
 +        memcpy(s->block_state, i_state, sizeof(s->block_state));
 +        return iscore;
 +    }else{
 +        memcpy(pbbak, p_buffer, p_len);
 +        s->c= pc;
 +        s->c.bytestream_start= pbbak_start;
 +        s->c.bytestream= pbbak + p_len;
 +        set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);
 +        memcpy(s->block_state, p_state, sizeof(s->block_state));
 +        return score;
 +    }
 +}
 +
 +static void encode_q_branch2(SnowContext *s, int level, int x, int y){
 +    const int w= s->b_width  << s->block_max_depth;
 +    const int rem_depth= s->block_max_depth - level;
 +    const int index= (x + y*w) << rem_depth;
 +    int trx= (x+1)<<rem_depth;
 +    BlockNode *b= &s->block[index];
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
 +    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
 +    int pl = left->color[0];
 +    int pcb= left->color[1];
 +    int pcr= left->color[2];
 +    int pmx, pmy;
 +    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
 +    int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref;
 +    int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref;
 +    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
 +
 +    if(s->keyframe){
 +        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
 +        return;
 +    }
 +
 +    if(level!=s->block_max_depth){
 +        if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){
 +            put_rac(&s->c, &s->block_state[4 + s_context], 1);
 +        }else{
 +            put_rac(&s->c, &s->block_state[4 + s_context], 0);
 +            encode_q_branch2(s, level+1, 2*x+0, 2*y+0);
 +            encode_q_branch2(s, level+1, 2*x+1, 2*y+0);
 +            encode_q_branch2(s, level+1, 2*x+0, 2*y+1);
 +            encode_q_branch2(s, level+1, 2*x+1, 2*y+1);
 +            return;
 +        }
 +    }
 +    if(b->type & BLOCK_INTRA){
 +        pred_mv(s, &pmx, &pmy, 0, left, top, tr);
 +        put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1);
 +        put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1);
 +        put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1);
 +        put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1);
 +        set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
 +    }else{
 +        pred_mv(s, &pmx, &pmy, b->ref, left, top, tr);
 +        put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0);
 +        if(s->ref_frames > 1)
 +            put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0);
 +        put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1);
 +        put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1);
 +        set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
 +    }
 +}
 +
 +static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){
 +    int i, x2, y2;
 +    Plane *p= &s->plane[plane_index];
 +    const int block_size = MB_SIZE >> s->block_max_depth;
 +    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    const int ref_stride= s->current_picture.linesize[plane_index];
 +    uint8_t *src= s-> input_picture.data[plane_index];
 +    IDWTELEM *dst= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int w= p->width;
 +    const int h= p->height;
 +    int index= mb_x + mb_y*b_stride;
 +    BlockNode *b= &s->block[index];
 +    BlockNode backup= *b;
 +    int ab=0;
 +    int aa=0;
 +
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above
 +
 +    b->type|= BLOCK_INTRA;
 +    b->color[plane_index]= 0;
 +    memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM));
 +
 +    for(i=0; i<4; i++){
 +        int mb_x2= mb_x + (i &1) - 1;
 +        int mb_y2= mb_y + (i>>1) - 1;
 +        int x= block_w*mb_x2 + block_w/2;
 +        int y= block_h*mb_y2 + block_h/2;
 +
 +        add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc,
 +                    x, y, block_w, block_h, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index);
 +
 +        for(y2= FFMAX(y, 0); y2<FFMIN(h, y+block_h); y2++){
 +            for(x2= FFMAX(x, 0); x2<FFMIN(w, x+block_w); x2++){
 +                int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_h*mb_y - block_h/2))*obmc_stride;
 +                int obmc_v= obmc[index];
 +                int d;
 +                if(y<0) obmc_v += obmc[index + block_h*obmc_stride];
 +                if(x<0) obmc_v += obmc[index + block_w];
 +                if(y+block_h>h) obmc_v += obmc[index - block_h*obmc_stride];
 +                if(x+block_w>w) obmc_v += obmc[index - block_w];
 +                //FIXME precalculate this or simplify it somehow else
 +
 +                d = -dst[index] + (1<<(FRAC_BITS-1));
 +                dst[index] = d;
 +                ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v;
 +                aa += obmc_v * obmc_v; //FIXME precalculate this
 +            }
 +        }
 +    }
 +    *b= backup;
 +
 +    return av_clip( ROUNDED_DIV(ab<<LOG2_OBMC_MAX, aa), 0, 255); //FIXME we should not need clipping
 +}
 +
 +static inline int get_block_bits(SnowContext *s, int x, int y, int w){
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int b_height = s->b_height<< s->block_max_depth;
 +    int index= x + y*b_stride;
 +    const BlockNode *b     = &s->block[index];
 +    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
 +    const BlockNode *top   = y ? &s->block[index-b_stride] : &null_block;
 +    const BlockNode *tl    = y && x ? &s->block[index-b_stride-1] : left;
 +    const BlockNode *tr    = y && x+w<b_stride ? &s->block[index-b_stride+w] : tl;
 +    int dmx, dmy;
 +//  int mx_context= av_log2(2*FFABS(left->mx - top->mx));
 +//  int my_context= av_log2(2*FFABS(left->my - top->my));
 +
 +    if(x<0 || x>=b_stride || y>=b_height)
 +        return 0;
 +/*
 +1            0      0
 +01X          1-2    1
 +001XX        3-6    2-3
 +0001XXX      7-14   4-7
 +00001XXXX   15-30   8-15
 +*/
 +//FIXME try accurate rate
 +//FIXME intra and inter predictors if surrounding blocks are not the same type
 +    if(b->type & BLOCK_INTRA){
 +        return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0]))
 +                   + av_log2(2*FFABS(left->color[1] - b->color[1]))
 +                   + av_log2(2*FFABS(left->color[2] - b->color[2])));
 +    }else{
 +        pred_mv(s, &dmx, &dmy, b->ref, left, top, tr);
 +        dmx-= b->mx;
 +        dmy-= b->my;
 +        return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda
 +                    + av_log2(2*FFABS(dmy))
 +                    + av_log2(2*b->ref));
 +    }
 +}
 +
 +static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){
 +    Plane *p= &s->plane[plane_index];
 +    const int block_size = MB_SIZE >> s->block_max_depth;
 +    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    const int ref_stride= s->current_picture.linesize[plane_index];
 +    uint8_t *dst= s->current_picture.data[plane_index];
 +    uint8_t *src= s->  input_picture.data[plane_index];
 +    IDWTELEM *pred= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4;
 +    uint8_t *cur = s->scratchbuf;
 +    uint8_t *tmp = s->emu_edge_buffer;
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int b_height = s->b_height<< s->block_max_depth;
 +    const int w= p->width;
 +    const int h= p->height;
 +    int distortion;
 +    int rate= 0;
 +    const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
 +    int sx= block_w*mb_x - block_w/2;
 +    int sy= block_h*mb_y - block_h/2;
 +    int x0= FFMAX(0,-sx);
 +    int y0= FFMAX(0,-sy);
 +    int x1= FFMIN(block_w*2, w-sx);
 +    int y1= FFMIN(block_h*2, h-sy);
 +    int i,x,y;
 +
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w
 +
 +    ff_snow_pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_h*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h);
 +
 +    for(y=y0; y<y1; y++){
 +        const uint8_t *obmc1= obmc_edged[y];
 +        const IDWTELEM *pred1 = pred + y*obmc_stride;
 +        uint8_t *cur1 = cur + y*ref_stride;
 +        uint8_t *dst1 = dst + sx + (sy+y)*ref_stride;
 +        for(x=x0; x<x1; x++){
 +#if FRAC_BITS >= LOG2_OBMC_MAX
 +            int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX);
 +#else
 +            int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS);
 +#endif
 +            v = (v + pred1[x]) >> FRAC_BITS;
 +            if(v&(~255)) v= ~(v>>31);
 +            dst1[x] = v;
 +        }
 +    }
 +
 +    /* copy the regions where obmc[] = (uint8_t)256 */
 +    if(LOG2_OBMC_MAX == 8
 +        && (mb_x == 0 || mb_x == b_stride-1)
 +        && (mb_y == 0 || mb_y == b_height-1)){
 +        if(mb_x == 0)
 +            x1 = block_w;
 +        else
 +            x0 = block_w;
 +        if(mb_y == 0)
 +            y1 = block_h;
 +        else
 +            y0 = block_h;
 +        for(y=y0; y<y1; y++)
 +            memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, x1-x0);
 +    }
 +
 +    if(block_w==16){
 +        /* FIXME rearrange dsputil to fit 32x32 cmp functions */
 +        /* FIXME check alignment of the cmp wavelet vs the encoding wavelet */
 +        /* FIXME cmps overlap but do not cover the wavelet's whole support.
 +         * So improving the score of one block is not strictly guaranteed
 +         * to improve the score of the whole frame, thus iterative motion
 +         * estimation does not always converge. */
 +        if(s->avctx->me_cmp == FF_CMP_W97)
 +            distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
 +        else if(s->avctx->me_cmp == FF_CMP_W53)
 +            distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
 +        else{
 +            distortion = 0;
 +            for(i=0; i<4; i++){
 +                int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride;
 +                distortion += s->dsp.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16);
 +            }
 +        }
 +    }else{
 +        assert(block_w==8);
 +        distortion = s->dsp.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2);
 +    }
 +
 +    if(plane_index==0){
 +        for(i=0; i<4; i++){
 +/* ..RRr
 + * .RXx.
 + * rxx..
 + */
 +            rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1);
 +        }
 +        if(mb_x == b_stride-2)
 +            rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1);
 +    }
 +    return distortion + rate*penalty_factor;
 +}
 +
 +static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){
 +    int i, y2;
 +    Plane *p= &s->plane[plane_index];
 +    const int block_size = MB_SIZE >> s->block_max_depth;
 +    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
 +    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
 +    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
 +    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
 +    const int ref_stride= s->current_picture.linesize[plane_index];
 +    uint8_t *dst= s->current_picture.data[plane_index];
 +    uint8_t *src= s-> input_picture.data[plane_index];
 +    //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst
 +    // const has only been removed from zero_dst to suppress a warning
 +    static IDWTELEM zero_dst[4096]; //FIXME
 +    const int b_stride = s->b_width << s->block_max_depth;
 +    const int w= p->width;
 +    const int h= p->height;
 +    int distortion= 0;
 +    int rate= 0;
 +    const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
 +
 +    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below
 +
 +    for(i=0; i<9; i++){
 +        int mb_x2= mb_x + (i%3) - 1;
 +        int mb_y2= mb_y + (i/3) - 1;
 +        int x= block_w*mb_x2 + block_w/2;
 +        int y= block_h*mb_y2 + block_h/2;
 +
 +        add_yblock(s, 0, NULL, zero_dst, dst, obmc,
 +                   x, y, block_w, block_h, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index);
 +
 +        //FIXME find a cleaner/simpler way to skip the outside stuff
 +        for(y2= y; y2<0; y2++)
 +            memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
 +        for(y2= h; y2<y+block_h; y2++)
 +            memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
 +        if(x<0){
 +            for(y2= y; y2<y+block_h; y2++)
 +                memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
 +        }
 +        if(x+block_w > w){
 +            for(y2= y; y2<y+block_h; y2++)
 +                memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
 +        }
 +
 +        assert(block_w== 8 || block_w==16);
 +        distortion += s->dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h);
 +    }
 +
 +    if(plane_index==0){
 +        BlockNode *b= &s->block[mb_x+mb_y*b_stride];
 +        int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1);
 +
 +/* ..RRRr
 + * .RXXx.
 + * .RXXx.
 + * rxxx.
 + */
 +        if(merged)
 +            rate = get_block_bits(s, mb_x, mb_y, 2);
 +        for(i=merged?4:0; i<9; i++){
 +            static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}};
 +            rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1);
 +        }
 +    }
 +    return distortion + rate*penalty_factor;
 +}
 +
 +static int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x, y;
 +
 +    if(1){
 +        int run=0;
 +        int *runs = s->run_buffer;
 +        int run_index=0;
 +        int max_index;
 +
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int v, p=0;
 +                int /*ll=0, */l=0, lt=0, t=0, rt=0;
 +                v= src[x + y*stride];
 +
 +                if(y){
 +                    t= src[x + (y-1)*stride];
 +                    if(x){
 +                        lt= src[x - 1 + (y-1)*stride];
 +                    }
 +                    if(x + 1 < w){
 +                        rt= src[x + 1 + (y-1)*stride];
 +                    }
 +                }
 +                if(x){
 +                    l= src[x - 1 + y*stride];
 +                    /*if(x > 1){
 +                        if(orientation==1) ll= src[y + (x-2)*stride];
 +                        else               ll= src[x - 2 + y*stride];
 +                    }*/
 +                }
 +                if(parent){
 +                    int px= x>>1;
 +                    int py= y>>1;
 +                    if(px<b->parent->width && py<b->parent->height)
 +                        p= parent[px + py*2*stride];
 +                }
 +                if(!(/*ll|*/l|lt|t|rt|p)){
 +                    if(v){
 +                        runs[run_index++]= run;
 +                        run=0;
 +                    }else{
 +                        run++;
 +                    }
 +                }
 +            }
 +        }
 +        max_index= run_index;
 +        runs[run_index++]= run;
 +        run_index=0;
 +        run= runs[run_index++];
 +
 +        put_symbol2(&s->c, b->state[30], max_index, 0);
 +        if(run_index <= max_index)
 +            put_symbol2(&s->c, b->state[1], run, 3);
 +
 +        for(y=0; y<h; y++){
 +            if(s->c.bytestream_end - s->c.bytestream < w*40){
 +                av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
 +                return -1;
 +            }
 +            for(x=0; x<w; x++){
 +                int v, p=0;
 +                int /*ll=0, */l=0, lt=0, t=0, rt=0;
 +                v= src[x + y*stride];
 +
 +                if(y){
 +                    t= src[x + (y-1)*stride];
 +                    if(x){
 +                        lt= src[x - 1 + (y-1)*stride];
 +                    }
 +                    if(x + 1 < w){
 +                        rt= src[x + 1 + (y-1)*stride];
 +                    }
 +                }
 +                if(x){
 +                    l= src[x - 1 + y*stride];
 +                    /*if(x > 1){
 +                        if(orientation==1) ll= src[y + (x-2)*stride];
 +                        else               ll= src[x - 2 + y*stride];
 +                    }*/
 +                }
 +                if(parent){
 +                    int px= x>>1;
 +                    int py= y>>1;
 +                    if(px<b->parent->width && py<b->parent->height)
 +                        p= parent[px + py*2*stride];
 +                }
 +                if(/*ll|*/l|lt|t|rt|p){
 +                    int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
 +
 +                    put_rac(&s->c, &b->state[0][context], !!v);
 +                }else{
 +                    if(!run){
 +                        run= runs[run_index++];
 +
 +                        if(run_index <= max_index)
 +                            put_symbol2(&s->c, b->state[1], run, 3);
 +                        assert(v);
 +                    }else{
 +                        run--;
 +                        assert(!v);
 +                    }
 +                }
 +                if(v){
 +                    int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
 +                    int l2= 2*FFABS(l) + (l<0);
 +                    int t2= 2*FFABS(t) + (t<0);
 +
 +                    put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4);
 +                    put_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l2&0xFF] + 3*ff_quant3bA[t2&0xFF]], v<0);
 +                }
 +            }
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
 +//    encode_subband_qtree(s, b, src, parent, stride, orientation);
 +//    encode_subband_z0run(s, b, src, parent, stride, orientation);
 +    return encode_subband_c0run(s, b, src, parent, stride, orientation);
 +//    encode_subband_dzr(s, b, src, parent, stride, orientation);
 +}
 +
 +static av_always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){
 +    const int b_stride= s->b_width << s->block_max_depth;
 +    BlockNode *block= &s->block[mb_x + mb_y * b_stride];
 +    BlockNode backup= *block;
 +    unsigned value;
 +    int rd, index;
 +
 +    assert(mb_x>=0 && mb_y>=0);
 +    assert(mb_x<b_stride);
 +
 +    if(intra){
 +        block->color[0] = p[0];
 +        block->color[1] = p[1];
 +        block->color[2] = p[2];
 +        block->type |= BLOCK_INTRA;
 +    }else{
 +        index= (p[0] + 31*p[1]) & (ME_CACHE_SIZE-1);
 +        value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6) + (block->ref<<12);
 +        if(s->me_cache[index] == value)
 +            return 0;
 +        s->me_cache[index]= value;
 +
 +        block->mx= p[0];
 +        block->my= p[1];
 +        block->type &= ~BLOCK_INTRA;
 +    }
 +
 +    rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged);
 +
 +//FIXME chroma
 +    if(rd < *best_rd){
 +        *best_rd= rd;
 +        return 1;
 +    }else{
 +        *block= backup;
 +        return 0;
 +    }
 +}
 +
 +/* special case for int[2] args we discard afterwards,
 + * fixes compilation problem with gcc 2.95 */
 +static av_always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){
 +    int p[2] = {p0, p1};
 +    return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
 +}
 +
 +static av_always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){
 +    const int b_stride= s->b_width << s->block_max_depth;
 +    BlockNode *block= &s->block[mb_x + mb_y * b_stride];
 +    BlockNode backup[4];
 +    unsigned value;
 +    int rd, index;
 +
 +    /* We don't initialize backup[] during variable declaration, because
 +     * that fails to compile on MSVC: "cannot convert from 'BlockNode' to
 +     * 'int16_t'". */
 +    backup[0] = block[0];
 +    backup[1] = block[1];
 +    backup[2] = block[b_stride];
 +    backup[3] = block[b_stride + 1];
 +
 +    assert(mb_x>=0 && mb_y>=0);
 +    assert(mb_x<b_stride);
 +    assert(((mb_x|mb_y)&1) == 0);
 +
 +    index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
 +    value= s->me_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12);
 +    if(s->me_cache[index] == value)
 +        return 0;
 +    s->me_cache[index]= value;
 +
 +    block->mx= p0;
 +    block->my= p1;
 +    block->ref= ref;
 +    block->type &= ~BLOCK_INTRA;
 +    block[1]= block[b_stride]= block[b_stride+1]= *block;
 +
 +    rd= get_4block_rd(s, mb_x, mb_y, 0);
 +
 +//FIXME chroma
 +    if(rd < *best_rd){
 +        *best_rd= rd;
 +        return 1;
 +    }else{
 +        block[0]= backup[0];
 +        block[1]= backup[1];
 +        block[b_stride]= backup[2];
 +        block[b_stride+1]= backup[3];
 +        return 0;
 +    }
 +}
 +
 +static void iterative_me(SnowContext *s){
 +    int pass, mb_x, mb_y;
 +    const int b_width = s->b_width  << s->block_max_depth;
 +    const int b_height= s->b_height << s->block_max_depth;
 +    const int b_stride= b_width;
 +    int color[3];
 +
 +    {
 +        RangeCoder r = s->c;
 +        uint8_t state[sizeof(s->block_state)];
 +        memcpy(state, s->block_state, sizeof(s->block_state));
 +        for(mb_y= 0; mb_y<s->b_height; mb_y++)
 +            for(mb_x= 0; mb_x<s->b_width; mb_x++)
 +                encode_q_branch(s, 0, mb_x, mb_y);
 +        s->c = r;
 +        memcpy(s->block_state, state, sizeof(s->block_state));
 +    }
 +
 +    for(pass=0; pass<25; pass++){
 +        int change= 0;
 +
 +        for(mb_y= 0; mb_y<b_height; mb_y++){
 +            for(mb_x= 0; mb_x<b_width; mb_x++){
 +                int dia_change, i, j, ref;
 +                int best_rd= INT_MAX, ref_rd;
 +                BlockNode backup, ref_b;
 +                const int index= mb_x + mb_y * b_stride;
 +                BlockNode *block= &s->block[index];
 +                BlockNode *tb =                   mb_y            ? &s->block[index-b_stride  ] : NULL;
 +                BlockNode *lb = mb_x                              ? &s->block[index         -1] : NULL;
 +                BlockNode *rb = mb_x+1<b_width                    ? &s->block[index         +1] : NULL;
 +                BlockNode *bb =                   mb_y+1<b_height ? &s->block[index+b_stride  ] : NULL;
 +                BlockNode *tlb= mb_x           && mb_y            ? &s->block[index-b_stride-1] : NULL;
 +                BlockNode *trb= mb_x+1<b_width && mb_y            ? &s->block[index-b_stride+1] : NULL;
 +                BlockNode *blb= mb_x           && mb_y+1<b_height ? &s->block[index+b_stride-1] : NULL;
 +                BlockNode *brb= mb_x+1<b_width && mb_y+1<b_height ? &s->block[index+b_stride+1] : NULL;
 +                const int b_w= (MB_SIZE >> s->block_max_depth);
 +                uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2];
 +
 +                if(pass && (block->type & BLOCK_OPT))
 +                    continue;
 +                block->type |= BLOCK_OPT;
 +
 +                backup= *block;
 +
 +                if(!s->me_cache_generation)
 +                    memset(s->me_cache, 0, sizeof(s->me_cache));
 +                s->me_cache_generation += 1<<22;
 +
 +                //FIXME precalculate
 +                {
 +                    int x, y;
 +                    for (y = 0; y < b_w * 2; y++)
 +                        memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2);
 +                    if(mb_x==0)
 +                        for(y=0; y<b_w*2; y++)
 +                            memset(obmc_edged[y], obmc_edged[y][0] + obmc_edged[y][b_w-1], b_w);
 +                    if(mb_x==b_stride-1)
 +                        for(y=0; y<b_w*2; y++)
 +                            memset(obmc_edged[y]+b_w, obmc_edged[y][b_w] + obmc_edged[y][b_w*2-1], b_w);
 +                    if(mb_y==0){
 +                        for(x=0; x<b_w*2; x++)
 +                            obmc_edged[0][x] += obmc_edged[b_w-1][x];
 +                        for(y=1; y<b_w; y++)
 +                            memcpy(obmc_edged[y], obmc_edged[0], b_w*2);
 +                    }
 +                    if(mb_y==b_height-1){
 +                        for(x=0; x<b_w*2; x++)
 +                            obmc_edged[b_w*2-1][x] += obmc_edged[b_w][x];
 +                        for(y=b_w; y<b_w*2-1; y++)
 +                            memcpy(obmc_edged[y], obmc_edged[b_w*2-1], b_w*2);
 +                    }
 +                }
 +
 +                //skip stuff outside the picture
 +                if(mb_x==0 || mb_y==0 || mb_x==b_width-1 || mb_y==b_height-1){
 +                    uint8_t *src= s->  input_picture.data[0];
 +                    uint8_t *dst= s->current_picture.data[0];
 +                    const int stride= s->current_picture.linesize[0];
 +                    const int block_w= MB_SIZE >> s->block_max_depth;
 +                    const int block_h= MB_SIZE >> s->block_max_depth;
 +                    const int sx= block_w*mb_x - block_w/2;
 +                    const int sy= block_h*mb_y - block_h/2;
 +                    const int w= s->plane[0].width;
 +                    const int h= s->plane[0].height;
 +                    int y;
 +
 +                    for(y=sy; y<0; y++)
 +                        memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
 +                    for(y=h; y<sy+block_h*2; y++)
 +                        memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
 +                    if(sx<0){
 +                        for(y=sy; y<sy+block_h*2; y++)
 +                            memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
 +                    }
 +                    if(sx+block_w*2 > w){
 +                        for(y=sy; y<sy+block_h*2; y++)
 +                            memcpy(dst + w + y*stride, src + w + y*stride, sx+block_w*2 - w);
 +                    }
 +                }
 +
 +                // intra(black) = neighbors' contribution to the current block
 +                for(i=0; i<3; i++)
 +                    color[i]= get_dc(s, mb_x, mb_y, i);
 +
 +                // get previous score (cannot be cached due to OBMC)
 +                if(pass > 0 && (block->type&BLOCK_INTRA)){
 +                    int color0[3]= {block->color[0], block->color[1], block->color[2]};
 +                    check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd);
 +                }else
 +                    check_block_inter(s, mb_x, mb_y, block->mx, block->my, obmc_edged, &best_rd);
 +
 +                ref_b= *block;
 +                ref_rd= best_rd;
 +                for(ref=0; ref < s->ref_frames; ref++){
 +                    int16_t (*mvr)[2]= &s->ref_mvs[ref][index];
 +                    if(s->ref_scores[ref][index] > s->ref_scores[ref_b.ref][index]*3/2) //FIXME tune threshold
 +                        continue;
 +                    block->ref= ref;
 +                    best_rd= INT_MAX;
 +
 +                    check_block_inter(s, mb_x, mb_y, mvr[0][0], mvr[0][1], obmc_edged, &best_rd);
 +                    check_block_inter(s, mb_x, mb_y, 0, 0, obmc_edged, &best_rd);
 +                    if(tb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd);
 +                    if(lb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd);
 +                    if(rb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd);
 +                    if(bb)
 +                        check_block_inter(s, mb_x, mb_y, mvr[b_stride][0], mvr[b_stride][1], obmc_edged, &best_rd);
 +
 +                    /* fullpel ME */
 +                    //FIXME avoid subpel interpolation / round to nearest integer
 +                    do{
 +                        dia_change=0;
 +                        for(i=0; i<FFMAX(s->avctx->dia_size, 1); i++){
 +                            for(j=0; j<i; j++){
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+4*(i-j), block->my+(4*j), obmc_edged, &best_rd);
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my-(4*j), obmc_edged, &best_rd);
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+4*(i-j), block->my-(4*j), obmc_edged, &best_rd);
 +                                dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my+(4*j), obmc_edged, &best_rd);
 +                            }
 +                        }
 +                    }while(dia_change);
 +                    /* subpel ME */
 +                    do{
 +                        static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};
 +                        dia_change=0;
 +                        for(i=0; i<8; i++)
 +                            dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+square[i][0], block->my+square[i][1], obmc_edged, &best_rd);
 +                    }while(dia_change);
 +                    //FIXME or try the standard 2 pass qpel or similar
 +
 +                    mvr[0][0]= block->mx;
 +                    mvr[0][1]= block->my;
 +                    if(ref_rd > best_rd){
 +                        ref_rd= best_rd;
 +                        ref_b= *block;
 +                    }
 +                }
 +                best_rd= ref_rd;
 +                *block= ref_b;
 +                check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd);
 +                //FIXME RD style color selection
 +                if(!same_block(block, &backup)){
 +                    if(tb ) tb ->type &= ~BLOCK_OPT;
 +                    if(lb ) lb ->type &= ~BLOCK_OPT;
 +                    if(rb ) rb ->type &= ~BLOCK_OPT;
 +                    if(bb ) bb ->type &= ~BLOCK_OPT;
 +                    if(tlb) tlb->type &= ~BLOCK_OPT;
 +                    if(trb) trb->type &= ~BLOCK_OPT;
 +                    if(blb) blb->type &= ~BLOCK_OPT;
 +                    if(brb) brb->type &= ~BLOCK_OPT;
 +                    change ++;
 +                }
 +            }
 +        }
 +        av_log(s->avctx, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change);
 +        if(!change)
 +            break;
 +    }
 +
 +    if(s->block_max_depth == 1){
 +        int change= 0;
 +        for(mb_y= 0; mb_y<b_height; mb_y+=2){
 +            for(mb_x= 0; mb_x<b_width; mb_x+=2){
 +                int i;
 +                int best_rd, init_rd;
 +                const int index= mb_x + mb_y * b_stride;
 +                BlockNode *b[4];
 +
 +                b[0]= &s->block[index];
 +                b[1]= b[0]+1;
 +                b[2]= b[0]+b_stride;
 +                b[3]= b[2]+1;
 +                if(same_block(b[0], b[1]) &&
 +                   same_block(b[0], b[2]) &&
 +                   same_block(b[0], b[3]))
 +                    continue;
 +
 +                if(!s->me_cache_generation)
 +                    memset(s->me_cache, 0, sizeof(s->me_cache));
 +                s->me_cache_generation += 1<<22;
 +
 +                init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0);
 +
 +                //FIXME more multiref search?
 +                check_4block_inter(s, mb_x, mb_y,
 +                                   (b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2,
 +                                   (b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, 0, &best_rd);
 +
 +                for(i=0; i<4; i++)
 +                    if(!(b[i]->type&BLOCK_INTRA))
 +                        check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, b[i]->ref, &best_rd);
 +
 +                if(init_rd != best_rd)
 +                    change++;
 +            }
 +        }
 +        av_log(s->avctx, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4);
 +    }
 +}
 +
 +static void encode_blocks(SnowContext *s, int search){
 +    int x, y;
 +    int w= s->b_width;
 +    int h= s->b_height;
 +
 +    if(s->avctx->me_method == ME_ITER && !s->keyframe && search)
 +        iterative_me(s);
 +
 +    for(y=0; y<h; y++){
 +        if(s->c.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit
 +            av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
 +            return;
 +        }
 +        for(x=0; x<w; x++){
 +            if(s->avctx->me_method == ME_ITER || !search)
 +                encode_q_branch2(s, 0, x, y);
 +            else
 +                encode_q_branch (s, 0, x, y);
 +        }
 +    }
 +}
 +
 +static void quantize(SnowContext *s, SubBand *b, IDWTELEM *dst, DWTELEM *src, int stride, int bias){
 +    const int w= b->width;
 +    const int h= b->height;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    const int qmul= ff_qexp[qlog&(QROOT-1)]<<((qlog>>QSHIFT) + ENCODER_EXTRA_BITS);
 +    int x,y, thres1, thres2;
 +
 +    if(s->qlog == LOSSLESS_QLOG){
 +        for(y=0; y<h; y++)
 +            for(x=0; x<w; x++)
 +                dst[x + y*stride]= src[x + y*stride];
 +        return;
 +    }
 +
 +    bias= bias ? 0 : (3*qmul)>>3;
 +    thres1= ((qmul - bias)>>QEXPSHIFT) - 1;
 +    thres2= 2*thres1;
 +
 +    if(!bias){
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= src[x + y*stride];
 +
 +                if((unsigned)(i+thres1) > thres2){
 +                    if(i>=0){
 +                        i<<= QEXPSHIFT;
 +                        i/= qmul; //FIXME optimize
 +                        dst[x + y*stride]=  i;
 +                    }else{
 +                        i= -i;
 +                        i<<= QEXPSHIFT;
 +                        i/= qmul; //FIXME optimize
 +                        dst[x + y*stride]= -i;
 +                    }
 +                }else
 +                    dst[x + y*stride]= 0;
 +            }
 +        }
 +    }else{
 +        for(y=0; y<h; y++){
 +            for(x=0; x<w; x++){
 +                int i= src[x + y*stride];
 +
 +                if((unsigned)(i+thres1) > thres2){
 +                    if(i>=0){
 +                        i<<= QEXPSHIFT;
 +                        i= (i + bias) / qmul; //FIXME optimize
 +                        dst[x + y*stride]=  i;
 +                    }else{
 +                        i= -i;
 +                        i<<= QEXPSHIFT;
 +                        i= (i + bias) / qmul; //FIXME optimize
 +                        dst[x + y*stride]= -i;
 +                    }
 +                }else
 +                    dst[x + y*stride]= 0;
 +            }
 +        }
 +    }
 +}
 +
 +static void dequantize(SnowContext *s, SubBand *b, IDWTELEM *src, int stride){
 +    const int w= b->width;
 +    const int h= b->height;
 +    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
 +    const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +    const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
 +    int x,y;
 +
 +    if(s->qlog == LOSSLESS_QLOG) return;
 +
 +    for(y=0; y<h; y++){
 +        for(x=0; x<w; x++){
 +            int i= src[x + y*stride];
 +            if(i<0){
 +                src[x + y*stride]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
 +            }else if(i>0){
 +                src[x + y*stride]=  (( i*qmul + qadd)>>(QEXPSHIFT));
 +            }
 +        }
 +    }
 +}
 +
 +static void decorrelate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x,y;
 +
 +    for(y=h-1; y>=0; y--){
 +        for(x=w-1; x>=0; x--){
 +            int i= x + y*stride;
 +
 +            if(x){
 +                if(use_median){
 +                    if(y && x+1<w) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
 +                    else  src[i] -= src[i - 1];
 +                }else{
 +                    if(y) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
 +                    else  src[i] -= src[i - 1];
 +                }
 +            }else{
 +                if(y) src[i] -= src[i - stride];
 +            }
 +        }
 +    }
 +}
 +
 +static void correlate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){
 +    const int w= b->width;
 +    const int h= b->height;
 +    int x,y;
 +
 +    for(y=0; y<h; y++){
 +        for(x=0; x<w; x++){
 +            int i= x + y*stride;
 +
 +            if(x){
 +                if(use_median){
 +                    if(y && x+1<w) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
 +                    else  src[i] += src[i - 1];
 +                }else{
 +                    if(y) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
 +                    else  src[i] += src[i - 1];
 +                }
 +            }else{
 +                if(y) src[i] += src[i - stride];
 +            }
 +        }
 +    }
 +}
 +
 +static void encode_qlogs(SnowContext *s){
 +    int plane_index, level, orientation;
 +
 +    for(plane_index=0; plane_index<2; plane_index++){
 +        for(level=0; level<s->spatial_decomposition_count; level++){
 +            for(orientation=level ? 1:0; orientation<4; orientation++){
 +                if(orientation==2) continue;
 +                put_symbol(&s->c, s->header_state, s->plane[plane_index].band[level][orientation].qlog, 1);
 +            }
 +        }
 +    }
 +}
 +
 +static void encode_header(SnowContext *s){
 +    int plane_index, i;
 +    uint8_t kstate[32];
 +
 +    memset(kstate, MID_STATE, sizeof(kstate));
 +
 +    put_rac(&s->c, kstate, s->keyframe);
 +    if(s->keyframe || s->always_reset){
 +        ff_snow_reset_contexts(s);
 +        s->last_spatial_decomposition_type=
 +        s->last_qlog=
 +        s->last_qbias=
 +        s->last_mv_scale=
 +        s->last_block_max_depth= 0;
 +        for(plane_index=0; plane_index<2; plane_index++){
 +            Plane *p= &s->plane[plane_index];
 +            p->last_htaps=0;
 +            p->last_diag_mc=0;
 +            memset(p->last_hcoeff, 0, sizeof(p->last_hcoeff));
 +        }
 +    }
 +    if(s->keyframe){
 +        put_symbol(&s->c, s->header_state, s->version, 0);
 +        put_rac(&s->c, s->header_state, s->always_reset);
 +        put_symbol(&s->c, s->header_state, s->temporal_decomposition_type, 0);
 +        put_symbol(&s->c, s->header_state, s->temporal_decomposition_count, 0);
 +        put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0);
 +        put_symbol(&s->c, s->header_state, s->colorspace_type, 0);
 +        put_symbol(&s->c, s->header_state, s->chroma_h_shift, 0);
 +        put_symbol(&s->c, s->header_state, s->chroma_v_shift, 0);
 +        put_rac(&s->c, s->header_state, s->spatial_scalability);
 +//        put_rac(&s->c, s->header_state, s->rate_scalability);
 +        put_symbol(&s->c, s->header_state, s->max_ref_frames-1, 0);
 +
 +        encode_qlogs(s);
 +    }
 +
 +    if(!s->keyframe){
 +        int update_mc=0;
 +        for(plane_index=0; plane_index<2; plane_index++){
 +            Plane *p= &s->plane[plane_index];
 +            update_mc |= p->last_htaps   != p->htaps;
 +            update_mc |= p->last_diag_mc != p->diag_mc;
 +            update_mc |= !!memcmp(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
 +        }
 +        put_rac(&s->c, s->header_state, update_mc);
 +        if(update_mc){
 +            for(plane_index=0; plane_index<2; plane_index++){
 +                Plane *p= &s->plane[plane_index];
 +                put_rac(&s->c, s->header_state, p->diag_mc);
 +                put_symbol(&s->c, s->header_state, p->htaps/2-1, 0);
 +                for(i= p->htaps/2; i; i--)
 +                    put_symbol(&s->c, s->header_state, FFABS(p->hcoeff[i]), 0);
 +            }
 +        }
 +        if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
 +            put_rac(&s->c, s->header_state, 1);
 +            put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0);
 +            encode_qlogs(s);
 +        }else
 +            put_rac(&s->c, s->header_state, 0);
 +    }
 +
 +    put_symbol(&s->c, s->header_state, s->spatial_decomposition_type - s->last_spatial_decomposition_type, 1);
 +    put_symbol(&s->c, s->header_state, s->qlog            - s->last_qlog    , 1);
 +    put_symbol(&s->c, s->header_state, s->mv_scale        - s->last_mv_scale, 1);
 +    put_symbol(&s->c, s->header_state, s->qbias           - s->last_qbias   , 1);
 +    put_symbol(&s->c, s->header_state, s->block_max_depth - s->last_block_max_depth, 1);
 +
 +}
 +
 +static void update_last_header_values(SnowContext *s){
 +    int plane_index;
 +
 +    if(!s->keyframe){
 +        for(plane_index=0; plane_index<2; plane_index++){
 +            Plane *p= &s->plane[plane_index];
 +            p->last_diag_mc= p->diag_mc;
 +            p->last_htaps  = p->htaps;
 +            memcpy(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
 +        }
 +    }
 +
 +    s->last_spatial_decomposition_type  = s->spatial_decomposition_type;
 +    s->last_qlog                        = s->qlog;
 +    s->last_qbias                       = s->qbias;
 +    s->last_mv_scale                    = s->mv_scale;
 +    s->last_block_max_depth             = s->block_max_depth;
 +    s->last_spatial_decomposition_count = s->spatial_decomposition_count;
 +}
 +
 +static int qscale2qlog(int qscale){
 +    return rint(QROOT*log2(qscale / (float)FF_QP2LAMBDA))
 +           + 61*QROOT/8; ///< 64 > 60
 +}
 +
 +static int ratecontrol_1pass(SnowContext *s, AVFrame *pict)
 +{
 +    /* Estimate the frame's complexity as a sum of weighted dwt coefficients.
 +     * FIXME we know exact mv bits at this point,
 +     * but ratecontrol isn't set up to include them. */
 +    uint32_t coef_sum= 0;
 +    int level, orientation, delta_qlog;
 +
 +    for(level=0; level<s->spatial_decomposition_count; level++){
 +        for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +            SubBand *b= &s->plane[0].band[level][orientation];
 +            IDWTELEM *buf= b->ibuf;
 +            const int w= b->width;
 +            const int h= b->height;
 +            const int stride= b->stride;
 +            const int qlog= av_clip(2*QROOT + b->qlog, 0, QROOT*16);
 +            const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
 +            const int qdiv= (1<<16)/qmul;
 +            int x, y;
 +            //FIXME this is ugly
 +            for(y=0; y<h; y++)
 +                for(x=0; x<w; x++)
 +                    buf[x+y*stride]= b->buf[x+y*stride];
 +            if(orientation==0)
 +                decorrelate(s, b, buf, stride, 1, 0);
 +            for(y=0; y<h; y++)
 +                for(x=0; x<w; x++)
 +                    coef_sum+= abs(buf[x+y*stride]) * qdiv >> 16;
 +        }
 +    }
 +
 +    /* ugly, ratecontrol just takes a sqrt again */
 +    coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
 +    assert(coef_sum < INT_MAX);
 +
 +    if(pict->pict_type == AV_PICTURE_TYPE_I){
 +        s->m.current_picture.mb_var_sum= coef_sum;
 +        s->m.current_picture.mc_mb_var_sum= 0;
 +    }else{
 +        s->m.current_picture.mc_mb_var_sum= coef_sum;
 +        s->m.current_picture.mb_var_sum= 0;
 +    }
 +
 +    pict->quality= ff_rate_estimate_qscale(&s->m, 1);
 +    if (pict->quality < 0)
 +        return INT_MIN;
 +    s->lambda= pict->quality * 3/2;
 +    delta_qlog= qscale2qlog(pict->quality) - s->qlog;
 +    s->qlog+= delta_qlog;
 +    return delta_qlog;
 +}
 +
 +static void calculate_visual_weight(SnowContext *s, Plane *p){
 +    int width = p->width;
 +    int height= p->height;
 +    int level, orientation, x, y;
 +
 +    for(level=0; level<s->spatial_decomposition_count; level++){
 +        for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +            SubBand *b= &p->band[level][orientation];
 +            IDWTELEM *ibuf= b->ibuf;
 +            int64_t error=0;
 +
 +            memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height);
 +            ibuf[b->width/2 + b->height/2*b->stride]= 256*16;
 +            ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
 +            for(y=0; y<height; y++){
 +                for(x=0; x<width; x++){
 +                    int64_t d= s->spatial_idwt_buffer[x + y*width]*16;
 +                    error += d*d;
 +                }
 +            }
 +
 +            b->qlog= (int)(log(352256.0/sqrt(error)) / log(pow(2.0, 1.0/QROOT))+0.5);
 +        }
 +    }
 +}
 +
 +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 +                        const AVFrame *pict, int *got_packet)
 +{
 +    SnowContext *s = avctx->priv_data;
 +    RangeCoder * const c= &s->c;
 +    AVFrame *pic = &s->new_picture;
 +    const int width= s->avctx->width;
 +    const int height= s->avctx->height;
 +    int level, orientation, plane_index, i, y, ret;
 +    uint8_t rc_header_bak[sizeof(s->header_state)];
 +    uint8_t rc_block_bak[sizeof(s->block_state)];
 +
 +    if ((ret = ff_alloc_packet2(avctx, pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + FF_MIN_BUFFER_SIZE)) < 0)
 +        return ret;
 +
 +    ff_init_range_encoder(c, pkt->data, pkt->size);
 +    ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
 +
 +    for(i=0; i<3; i++){
 +        int hshift= i ? s->chroma_h_shift : 0;
 +        int vshift= i ? s->chroma_v_shift : 0;
 +        for(y=0; y<(height>>vshift); y++)
 +            memcpy(&s->input_picture.data[i][y * s->input_picture.linesize[i]],
 +                   &pict->data[i][y * pict->linesize[i]],
 +                   width>>hshift);
 +        s->dsp.draw_edges(s->input_picture.data[i], s->input_picture.linesize[i],
 +                            width >> hshift, height >> vshift,
 +                            EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
 +                            EDGE_TOP | EDGE_BOTTOM);
 +
 +    }
 +    emms_c();
 +    s->new_picture = *pict;
 +
 +    s->m.picture_number= avctx->frame_number;
 +    if(avctx->flags&CODEC_FLAG_PASS2){
 +        s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_number].new_pict_type;
 +        s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I;
 +        if(!(avctx->flags&CODEC_FLAG_QSCALE)) {
 +            pic->quality = ff_rate_estimate_qscale(&s->m, 0);
 +            if (pic->quality < 0)
 +                return -1;
 +        }
 +    }else{
 +        s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
 +        s->m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
 +    }
 +
 +    if(s->pass1_rc && avctx->frame_number == 0)
 +        pic->quality = 2*FF_QP2LAMBDA;
 +    if (pic->quality) {
 +        s->qlog   = qscale2qlog(pic->quality);
 +        s->lambda = pic->quality * 3/2;
 +    }
 +    if (s->qlog < 0 || (!pic->quality && (avctx->flags & CODEC_FLAG_QSCALE))) {
 +        s->qlog= LOSSLESS_QLOG;
 +        s->lambda = 0;
 +    }//else keep previous frame's qlog until after motion estimation
 +
 +    ff_snow_frame_start(s);
 +
 +    s->m.current_picture_ptr= &s->m.current_picture;
 +    s->m.last_picture.f.pts = s->m.current_picture.f.pts;
 +    s->m.current_picture.f.pts = pict->pts;
 +    if(pic->pict_type == AV_PICTURE_TYPE_P){
 +        int block_width = (width +15)>>4;
 +        int block_height= (height+15)>>4;
 +        int stride= s->current_picture.linesize[0];
 +
 +        assert(s->current_picture.data[0]);
 +        assert(s->last_picture[0].data[0]);
 +
 +        s->m.avctx= s->avctx;
 +        s->m.current_picture.f.data[0] = s->current_picture.data[0];
 +        s->m.   last_picture.f.data[0] = s->last_picture[0].data[0];
 +        s->m.    new_picture.f.data[0] = s->  input_picture.data[0];
 +        s->m.   last_picture_ptr= &s->m.   last_picture;
 +        s->m.linesize=
 +        s->m.   last_picture.f.linesize[0] =
 +        s->m.    new_picture.f.linesize[0] =
 +        s->m.current_picture.f.linesize[0] = stride;
 +        s->m.uvlinesize= s->current_picture.linesize[1];
 +        s->m.width = width;
 +        s->m.height= height;
 +        s->m.mb_width = block_width;
 +        s->m.mb_height= block_height;
 +        s->m.mb_stride=   s->m.mb_width+1;
 +        s->m.b8_stride= 2*s->m.mb_width+1;
 +        s->m.f_code=1;
 +        s->m.pict_type = pic->pict_type;
 +        s->m.me_method= s->avctx->me_method;
 +        s->m.me.scene_change_score=0;
 +        s->m.flags= s->avctx->flags;
 +        s->m.quarter_sample= (s->avctx->flags & CODEC_FLAG_QPEL)!=0;
 +        s->m.out_format= FMT_H263;
 +        s->m.unrestricted_mv= 1;
 +
 +        s->m.lambda = s->lambda;
 +        s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
 +        s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
 +
 +        s->m.dsp= s->dsp; //move
 +        ff_init_me(&s->m);
 +        s->dsp= s->m.dsp;
 +    }
 +
 +    if(s->pass1_rc){
 +        memcpy(rc_header_bak, s->header_state, sizeof(s->header_state));
 +        memcpy(rc_block_bak, s->block_state, sizeof(s->block_state));
 +    }
 +
 +redo_frame:
 +
 +    if (pic->pict_type == AV_PICTURE_TYPE_I)
 +        s->spatial_decomposition_count= 5;
 +    else
 +        s->spatial_decomposition_count= 5;
 +
 +    while(   !(width >>(s->chroma_h_shift + s->spatial_decomposition_count))
 +          || !(height>>(s->chroma_v_shift + s->spatial_decomposition_count)))
 +        s->spatial_decomposition_count--;
 +
 +    s->m.pict_type = pic->pict_type;
 +    s->qbias = pic->pict_type == AV_PICTURE_TYPE_P ? 2 : 0;
 +
 +    ff_snow_common_init_after_header(avctx);
 +
 +    if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
 +        for(plane_index=0; plane_index<3; plane_index++){
 +            calculate_visual_weight(s, &s->plane[plane_index]);
 +        }
 +    }
 +
 +    encode_header(s);
 +    s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start);
 +    encode_blocks(s, 1);
 +    s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits;
 +
 +    for(plane_index=0; plane_index<3; plane_index++){
 +        Plane *p= &s->plane[plane_index];
 +        int w= p->width;
 +        int h= p->height;
 +        int x, y;
 +//        int bits= put_bits_count(&s->c.pb);
 +
 +        if (!s->memc_only) {
 +            //FIXME optimize
 +            if(pict->data[plane_index]) //FIXME gray hack
 +                for(y=0; y<h; y++){
 +                    for(x=0; x<w; x++){
 +                        s->spatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
 +                    }
 +                }
 +            predict_plane(s, s->spatial_idwt_buffer, plane_index, 0);
 +
 +            if(   plane_index==0
 +               && pic->pict_type == AV_PICTURE_TYPE_P
 +               && !(avctx->flags&CODEC_FLAG_PASS2)
 +               && s->m.me.scene_change_score > s->avctx->scenechange_threshold){
 +                ff_init_range_encoder(c, pkt->data, pkt->size);
 +                ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
 +                pic->pict_type= AV_PICTURE_TYPE_I;
 +                s->keyframe=1;
 +                s->current_picture.key_frame=1;
 +                goto redo_frame;
 +            }
 +
 +            if(s->qlog == LOSSLESS_QLOG){
 +                for(y=0; y<h; y++){
 +                    for(x=0; x<w; x++){
 +                        s->spatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
 +                    }
 +                }
 +            }else{
 +                for(y=0; y<h; y++){
 +                    for(x=0; x<w; x++){
 +                        s->spatial_dwt_buffer[y*w + x]=s->spatial_idwt_buffer[y*w + x]<<ENCODER_EXTRA_BITS;
 +                    }
 +                }
 +            }
 +
 +            /*  if(QUANTIZE2)
 +                dwt_quantize(s, p, s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type);
 +            else*/
 +                ff_spatial_dwt(s->spatial_dwt_buffer, s->temp_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
 +
 +            if(s->pass1_rc && plane_index==0){
 +                int delta_qlog = ratecontrol_1pass(s, pic);
 +                if (delta_qlog <= INT_MIN)
 +                    return -1;
 +                if(delta_qlog){
 +                    //reordering qlog in the bitstream would eliminate this reset
 +                    ff_init_range_encoder(c, pkt->data, pkt->size);
 +                    memcpy(s->header_state, rc_header_bak, sizeof(s->header_state));
 +                    memcpy(s->block_state, rc_block_bak, sizeof(s->block_state));
 +                    encode_header(s);
 +                    encode_blocks(s, 0);
 +                }
 +            }
 +
 +            for(level=0; level<s->spatial_decomposition_count; level++){
 +                for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                    SubBand *b= &p->band[level][orientation];
 +
 +                    if(!QUANTIZE2)
 +                        quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias);
 +                    if(orientation==0)
 +                        decorrelate(s, b, b->ibuf, b->stride, pic->pict_type == AV_PICTURE_TYPE_P, 0);
 +                    if (!s->no_bitstream)
 +                    encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation);
 +                    assert(b->parent==NULL || b->parent->stride == b->stride*2);
 +                    if(orientation==0)
 +                        correlate(s, b, b->ibuf, b->stride, 1, 0);
 +                }
 +            }
 +
 +            for(level=0; level<s->spatial_decomposition_count; level++){
 +                for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                    SubBand *b= &p->band[level][orientation];
 +
 +                    dequantize(s, b, b->ibuf, b->stride);
 +                }
 +            }
 +
 +            ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
 +            if(s->qlog == LOSSLESS_QLOG){
 +                for(y=0; y<h; y++){
 +                    for(x=0; x<w; x++){
 +                        s->spatial_idwt_buffer[y*w + x]<<=FRAC_BITS;
 +                    }
 +                }
 +            }
 +            predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
 +        }else{
 +            //ME/MC only
 +            if(pic->pict_type == AV_PICTURE_TYPE_I){
 +                for(y=0; y<h; y++){
 +                    for(x=0; x<w; x++){
 +                        s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x]=
 +                            pict->data[plane_index][y*pict->linesize[plane_index] + x];
 +                    }
 +                }
 +            }else{
 +                memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h);
 +                predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
 +            }
 +        }
 +        if(s->avctx->flags&CODEC_FLAG_PSNR){
 +            int64_t error= 0;
 +
 +            if(pict->data[plane_index]) //FIXME gray hack
 +                for(y=0; y<h; y++){
 +                    for(x=0; x<w; x++){
 +                        int d= s->current_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x];
 +                        error += d*d;
 +                    }
 +                }
 +            s->avctx->error[plane_index] += error;
 +            s->current_picture.error[plane_index] = error;
 +        }
 +
 +    }
 +
 +    update_last_header_values(s);
 +
 +    ff_snow_release_buffer(avctx);
 +
 +    s->current_picture.coded_picture_number = avctx->frame_number;
 +    s->current_picture.pict_type = pict->pict_type;
 +    s->current_picture.quality = pict->quality;
 +    s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
 +    s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits;
 +    s->m.current_picture.f.display_picture_number =
 +    s->m.current_picture.f.coded_picture_number   = avctx->frame_number;
 +    s->m.current_picture.f.quality                = pic->quality;
 +    s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
 +    if(s->pass1_rc)
 +        if (ff_rate_estimate_qscale(&s->m, 0) < 0)
 +            return -1;
 +    if(avctx->flags&CODEC_FLAG_PASS1)
 +        ff_write_pass1_stats(&s->m);
 +    s->m.last_pict_type = s->m.pict_type;
 +    avctx->frame_bits = s->m.frame_bits;
 +    avctx->mv_bits = s->m.mv_bits;
 +    avctx->misc_bits = s->m.misc_bits;
 +    avctx->p_tex_bits = s->m.p_tex_bits;
 +
 +    emms_c();
 +
 +    pkt->size = ff_rac_terminate(c);
 +    if (avctx->coded_frame->key_frame)
 +        pkt->flags |= AV_PKT_FLAG_KEY;
 +    *got_packet = 1;
 +
 +    return 0;
 +}
 +
 +static av_cold int encode_end(AVCodecContext *avctx)
 +{
 +    SnowContext *s = avctx->priv_data;
 +
 +    ff_snow_common_end(s);
++    av_frame_unref(&s->input_picture);
 +    av_free(avctx->stats_out);
 +
 +    return 0;
 +}
 +
 +#define OFFSET(x) offsetof(SnowContext, x)
 +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +static const AVOption options[] = {
 +    { "memc_only",      "Only do ME/MC (I frames -> ref, P frame -> ME+MC).",   OFFSET(memc_only), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
 +    { "no_bitstream",   "Skip final bitstream writeout.",                    OFFSET(no_bitstream), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
 +    { NULL },
 +};
 +
 +static const AVClass snowenc_class = {
 +    .class_name = "snow encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_snow_encoder = {
 +    .name           = "snow",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_SNOW,
 +    .priv_data_size = sizeof(SnowContext),
 +    .init           = encode_init,
 +    .encode2        = encode_frame,
 +    .close          = encode_end,
 +    .pix_fmts       = (const enum AVPixelFormat[]){
 +        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV444P,
 +        AV_PIX_FMT_NONE
 +    },
 +    .long_name      = NULL_IF_CONFIG_SMALL("Snow"),
 +    .priv_class     = &snowenc_class,
 +};
 +
 +
 +#ifdef TEST
 +#undef malloc
 +#undef free
 +#undef printf
 +
 +#include "libavutil/lfg.h"
 +#include "libavutil/mathematics.h"
 +
 +int main(void){
 +#define width  256
 +#define height 256
 +    int buffer[2][width*height];
 +    SnowContext s;
 +    int i;
 +    AVLFG prng;
 +    s.spatial_decomposition_count=6;
 +    s.spatial_decomposition_type=1;
 +
 +    s.temp_dwt_buffer  = av_mallocz(width * sizeof(DWTELEM));
 +    s.temp_idwt_buffer = av_mallocz(width * sizeof(IDWTELEM));
 +
 +    av_lfg_init(&prng, 1);
 +
 +    printf("testing 5/3 DWT\n");
 +    for(i=0; i<width*height; i++)
 +        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
 +
 +    ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
 +    ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
 +
 +    for(i=0; i<width*height; i++)
 +        if(buffer[0][i]!= buffer[1][i]) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
 +
 +    printf("testing 9/7 DWT\n");
 +    s.spatial_decomposition_type=0;
 +    for(i=0; i<width*height; i++)
 +        buffer[0][i] = buffer[1][i] = av_lfg_get(&prng) % 54321 - 12345;
 +
 +    ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
 +    ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
 +
 +    for(i=0; i<width*height; i++)
 +        if(FFABS(buffer[0][i] - buffer[1][i])>20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]);
 +
 +    {
 +    int level, orientation, x, y;
 +    int64_t errors[8][4];
 +    int64_t g=0;
 +
 +        memset(errors, 0, sizeof(errors));
 +        s.spatial_decomposition_count=3;
 +        s.spatial_decomposition_type=0;
 +        for(level=0; level<s.spatial_decomposition_count; level++){
 +            for(orientation=level ? 1 : 0; orientation<4; orientation++){
 +                int w= width  >> (s.spatial_decomposition_count-level);
 +                int h= height >> (s.spatial_decomposition_count-level);
 +                int stride= width  << (s.spatial_decomposition_count-level);
 +                DWTELEM *buf= buffer[0];
 +                int64_t error=0;
 +
 +                if(orientation&1) buf+=w;
 +                if(orientation>1) buf+=stride>>1;
 +
 +                memset(buffer[0], 0, sizeof(int)*width*height);
 +                buf[w/2 + h/2*stride]= 256*256;
 +                ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
 +                for(y=0; y<height; y++){
 +                    for(x=0; x<width; x++){
 +                        int64_t d= buffer[0][x + y*width];
 +                        error += d*d;
 +                        if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9 && level==2) printf("%8"PRId64" ", d);
 +                    }
 +                    if(FFABS(height/2-y)<9 && level==2) printf("\n");
 +                }
 +                error= (int)(sqrt(error)+0.5);
 +                errors[level][orientation]= error;
 +                if(g) g=av_gcd(g, error);
 +                else g= error;
 +            }
 +        }
 +        printf("static int const visual_weight[][4]={\n");
 +        for(level=0; level<s.spatial_decomposition_count; level++){
 +            printf("  {");
 +            for(orientation=0; orientation<4; orientation++){
 +                printf("%8"PRId64",", errors[level][orientation]/g);
 +            }
 +            printf("},\n");
 +        }
 +        printf("};\n");
 +        {
 +            int level=2;
 +            int w= width  >> (s.spatial_decomposition_count-level);
 +            //int h= height >> (s.spatial_decomposition_count-level);
 +            int stride= width  << (s.spatial_decomposition_count-level);
 +            DWTELEM *buf= buffer[0];
 +            int64_t error=0;
 +
 +            buf+=w;
 +            buf+=stride>>1;
 +
 +            memset(buffer[0], 0, sizeof(int)*width*height);
 +            for(y=0; y<height; y++){
 +                for(x=0; x<width; x++){
 +                    int tab[4]={0,2,3,1};
 +                    buffer[0][x+width*y]= 256*256*tab[(x&1) + 2*(y&1)];
 +                }
 +            }
 +            ff_spatial_dwt(buffer[0], s.temp_dwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count);
 +            for(y=0; y<height; y++){
 +                for(x=0; x<width; x++){
 +                    int64_t d= buffer[0][x + y*width];
 +                    error += d*d;
 +                    if(FFABS(width/2-x)<9 && FFABS(height/2-y)<9) printf("%8"PRId64" ", d);
 +                }
 +                if(FFABS(height/2-y)<9) printf("\n");
 +            }
 +        }
 +
 +    }
 +    return 0;
 +}
 +#endif /* TEST */
index ae54388,0000000..7f11ca7
mode 100644,000000..100644
--- /dev/null
@@@ -1,1001 -1,0 +1,1001 @@@
-     if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) {
 +/*
 + * Simple free lossless/lossy audio codec
 + * Copyright (c) 2004 Alex Beregszaszi
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +#include "avcodec.h"
 +#include "get_bits.h"
 +#include "golomb.h"
 +#include "internal.h"
 +
 +/**
 + * @file
 + * Simple free lossless/lossy audio codec
 + * Based on Paul Francis Harrison's Bonk (http://www.logarithmic.net/pfh/bonk)
 + * Written and designed by Alex Beregszaszi
 + *
 + * TODO:
 + *  - CABAC put/get_symbol
 + *  - independent quantizer for channels
 + *  - >2 channels support
 + *  - more decorrelation types
 + *  - more tap_quant tests
 + *  - selectable intlist writers/readers (bonk-style, golomb, cabac)
 + */
 +
 +#define MAX_CHANNELS 2
 +
 +#define MID_SIDE 0
 +#define LEFT_SIDE 1
 +#define RIGHT_SIDE 2
 +
 +typedef struct SonicContext {
 +    AVFrame frame;
 +    int lossless, decorrelation;
 +
 +    int num_taps, downsampling;
 +    double quantization;
 +
 +    int channels, samplerate, block_align, frame_size;
 +
 +    int *tap_quant;
 +    int *int_samples;
 +    int *coded_samples[MAX_CHANNELS];
 +
 +    // for encoding
 +    int *tail;
 +    int tail_size;
 +    int *window;
 +    int window_size;
 +
 +    // for decoding
 +    int *predictor_k;
 +    int *predictor_state[MAX_CHANNELS];
 +} SonicContext;
 +
 +#define LATTICE_SHIFT   10
 +#define SAMPLE_SHIFT    4
 +#define LATTICE_FACTOR  (1 << LATTICE_SHIFT)
 +#define SAMPLE_FACTOR   (1 << SAMPLE_SHIFT)
 +
 +#define BASE_QUANT      0.6
 +#define RATE_VARIATION  3.0
 +
 +static inline int divide(int a, int b)
 +{
 +    if (a < 0)
 +        return -( (-a + b/2)/b );
 +    else
 +        return (a + b/2)/b;
 +}
 +
 +static inline int shift(int a,int b)
 +{
 +    return (a+(1<<(b-1))) >> b;
 +}
 +
 +static inline int shift_down(int a,int b)
 +{
 +    return (a>>b)+((a<0)?1:0);
 +}
 +
 +#if 1
 +static inline int intlist_write(PutBitContext *pb, int *buf, int entries, int base_2_part)
 +{
 +    int i;
 +
 +    for (i = 0; i < entries; i++)
 +        set_se_golomb(pb, buf[i]);
 +
 +    return 1;
 +}
 +
 +static inline int intlist_read(GetBitContext *gb, int *buf, int entries, int base_2_part)
 +{
 +    int i;
 +
 +    for (i = 0; i < entries; i++)
 +        buf[i] = get_se_golomb(gb);
 +
 +    return 1;
 +}
 +
 +#else
 +
 +#define ADAPT_LEVEL 8
 +
 +static int bits_to_store(uint64_t x)
 +{
 +    int res = 0;
 +
 +    while(x)
 +    {
 +        res++;
 +        x >>= 1;
 +    }
 +    return res;
 +}
 +
 +static void write_uint_max(PutBitContext *pb, unsigned int value, unsigned int max)
 +{
 +    int i, bits;
 +
 +    if (!max)
 +        return;
 +
 +    bits = bits_to_store(max);
 +
 +    for (i = 0; i < bits-1; i++)
 +        put_bits(pb, 1, value & (1 << i));
 +
 +    if ( (value | (1 << (bits-1))) <= max)
 +        put_bits(pb, 1, value & (1 << (bits-1)));
 +}
 +
 +static unsigned int read_uint_max(GetBitContext *gb, int max)
 +{
 +    int i, bits, value = 0;
 +
 +    if (!max)
 +        return 0;
 +
 +    bits = bits_to_store(max);
 +
 +    for (i = 0; i < bits-1; i++)
 +        if (get_bits1(gb))
 +            value += 1 << i;
 +
 +    if ( (value | (1<<(bits-1))) <= max)
 +        if (get_bits1(gb))
 +            value += 1 << (bits-1);
 +
 +    return value;
 +}
 +
 +static int intlist_write(PutBitContext *pb, int *buf, int entries, int base_2_part)
 +{
 +    int i, j, x = 0, low_bits = 0, max = 0;
 +    int step = 256, pos = 0, dominant = 0, any = 0;
 +    int *copy, *bits;
 +
 +    copy = av_mallocz(4* entries);
 +    if (!copy)
 +        return -1;
 +
 +    if (base_2_part)
 +    {
 +        int energy = 0;
 +
 +        for (i = 0; i < entries; i++)
 +            energy += abs(buf[i]);
 +
 +        low_bits = bits_to_store(energy / (entries * 2));
 +        if (low_bits > 15)
 +            low_bits = 15;
 +
 +        put_bits(pb, 4, low_bits);
 +    }
 +
 +    for (i = 0; i < entries; i++)
 +    {
 +        put_bits(pb, low_bits, abs(buf[i]));
 +        copy[i] = abs(buf[i]) >> low_bits;
 +        if (copy[i] > max)
 +            max = abs(copy[i]);
 +    }
 +
 +    bits = av_mallocz(4* entries*max);
 +    if (!bits)
 +    {
 +//        av_free(copy);
 +        return -1;
 +    }
 +
 +    for (i = 0; i <= max; i++)
 +    {
 +        for (j = 0; j < entries; j++)
 +            if (copy[j] >= i)
 +                bits[x++] = copy[j] > i;
 +    }
 +
 +    // store bitstream
 +    while (pos < x)
 +    {
 +        int steplet = step >> 8;
 +
 +        if (pos + steplet > x)
 +            steplet = x - pos;
 +
 +        for (i = 0; i < steplet; i++)
 +            if (bits[i+pos] != dominant)
 +                any = 1;
 +
 +        put_bits(pb, 1, any);
 +
 +        if (!any)
 +        {
 +            pos += steplet;
 +            step += step / ADAPT_LEVEL;
 +        }
 +        else
 +        {
 +            int interloper = 0;
 +
 +            while (((pos + interloper) < x) && (bits[pos + interloper] == dominant))
 +                interloper++;
 +
 +            // note change
 +            write_uint_max(pb, interloper, (step >> 8) - 1);
 +
 +            pos += interloper + 1;
 +            step -= step / ADAPT_LEVEL;
 +        }
 +
 +        if (step < 256)
 +        {
 +            step = 65536 / step;
 +            dominant = !dominant;
 +        }
 +    }
 +
 +    // store signs
 +    for (i = 0; i < entries; i++)
 +        if (buf[i])
 +            put_bits(pb, 1, buf[i] < 0);
 +
 +//    av_free(bits);
 +//    av_free(copy);
 +
 +    return 0;
 +}
 +
 +static int intlist_read(GetBitContext *gb, int *buf, int entries, int base_2_part)
 +{
 +    int i, low_bits = 0, x = 0;
 +    int n_zeros = 0, step = 256, dominant = 0;
 +    int pos = 0, level = 0;
 +    int *bits = av_mallocz(4* entries);
 +
 +    if (!bits)
 +        return -1;
 +
 +    if (base_2_part)
 +    {
 +        low_bits = get_bits(gb, 4);
 +
 +        if (low_bits)
 +            for (i = 0; i < entries; i++)
 +                buf[i] = get_bits(gb, low_bits);
 +    }
 +
 +//    av_log(NULL, AV_LOG_INFO, "entries: %d, low bits: %d\n", entries, low_bits);
 +
 +    while (n_zeros < entries)
 +    {
 +        int steplet = step >> 8;
 +
 +        if (!get_bits1(gb))
 +        {
 +            for (i = 0; i < steplet; i++)
 +                bits[x++] = dominant;
 +
 +            if (!dominant)
 +                n_zeros += steplet;
 +
 +            step += step / ADAPT_LEVEL;
 +        }
 +        else
 +        {
 +            int actual_run = read_uint_max(gb, steplet-1);
 +
 +//            av_log(NULL, AV_LOG_INFO, "actual run: %d\n", actual_run);
 +
 +            for (i = 0; i < actual_run; i++)
 +                bits[x++] = dominant;
 +
 +            bits[x++] = !dominant;
 +
 +            if (!dominant)
 +                n_zeros += actual_run;
 +            else
 +                n_zeros++;
 +
 +            step -= step / ADAPT_LEVEL;
 +        }
 +
 +        if (step < 256)
 +        {
 +            step = 65536 / step;
 +            dominant = !dominant;
 +        }
 +    }
 +
 +    // reconstruct unsigned values
 +    n_zeros = 0;
 +    for (i = 0; n_zeros < entries; i++)
 +    {
 +        while(1)
 +        {
 +            if (pos >= entries)
 +            {
 +                pos = 0;
 +                level += 1 << low_bits;
 +            }
 +
 +            if (buf[pos] >= level)
 +                break;
 +
 +            pos++;
 +        }
 +
 +        if (bits[i])
 +            buf[pos] += 1 << low_bits;
 +        else
 +            n_zeros++;
 +
 +        pos++;
 +    }
 +//    av_free(bits);
 +
 +    // read signs
 +    for (i = 0; i < entries; i++)
 +        if (buf[i] && get_bits1(gb))
 +            buf[i] = -buf[i];
 +
 +//    av_log(NULL, AV_LOG_INFO, "zeros: %d pos: %d\n", n_zeros, pos);
 +
 +    return 0;
 +}
 +#endif
 +
 +static void predictor_init_state(int *k, int *state, int order)
 +{
 +    int i;
 +
 +    for (i = order-2; i >= 0; i--)
 +    {
 +        int j, p, x = state[i];
 +
 +        for (j = 0, p = i+1; p < order; j++,p++)
 +            {
 +            int tmp = x + shift_down(k[j] * state[p], LATTICE_SHIFT);
 +            state[p] += shift_down(k[j]*x, LATTICE_SHIFT);
 +            x = tmp;
 +        }
 +    }
 +}
 +
 +static int predictor_calc_error(int *k, int *state, int order, int error)
 +{
 +    int i, x = error - shift_down(k[order-1] * state[order-1], LATTICE_SHIFT);
 +
 +#if 1
 +    int *k_ptr = &(k[order-2]),
 +        *state_ptr = &(state[order-2]);
 +    for (i = order-2; i >= 0; i--, k_ptr--, state_ptr--)
 +    {
 +        int k_value = *k_ptr, state_value = *state_ptr;
 +        x -= shift_down(k_value * state_value, LATTICE_SHIFT);
 +        state_ptr[1] = state_value + shift_down(k_value * x, LATTICE_SHIFT);
 +    }
 +#else
 +    for (i = order-2; i >= 0; i--)
 +    {
 +        x -= shift_down(k[i] * state[i], LATTICE_SHIFT);
 +        state[i+1] = state[i] + shift_down(k[i] * x, LATTICE_SHIFT);
 +    }
 +#endif
 +
 +    // don't drift too far, to avoid overflows
 +    if (x >  (SAMPLE_FACTOR<<16)) x =  (SAMPLE_FACTOR<<16);
 +    if (x < -(SAMPLE_FACTOR<<16)) x = -(SAMPLE_FACTOR<<16);
 +
 +    state[0] = x;
 +
 +    return x;
 +}
 +
 +#if CONFIG_SONIC_ENCODER || CONFIG_SONIC_LS_ENCODER
 +// Heavily modified Levinson-Durbin algorithm which
 +// copes better with quantization, and calculates the
 +// actual whitened result as it goes.
 +
 +static void modified_levinson_durbin(int *window, int window_entries,
 +        int *out, int out_entries, int channels, int *tap_quant)
 +{
 +    int i;
 +    int *state = av_mallocz(4* window_entries);
 +
 +    memcpy(state, window, 4* window_entries);
 +
 +    for (i = 0; i < out_entries; i++)
 +    {
 +        int step = (i+1)*channels, k, j;
 +        double xx = 0.0, xy = 0.0;
 +#if 1
 +        int *x_ptr = &(window[step]), *state_ptr = &(state[0]);
 +        j = window_entries - step;
 +        for (;j>=0;j--,x_ptr++,state_ptr++)
 +        {
 +            double x_value = *x_ptr, state_value = *state_ptr;
 +            xx += state_value*state_value;
 +            xy += x_value*state_value;
 +        }
 +#else
 +        for (j = 0; j <= (window_entries - step); j++);
 +        {
 +            double stepval = window[step+j], stateval = window[j];
 +//            xx += (double)window[j]*(double)window[j];
 +//            xy += (double)window[step+j]*(double)window[j];
 +            xx += stateval*stateval;
 +            xy += stepval*stateval;
 +        }
 +#endif
 +        if (xx == 0.0)
 +            k = 0;
 +        else
 +            k = (int)(floor(-xy/xx * (double)LATTICE_FACTOR / (double)(tap_quant[i]) + 0.5));
 +
 +        if (k > (LATTICE_FACTOR/tap_quant[i]))
 +            k = LATTICE_FACTOR/tap_quant[i];
 +        if (-k > (LATTICE_FACTOR/tap_quant[i]))
 +            k = -(LATTICE_FACTOR/tap_quant[i]);
 +
 +        out[i] = k;
 +        k *= tap_quant[i];
 +
 +#if 1
 +        x_ptr = &(window[step]);
 +        state_ptr = &(state[0]);
 +        j = window_entries - step;
 +        for (;j>=0;j--,x_ptr++,state_ptr++)
 +        {
 +            int x_value = *x_ptr, state_value = *state_ptr;
 +            *x_ptr = x_value + shift_down(k*state_value,LATTICE_SHIFT);
 +            *state_ptr = state_value + shift_down(k*x_value, LATTICE_SHIFT);
 +        }
 +#else
 +        for (j=0; j <= (window_entries - step); j++)
 +        {
 +            int stepval = window[step+j], stateval=state[j];
 +            window[step+j] += shift_down(k * stateval, LATTICE_SHIFT);
 +            state[j] += shift_down(k * stepval, LATTICE_SHIFT);
 +        }
 +#endif
 +    }
 +
 +    av_free(state);
 +}
 +
 +static inline int code_samplerate(int samplerate)
 +{
 +    switch (samplerate)
 +    {
 +        case 44100: return 0;
 +        case 22050: return 1;
 +        case 11025: return 2;
 +        case 96000: return 3;
 +        case 48000: return 4;
 +        case 32000: return 5;
 +        case 24000: return 6;
 +        case 16000: return 7;
 +        case 8000: return 8;
 +    }
 +    return -1;
 +}
 +
 +static av_cold int sonic_encode_init(AVCodecContext *avctx)
 +{
 +    SonicContext *s = avctx->priv_data;
 +    PutBitContext pb;
 +    int i, version = 0;
 +
 +    if (avctx->channels > MAX_CHANNELS)
 +    {
 +        av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n");
 +        return -1; /* only stereo or mono for now */
 +    }
 +
 +    if (avctx->channels == 2)
 +        s->decorrelation = MID_SIDE;
 +
 +    if (avctx->codec->id == AV_CODEC_ID_SONIC_LS)
 +    {
 +        s->lossless = 1;
 +        s->num_taps = 32;
 +        s->downsampling = 1;
 +        s->quantization = 0.0;
 +    }
 +    else
 +    {
 +        s->num_taps = 128;
 +        s->downsampling = 2;
 +        s->quantization = 1.0;
 +    }
 +
 +    // max tap 2048
 +    if ((s->num_taps < 32) || (s->num_taps > 1024) ||
 +        ((s->num_taps>>5)<<5 != s->num_taps))
 +    {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid number of taps\n");
 +        return -1;
 +    }
 +
 +    // generate taps
 +    s->tap_quant = av_mallocz(4* s->num_taps);
 +    for (i = 0; i < s->num_taps; i++)
 +        s->tap_quant[i] = (int)(sqrt(i+1));
 +
 +    s->channels = avctx->channels;
 +    s->samplerate = avctx->sample_rate;
 +
 +    s->block_align = (int)(2048.0*s->samplerate/44100)/s->downsampling;
 +    s->frame_size = s->channels*s->block_align*s->downsampling;
 +
 +    s->tail_size = s->num_taps*s->channels;
 +    s->tail = av_mallocz(4 * s->tail_size);
 +    if (!s->tail)
 +        return -1;
 +
 +    s->predictor_k = av_mallocz(4 * s->num_taps);
 +    if (!s->predictor_k)
 +        return -1;
 +
 +    for (i = 0; i < s->channels; i++)
 +    {
 +        s->coded_samples[i] = av_mallocz(4* s->block_align);
 +        if (!s->coded_samples[i])
 +            return -1;
 +    }
 +
 +    s->int_samples = av_mallocz(4* s->frame_size);
 +
 +    s->window_size = ((2*s->tail_size)+s->frame_size);
 +    s->window = av_mallocz(4* s->window_size);
 +    if (!s->window)
 +        return -1;
 +
 +    avctx->extradata = av_mallocz(16);
 +    if (!avctx->extradata)
 +        return -1;
 +    init_put_bits(&pb, avctx->extradata, 16*8);
 +
 +    put_bits(&pb, 2, version); // version
 +    if (version == 1)
 +    {
 +        put_bits(&pb, 2, s->channels);
 +        put_bits(&pb, 4, code_samplerate(s->samplerate));
 +    }
 +    put_bits(&pb, 1, s->lossless);
 +    if (!s->lossless)
 +        put_bits(&pb, 3, SAMPLE_SHIFT); // XXX FIXME: sample precision
 +    put_bits(&pb, 2, s->decorrelation);
 +    put_bits(&pb, 2, s->downsampling);
 +    put_bits(&pb, 5, (s->num_taps >> 5)-1); // 32..1024
 +    put_bits(&pb, 1, 0); // XXX FIXME: no custom tap quant table
 +
 +    flush_put_bits(&pb);
 +    avctx->extradata_size = put_bits_count(&pb)/8;
 +
 +    av_log(avctx, AV_LOG_INFO, "Sonic: ver: %d ls: %d dr: %d taps: %d block: %d frame: %d downsamp: %d\n",
 +        version, s->lossless, s->decorrelation, s->num_taps, s->block_align, s->frame_size, s->downsampling);
 +
 +    avctx->coded_frame = avcodec_alloc_frame();
 +    if (!avctx->coded_frame)
 +        return AVERROR(ENOMEM);
 +    avctx->coded_frame->key_frame = 1;
 +    avctx->frame_size = s->block_align*s->downsampling;
 +
 +    return 0;
 +}
 +
 +static av_cold int sonic_encode_close(AVCodecContext *avctx)
 +{
 +    SonicContext *s = avctx->priv_data;
 +    int i;
 +
 +    av_freep(&avctx->coded_frame);
 +
 +    for (i = 0; i < s->channels; i++)
 +        av_free(s->coded_samples[i]);
 +
 +    av_free(s->predictor_k);
 +    av_free(s->tail);
 +    av_free(s->tap_quant);
 +    av_free(s->window);
 +    av_free(s->int_samples);
 +
 +    return 0;
 +}
 +
 +static int sonic_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 +                              const AVFrame *frame, int *got_packet_ptr)
 +{
 +    SonicContext *s = avctx->priv_data;
 +    PutBitContext pb;
 +    int i, j, ch, quant = 0, x = 0;
 +    int ret;
 +    const short *samples = (const int16_t*)frame->data[0];
 +
 +    if ((ret = ff_alloc_packet2(avctx, avpkt, s->frame_size * 5 + 1000)) < 0)
 +        return ret;
 +
 +    init_put_bits(&pb, avpkt->data, avpkt->size);
 +
 +    // short -> internal
 +    for (i = 0; i < s->frame_size; i++)
 +        s->int_samples[i] = samples[i];
 +
 +    if (!s->lossless)
 +        for (i = 0; i < s->frame_size; i++)
 +            s->int_samples[i] = s->int_samples[i] << SAMPLE_SHIFT;
 +
 +    switch(s->decorrelation)
 +    {
 +        case MID_SIDE:
 +            for (i = 0; i < s->frame_size; i += s->channels)
 +            {
 +                s->int_samples[i] += s->int_samples[i+1];
 +                s->int_samples[i+1] -= shift(s->int_samples[i], 1);
 +            }
 +            break;
 +        case LEFT_SIDE:
 +            for (i = 0; i < s->frame_size; i += s->channels)
 +                s->int_samples[i+1] -= s->int_samples[i];
 +            break;
 +        case RIGHT_SIDE:
 +            for (i = 0; i < s->frame_size; i += s->channels)
 +                s->int_samples[i] -= s->int_samples[i+1];
 +            break;
 +    }
 +
 +    memset(s->window, 0, 4* s->window_size);
 +
 +    for (i = 0; i < s->tail_size; i++)
 +        s->window[x++] = s->tail[i];
 +
 +    for (i = 0; i < s->frame_size; i++)
 +        s->window[x++] = s->int_samples[i];
 +
 +    for (i = 0; i < s->tail_size; i++)
 +        s->window[x++] = 0;
 +
 +    for (i = 0; i < s->tail_size; i++)
 +        s->tail[i] = s->int_samples[s->frame_size - s->tail_size + i];
 +
 +    // generate taps
 +    modified_levinson_durbin(s->window, s->window_size,
 +                s->predictor_k, s->num_taps, s->channels, s->tap_quant);
 +    if (intlist_write(&pb, s->predictor_k, s->num_taps, 0) < 0)
 +        return -1;
 +
 +    for (ch = 0; ch < s->channels; ch++)
 +    {
 +        x = s->tail_size+ch;
 +        for (i = 0; i < s->block_align; i++)
 +        {
 +            int sum = 0;
 +            for (j = 0; j < s->downsampling; j++, x += s->channels)
 +                sum += s->window[x];
 +            s->coded_samples[ch][i] = sum;
 +        }
 +    }
 +
 +    // simple rate control code
 +    if (!s->lossless)
 +    {
 +        double energy1 = 0.0, energy2 = 0.0;
 +        for (ch = 0; ch < s->channels; ch++)
 +        {
 +            for (i = 0; i < s->block_align; i++)
 +            {
 +                double sample = s->coded_samples[ch][i];
 +                energy2 += sample*sample;
 +                energy1 += fabs(sample);
 +            }
 +        }
 +
 +        energy2 = sqrt(energy2/(s->channels*s->block_align));
 +        energy1 = sqrt(2.0)*energy1/(s->channels*s->block_align);
 +
 +        // increase bitrate when samples are like a gaussian distribution
 +        // reduce bitrate when samples are like a two-tailed exponential distribution
 +
 +        if (energy2 > energy1)
 +            energy2 += (energy2-energy1)*RATE_VARIATION;
 +
 +        quant = (int)(BASE_QUANT*s->quantization*energy2/SAMPLE_FACTOR);
 +//        av_log(avctx, AV_LOG_DEBUG, "quant: %d energy: %f / %f\n", quant, energy1, energy2);
 +
 +        if (quant < 1)
 +            quant = 1;
 +        if (quant > 65534)
 +            quant = 65534;
 +
 +        set_ue_golomb(&pb, quant);
 +
 +        quant *= SAMPLE_FACTOR;
 +    }
 +
 +    // write out coded samples
 +    for (ch = 0; ch < s->channels; ch++)
 +    {
 +        if (!s->lossless)
 +            for (i = 0; i < s->block_align; i++)
 +                s->coded_samples[ch][i] = divide(s->coded_samples[ch][i], quant);
 +
 +        if (intlist_write(&pb, s->coded_samples[ch], s->block_align, 1) < 0)
 +            return -1;
 +    }
 +
 +//    av_log(avctx, AV_LOG_DEBUG, "used bytes: %d\n", (put_bits_count(&pb)+7)/8);
 +
 +    flush_put_bits(&pb);
 +    avpkt->size = (put_bits_count(&pb)+7)/8;
 +    *got_packet_ptr = 1;
 +    return 0;
 +}
 +#endif /* CONFIG_SONIC_ENCODER || CONFIG_SONIC_LS_ENCODER */
 +
 +#if CONFIG_SONIC_DECODER
 +static const int samplerate_table[] =
 +    { 44100, 22050, 11025, 96000, 48000, 32000, 24000, 16000, 8000 };
 +
 +static av_cold int sonic_decode_init(AVCodecContext *avctx)
 +{
 +    SonicContext *s = avctx->priv_data;
 +    GetBitContext gb;
 +    int i, version;
 +
 +    s->channels = avctx->channels;
 +    s->samplerate = avctx->sample_rate;
 +
 +    avcodec_get_frame_defaults(&s->frame);
 +    avctx->coded_frame = &s->frame;
 +
 +    if (!avctx->extradata)
 +    {
 +        av_log(avctx, AV_LOG_ERROR, "No mandatory headers present\n");
 +        return -1;
 +    }
 +
 +    init_get_bits(&gb, avctx->extradata, avctx->extradata_size);
 +
 +    version = get_bits(&gb, 2);
 +    if (version > 1)
 +    {
 +        av_log(avctx, AV_LOG_ERROR, "Unsupported Sonic version, please report\n");
 +        return -1;
 +    }
 +
 +    if (version == 1)
 +    {
 +        s->channels = get_bits(&gb, 2);
 +        s->samplerate = samplerate_table[get_bits(&gb, 4)];
 +        av_log(avctx, AV_LOG_INFO, "Sonicv2 chans: %d samprate: %d\n",
 +            s->channels, s->samplerate);
 +    }
 +
 +    if (s->channels > MAX_CHANNELS)
 +    {
 +        av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n");
 +        return -1;
 +    }
 +
 +    s->lossless = get_bits1(&gb);
 +    if (!s->lossless)
 +        skip_bits(&gb, 3); // XXX FIXME
 +    s->decorrelation = get_bits(&gb, 2);
 +
 +    s->downsampling = get_bits(&gb, 2);
 +    if (!s->downsampling) {
 +        av_log(avctx, AV_LOG_ERROR, "invalid downsampling value\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    s->num_taps = (get_bits(&gb, 5)+1)<<5;
 +    if (get_bits1(&gb)) // XXX FIXME
 +        av_log(avctx, AV_LOG_INFO, "Custom quant table\n");
 +
 +    s->block_align = (int)(2048.0*s->samplerate/44100)/s->downsampling;
 +    s->frame_size = s->channels*s->block_align*s->downsampling;
 +//    avctx->frame_size = s->block_align;
 +
 +    av_log(avctx, AV_LOG_INFO, "Sonic: ver: %d ls: %d dr: %d taps: %d block: %d frame: %d downsamp: %d\n",
 +        version, s->lossless, s->decorrelation, s->num_taps, s->block_align, s->frame_size, s->downsampling);
 +
 +    // generate taps
 +    s->tap_quant = av_mallocz(4* s->num_taps);
 +    for (i = 0; i < s->num_taps; i++)
 +        s->tap_quant[i] = (int)(sqrt(i+1));
 +
 +    s->predictor_k = av_mallocz(4* s->num_taps);
 +
 +    for (i = 0; i < s->channels; i++)
 +    {
 +        s->predictor_state[i] = av_mallocz(4* s->num_taps);
 +        if (!s->predictor_state[i])
 +            return -1;
 +    }
 +
 +    for (i = 0; i < s->channels; i++)
 +    {
 +        s->coded_samples[i] = av_mallocz(4* s->block_align);
 +        if (!s->coded_samples[i])
 +            return -1;
 +    }
 +    s->int_samples = av_mallocz(4* s->frame_size);
 +
 +    avctx->sample_fmt = AV_SAMPLE_FMT_S16;
 +    return 0;
 +}
 +
 +static av_cold int sonic_decode_close(AVCodecContext *avctx)
 +{
 +    SonicContext *s = avctx->priv_data;
 +    int i;
 +
 +    av_free(s->int_samples);
 +    av_free(s->tap_quant);
 +    av_free(s->predictor_k);
 +
 +    for (i = 0; i < s->channels; i++)
 +    {
 +        av_free(s->predictor_state[i]);
 +        av_free(s->coded_samples[i]);
 +    }
 +
 +    return 0;
 +}
 +
 +static int sonic_decode_frame(AVCodecContext *avctx,
 +                            void *data, int *got_frame_ptr,
 +                            AVPacket *avpkt)
 +{
 +    const uint8_t *buf = avpkt->data;
 +    int buf_size = avpkt->size;
 +    SonicContext *s = avctx->priv_data;
 +    GetBitContext gb;
 +    int i, quant, ch, j, ret;
 +    int16_t *samples;
 +
 +    if (buf_size == 0) return 0;
 +
 +    s->frame.nb_samples = s->frame_size;
++    if ((ret = ff_get_buffer(avctx, &s->frame, 0)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +    samples = (int16_t *)s->frame.data[0];
 +
 +//    av_log(NULL, AV_LOG_INFO, "buf_size: %d\n", buf_size);
 +
 +    init_get_bits(&gb, buf, buf_size*8);
 +
 +    intlist_read(&gb, s->predictor_k, s->num_taps, 0);
 +
 +    // dequantize
 +    for (i = 0; i < s->num_taps; i++)
 +        s->predictor_k[i] *= s->tap_quant[i];
 +
 +    if (s->lossless)
 +        quant = 1;
 +    else
 +        quant = get_ue_golomb(&gb) * SAMPLE_FACTOR;
 +
 +//    av_log(NULL, AV_LOG_INFO, "quant: %d\n", quant);
 +
 +    for (ch = 0; ch < s->channels; ch++)
 +    {
 +        int x = ch;
 +
 +        predictor_init_state(s->predictor_k, s->predictor_state[ch], s->num_taps);
 +
 +        intlist_read(&gb, s->coded_samples[ch], s->block_align, 1);
 +
 +        for (i = 0; i < s->block_align; i++)
 +        {
 +            for (j = 0; j < s->downsampling - 1; j++)
 +            {
 +                s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, 0);
 +                x += s->channels;
 +            }
 +
 +            s->int_samples[x] = predictor_calc_error(s->predictor_k, s->predictor_state[ch], s->num_taps, s->coded_samples[ch][i] * quant);
 +            x += s->channels;
 +        }
 +
 +        for (i = 0; i < s->num_taps; i++)
 +            s->predictor_state[ch][i] = s->int_samples[s->frame_size - s->channels + ch - i*s->channels];
 +    }
 +
 +    switch(s->decorrelation)
 +    {
 +        case MID_SIDE:
 +            for (i = 0; i < s->frame_size; i += s->channels)
 +            {
 +                s->int_samples[i+1] += shift(s->int_samples[i], 1);
 +                s->int_samples[i] -= s->int_samples[i+1];
 +            }
 +            break;
 +        case LEFT_SIDE:
 +            for (i = 0; i < s->frame_size; i += s->channels)
 +                s->int_samples[i+1] += s->int_samples[i];
 +            break;
 +        case RIGHT_SIDE:
 +            for (i = 0; i < s->frame_size; i += s->channels)
 +                s->int_samples[i] += s->int_samples[i+1];
 +            break;
 +    }
 +
 +    if (!s->lossless)
 +        for (i = 0; i < s->frame_size; i++)
 +            s->int_samples[i] = shift(s->int_samples[i], SAMPLE_SHIFT);
 +
 +    // internal -> short
 +    for (i = 0; i < s->frame_size; i++)
 +        samples[i] = av_clip_int16(s->int_samples[i]);
 +
 +    align_get_bits(&gb);
 +
 +    *got_frame_ptr = 1;
 +    *(AVFrame*)data = s->frame;
 +
 +    return (get_bits_count(&gb)+7)/8;
 +}
 +
 +AVCodec ff_sonic_decoder = {
 +    .name           = "sonic",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_SONIC,
 +    .priv_data_size = sizeof(SonicContext),
 +    .init           = sonic_decode_init,
 +    .close          = sonic_decode_close,
 +    .decode         = sonic_decode_frame,
 +    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_EXPERIMENTAL,
 +    .long_name = NULL_IF_CONFIG_SMALL("Sonic"),
 +};
 +#endif /* CONFIG_SONIC_DECODER */
 +
 +#if CONFIG_SONIC_ENCODER
 +AVCodec ff_sonic_encoder = {
 +    .name           = "sonic",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_SONIC,
 +    .priv_data_size = sizeof(SonicContext),
 +    .init           = sonic_encode_init,
 +    .encode2        = sonic_encode_frame,
 +    .capabilities   = CODEC_CAP_EXPERIMENTAL,
 +    .close          = sonic_encode_close,
 +    .long_name = NULL_IF_CONFIG_SMALL("Sonic"),
 +};
 +#endif
 +
 +#if CONFIG_SONIC_LS_ENCODER
 +AVCodec ff_sonic_ls_encoder = {
 +    .name           = "sonicls",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_SONIC_LS,
 +    .priv_data_size = sizeof(SonicContext),
 +    .init           = sonic_encode_init,
 +    .encode2        = sonic_encode_frame,
 +    .capabilities   = CODEC_CAP_EXPERIMENTAL,
 +    .close          = sonic_encode_close,
 +    .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"),
 +};
 +#endif
@@@ -44,11 -31,9 +31,9 @@@ static int sunrast_decode_frame(AVCodec
  {
      const uint8_t *buf       = avpkt->data;
      const uint8_t *buf_end   = avpkt->data + avpkt->size;
-     SUNRASTContext * const s = avctx->priv_data;
-     AVFrame *picture         = data;
-     AVFrame * const p        = &s->picture;
+     AVFrame * const p        = data;
      unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen;
 -    uint8_t *ptr;
 +    uint8_t *ptr, *ptr2 = NULL;
      const uint8_t *bufstart = buf;
      int ret;
  
              buf += alen;
          }
      }
 +    if (avctx->pix_fmt == AV_PIX_FMT_PAL8 && depth < 8) {
 +        uint8_t *ptr_free = ptr2;
 +        ptr = p->data[0];
 +        for (y=0; y<h; y++) {
 +            for (x = 0; x < (w + 7 >> 3) * depth; x++) {
 +                if (depth == 1) {
 +                    ptr[8*x]   = ptr2[x] >> 7;
 +                    ptr[8*x+1] = ptr2[x] >> 6 & 1;
 +                    ptr[8*x+2] = ptr2[x] >> 5 & 1;
 +                    ptr[8*x+3] = ptr2[x] >> 4 & 1;
 +                    ptr[8*x+4] = ptr2[x] >> 3 & 1;
 +                    ptr[8*x+5] = ptr2[x] >> 2 & 1;
 +                    ptr[8*x+6] = ptr2[x] >> 1 & 1;
 +                    ptr[8*x+7] = ptr2[x]      & 1;
 +                } else {
 +                    ptr[2*x]   = ptr2[x] >> 4;
 +                    ptr[2*x+1] = ptr2[x] & 0xF;
 +                }
 +            }
 +            ptr  += p->linesize[0];
 +            ptr2 += (w + 15 >> 3) * depth;
 +        }
 +        av_freep(&ptr_free);
 +    }
  
-     *picture   = s->picture;
      *got_frame = 1;
  
      return buf - bufstart;
@@@ -692,7 -689,7 +689,7 @@@ static int svq1_decode_frame(AVCodecCon
          } else {
              /* delta frame */
              uint8_t *previous = s->prev->data[i];
-             if (!previous || s->prev->width != s->cur->width || s->prev->height != s->cur->height) {
 -            if (!previous) {
++            if (!previous || s->prev->width != cur->width || s->prev->height != cur->height) {
                  av_log(avctx, AV_LOG_ERROR, "Missing reference frame.\n");
                  result = AVERROR_INVALIDDATA;
                  goto err;
@@@ -546,10 -550,8 +546,10 @@@ static int svq1_encode_frame(AVCodecCon
      }
  
      if (!s->current_picture.data[0]) {
-         if ((ret = ff_get_buffer(avctx, &s->current_picture))< 0 ||
-             (ret = ff_get_buffer(avctx, &s->last_picture))   < 0) {
 -        ff_get_buffer(avctx, &s->current_picture, 0);
 -        ff_get_buffer(avctx, &s->last_picture, 0);
++        if ((ret = ff_get_buffer(avctx, &s->current_picture, 0))< 0 ||
++            (ret = ff_get_buffer(avctx, &s->last_picture, 0))   < 0) {
 +            return ret;
 +        }
          s->scratchbuf = av_malloc(s->current_picture.linesize[0] * 16 * 2);
      }
  
@@@ -1249,22 -1259,12 +1276,24 @@@ static int svq3_decode_frame(AVCodecCon
                             h->low_delay, h->mb_height * 16, h->mb_width * 16);
      }
  
 +    left = buf_size*8 - get_bits_count(&h->gb);
 +
 +    if (h->mb_y != h->mb_height || h->mb_x != h->mb_width) {
 +        av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, h->mb_y, h->mb_x, left);
 +        //av_hex_dump(stderr, buf+buf_size-8, 8);
 +    }
 +
 +    if (left < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "frame num %d left %d\n", avctx->frame_number, left);
 +        return -1;
 +    }
 +
      if (h->pict_type == AV_PICTURE_TYPE_B || h->low_delay)
-         *(AVFrame *)data = s->cur_pic->f;
-     else
-         *(AVFrame *)data = s->last_pic->f;
+         ret = av_frame_ref(data, &s->cur_pic->f);
+     else if (s->last_pic->f.data[0])
+         ret = av_frame_ref(data, &s->last_pic->f);
+     if (ret < 0)
+         return ret;
  
      /* Do not output the last pic after seeking. */
      if (s->last_pic->f.data[0] || h->low_delay)
@@@ -749,10 -740,10 +749,10 @@@ static int tak_decode_frame(AVCodecCont
                                               : s->ti.frame_samples;
  
      frame->nb_samples = s->nb_samples;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0)
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
          return ret;
  
 -    if (avctx->bits_per_coded_sample <= 16) {
 +    if (avctx->bits_per_raw_sample <= 16) {
          int buf_size = av_samples_get_buffer_size(NULL, avctx->channels,
                                                    s->nb_samples,
                                                    AV_SAMPLE_FMT_S32P, 0);
  #include "targa.h"
  
  typedef struct TargaContext {
-     AVFrame picture;
      GetByteContext gb;
 -
 -    int color_type;
 -    int compression_type;
  } TargaContext;
  
 +static uint8_t *advance_line(uint8_t *start, uint8_t *line,
 +                             int stride, int *y, int h, int interleave)
 +{
 +    *y += interleave;
 +
 +    if (*y < h) {
 +        return line + interleave * stride;
 +    } else {
 +        *y = (*y + 1) & (interleave - 1);
 +        if (*y && *y < h) {
 +            return start + *y * stride;
 +        } else {
 +            return NULL;
 +        }
 +    }
 +}
 +
  static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s,
 -                            uint8_t *dst, int w, int h, int stride, int bpp)
 +                            uint8_t *start, int w, int h, int stride,
 +                            int bpp, int interleave)
  {
      int x, y;
      int depth = (bpp + 1) >> 3;
@@@ -112,13 -98,11 +111,12 @@@ static int decode_frame(AVCodecContext 
                          AVPacket *avpkt)
  {
      TargaContext * const s = avctx->priv_data;
-     AVFrame *picture = data;
-     AVFrame * const p = &s->picture;
+     AVFrame * const p = data;
      uint8_t *dst;
      int stride;
 -    int idlen, compr, y, w, h, bpp, flags, ret;
 +    int idlen, pal, compr, y, w, h, bpp, flags, ret;
      int first_clr, colors, csize;
 +    int interleave;
  
      bytestream2_init(&s->gb, avpkt->data, avpkt->size);
  
          return AVERROR_INVALIDDATA;
      }
  
-     if (s->picture.data[0])
-         avctx->release_buffer(avctx, &s->picture);
 +    if (colors && (colors + first_clr) > 256) {
 +        av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      if ((ret = av_image_check_size(w, h, 0, avctx)) < 0)
          return ret;
 -    if(w != avctx->width || h != avctx->height)
 +    if (w != avctx->width || h != avctx->height)
          avcodec_set_dimensions(avctx, w, h);
-     if ((ret = ff_get_buffer(avctx, p)) < 0) {
 -    if ((ret = ff_get_buffer(avctx, p, 0)) < 0){
++    if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
index 3b97000,0000000..67d19a1
mode 100644,000000..100644
--- /dev/null
@@@ -1,109 -1,0 +1,92 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame) {
-         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-         return AVERROR(ENOMEM);
-     }
 +/*
 + * Pinnacle TARGA CineWave YUV16 decoder
 + * Copyright (c) 2012 Carl Eugen Hoyos
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +
 +static av_cold int y216_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt             = AV_PIX_FMT_YUV422P16;
 +    avctx->bits_per_raw_sample = 14;
 +
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int y216_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame, AVPacket *avpkt)
 +{
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    const uint16_t *src = (uint16_t *)avpkt->data;
 +    uint16_t *y, *u, *v, aligned_width = FFALIGN(avctx->width, 4);
 +    int i, j;
 +
-     pic->reference = 0;
-     if (ff_get_buffer(avctx, pic) < 0) {
 +    if (avpkt->size < 4 * avctx->height * aligned_width) {
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     *(AVFrame *)data = *pic;
++    if (ff_get_buffer(avctx, pic, 0) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    pic->key_frame = 1;
 +    pic->pict_type = AV_PICTURE_TYPE_I;
 +
 +    y = (uint16_t *)pic->data[0];
 +    u = (uint16_t *)pic->data[1];
 +    v = (uint16_t *)pic->data[2];
 +
 +    for (i = 0; i < avctx->height; i++) {
 +        for (j = 0; j < avctx->width >> 1; j++) {
 +            u[    j    ] = src[4 * j    ] << 2 | src[4 * j    ] >> 14;
 +            y[2 * j    ] = src[4 * j + 1] << 2 | src[4 * j + 1] >> 14;
 +            v[    j    ] = src[4 * j + 2] << 2 | src[4 * j + 2] >> 14;
 +            y[2 * j + 1] = src[4 * j + 3] << 2 | src[4 * j + 3] >> 14;
 +        }
 +
 +        y += pic->linesize[0] >> 1;
 +        u += pic->linesize[1] >> 1;
 +        v += pic->linesize[2] >> 1;
 +        src += aligned_width << 1;
 +    }
 +
 +    *got_frame = 1;
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int y216_decode_close(AVCodecContext *avctx)
 +{
 +
 +    return 0;
 +}
 +
 +AVCodec ff_targa_y216_decoder = {
 +    .name         = "targa_y216",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_TARGA_Y216,
 +    .init         = y216_decode_init,
 +    .decode       = y216_decode_frame,
 +    .close        = y216_decode_close,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"),
 +};
Simple merge
@@@ -231,11 -232,9 +233,9 @@@ static int seqvideo_decode_frame(AVCode
  
      SeqVideoContext *seq = avctx->priv_data;
  
-     seq->frame.reference = 3;
-     seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     if (avctx->reget_buffer(avctx, &seq->frame)) {
+     if ((ret = ff_reget_buffer(avctx, &seq->frame)) < 0) {
 -        av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n");
 +        av_log(seq->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
-         return -1;
+         return ret;
      }
  
      if (seqvideo_decode(seq, buf, buf_size))
@@@ -43,8 -41,6 +43,8 @@@
  
  typedef struct TiffContext {
      AVCodecContext *avctx;
-     AVFrame picture;
 +    GetByteContext gb;
++    AVFrame picture;
  
      int width, height;
      unsigned int bpp, bppcount;
@@@ -650,12 -285,12 +648,12 @@@ static int init_image(TiffContext *s, A
      }
      if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8) {
          if (s->palette_is_set) {
-             memcpy(s->picture.data[1], s->palette, sizeof(s->palette));
+             memcpy(frame->data[1], s->palette, sizeof(s->palette));
          } else {
              /* make default grayscale pal */
-             pal = (uint32_t *) s->picture.data[1];
+             pal = (uint32_t *) frame->data[1];
 -            for (i = 0; i < 256; i++)
 -                pal[i] = i * 0x010101;
 +            for (i = 0; i < 1<<s->bpp; i++)
 +                pal[i] = 0xFFU << 24 | i * 255 / ((1<<s->bpp) - 1) * 0x010101;
          }
      }
      return 0;
@@@ -1040,9 -539,11 +1038,8 @@@ static int tiff_decode_tag(TiffContext 
  static int decode_frame(AVCodecContext *avctx,
                          void *data, int *got_frame, AVPacket *avpkt)
  {
 -    const uint8_t *buf = avpkt->data;
 -    int buf_size = avpkt->size;
      TiffContext *const s = avctx->priv_data;
-     AVFrame *picture = data;
-     AVFrame *const p = &s->picture;
+     AVFrame *const p = data;
 -    const uint8_t *orig_buf = buf, *end_buf = buf + buf_size;
      unsigned off;
      int id, le, ret;
      int i, j, entries;
      s->invert = 0;
      s->compr = TIFF_RAW;
      s->fill_order = 0;
-     av_frame_set_metadata(&s->picture, NULL);
 +    free_geotags(s);
 +    /* metadata has been destroyed from lavc internals, that pointer is not
 +     * valid anymore */
++    av_frame_set_metadata(p, NULL);
 +
      // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number
      // that further identifies the file as a TIFF file"
 -    if (tget_short(&buf, le) != 42) {
 +    if (tget_short(&s->gb, le) != 42) {
          av_log(avctx, AV_LOG_ERROR,
                 "The answer to life, universe and everything is not correct!\n");
          return AVERROR_INVALIDDATA;
      }
  
      if (s->invert) {
-         dst = s->picture.data[0];
 -        uint8_t *src;
 -        int j;
 -
 -        src = p->data[0];
 -        for (j = 0; j < s->height; j++) {
 -            for (i = 0; i < p->linesize[0]; i++)
 -                src[i] = 255 - src[i];
 -            src += p->linesize[0];
++        dst = p->data[0];
 +        for (i = 0; i < s->height; i++) {
-             for (j = 0; j < s->picture.linesize[0]; j++)
++            for (j = 0; j < p->linesize[0]; j++)
 +                dst[j] = (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 ? (1<<s->bpp) - 1 : 255) - dst[j];
-             dst += s->picture.linesize[0];
++            dst += p->linesize[0];
          }
      }
-     *picture   = s->picture;
      *got_frame = 1;
  
 -    return buf_size;
 +    return avpkt->size;
  }
  
  static av_cold int tiff_init(AVCodecContext *avctx)
@@@ -1229,12 -672,7 +1223,10 @@@ static av_cold int tiff_end(AVCodecCont
  {
      TiffContext *const s = avctx->priv_data;
  
 +    free_geotags(s);
 +
      ff_lzw_decode_close(&s->lzw);
-     if (s->picture.data[0])
-         avctx->release_buffer(avctx, &s->picture);
 +    av_freep(&s->deinvert_buf);
      return 0;
  }
  
@@@ -65,23 -57,22 +58,23 @@@ static int tmv_decode_frame(AVCodecCont
          return AVERROR_INVALIDDATA;
      }
  
-     tmv->pic.pict_type = AV_PICTURE_TYPE_I;
-     tmv->pic.key_frame = 1;
-     dst                = tmv->pic.data[0];
+     frame->pict_type = AV_PICTURE_TYPE_I;
+     frame->key_frame = 1;
+     dst              = frame->data[0];
  
-     tmv->pic.palette_has_changed = 1;
-     memcpy(tmv->pic.data[1], ff_cga_palette, 16 * 4);
-     memset(tmv->pic.data[1] + 16 * 4, 0, AVPALETTE_SIZE - 16 * 4);
+     frame->palette_has_changed = 1;
+     memcpy(frame->data[1], ff_cga_palette, 16 * 4);
++    memset(frame->data[1] + 16 * 4, 0, AVPALETTE_SIZE - 16 * 4);
  
      for (y = 0; y < char_rows; y++) {
          for (x = 0; x < char_cols; x++) {
              c  = *src++;
              bg = *src  >> 4;
              fg = *src++ & 0xF;
-             ff_draw_pc_font(dst + x * 8, tmv->pic.linesize[0],
+             ff_draw_pc_font(dst + x * 8, frame->linesize[0],
 -                            ff_cga_font, 8, c, fg, bg);
 +                            avpriv_cga_font, 8, c, fg, bg);
          }
-         dst += tmv->pic.linesize[0] * 8;
+         dst += frame->linesize[0] * 8;
      }
  
      *got_frame = 1;
Simple merge
@@@ -866,10 -848,10 +867,9 @@@ static int decode_frame(AVCodecContext 
          av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n");
          return AVERROR(ENOMEM);
      }
-     p->reference = 3;
-     p->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
-     if ((ret = avctx->reget_buffer(avctx, p)) < 0) {
+     if ((ret = ff_reget_buffer(avctx, p)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -        av_free(swbuf);
          return ret;
      }
  
  
      l->cur = !l->cur;
      *got_frame      = 1;
-     *(AVFrame*)data = l->pic;
+     ret = av_frame_ref(data, &l->pic);
 -    av_free(swbuf);
  
-     return buf_size;
+     return (ret < 0) ? ret : buf_size;
  }
  
  static av_cold int decode_init(AVCodecContext *avctx)
@@@ -986,11 -967,8 +986,10 @@@ static av_cold int decode_end(AVCodecCo
          av_free(l->U2_base);
          av_free(l->V2_base);
      }
 +    av_freep(&l->buffer);
 +    l->buffer_size = 0;
  
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
+     av_frame_unref(pic);
  
      return 0;
  }
Simple merge
@@@ -47,7 -47,6 +47,7 @@@
  typedef struct TsccContext {
  
      AVCodecContext *avctx;
-     AVFrame pic;
++    AVFrame *frame;
  
      // Bits per pixel
      int bpp;
@@@ -69,13 -68,12 +69,12 @@@ static int decode_frame(AVCodecContext 
      int buf_size = avpkt->size;
      CamtasiaContext * const c = avctx->priv_data;
      const unsigned char *encoded = buf;
 -    AVFrame *frame = data;
++    AVFrame *frame = c->frame;
      int zret; // Zlib return code
      int ret, len = buf_size;
  
-     c->pic.reference = 3;
-     c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
-     if ((ret = avctx->reget_buffer(avctx, &c->pic)) < 0) {
 -    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0){
--        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
++    if ((ret = ff_reget_buffer(avctx, frame)) < 0) {
++        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
          return ret;
      }
  
          const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
  
          if (pal) {
-             c->pic.palette_has_changed = 1;
+             frame->palette_has_changed = 1;
              memcpy(c->pal, pal, AVPALETTE_SIZE);
          }
-         memcpy(c->pic.data[1], c->pal, AVPALETTE_SIZE);
+         memcpy(frame->data[1], c->pal, AVPALETTE_SIZE);
      }
  
++    if ((ret = av_frame_ref(data, frame)) < 0)
++        return ret;
      *got_frame      = 1;
-     *(AVFrame*)data = c->pic;
  
      /* always report that the buffer was completely consumed */
      return buf_size;
@@@ -163,6 -159,6 +162,8 @@@ static av_cold int decode_init(AVCodecC
          return AVERROR_UNKNOWN;
      }
  
++    c->frame = av_frame_alloc();
++
      return 0;
  }
  
@@@ -171,9 -167,7 +172,8 @@@ static av_cold int decode_end(AVCodecCo
      CamtasiaContext * const c = avctx->priv_data;
  
      av_freep(&c->decomp_buf);
++    av_frame_free(&c->frame);
  
-     if (c->pic.data[0])
-         avctx->release_buffer(avctx, &c->pic);
      inflateEnd(&c->zstream);
  
      return 0;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
  #include "config.h"
  #include "libavutil/avassert.h"
  #include "libavutil/avstring.h"
 +#include "libavutil/bprint.h"
  #include "libavutil/channel_layout.h"
  #include "libavutil/crc.h"
+ #include "libavutil/frame.h"
  #include "libavutil/mathematics.h"
  #include "libavutil/pixdesc.h"
  #include "libavutil/imgutils.h"
@@@ -175,12 -152,10 +176,10 @@@ void avcodec_set_dimensions(AVCodecCont
  {
      s->coded_width  = width;
      s->coded_height = height;
 -    s->width        = width;
 -    s->height       = height;
 +    s->width        = -((-width ) >> s->lowres);
 +    s->height       = -((-height) >> s->lowres);
  }
  
- #define INTERNAL_BUFFER_SIZE (32 + 1)
  #if (ARCH_ARM && HAVE_NEON) || ARCH_PPC || HAVE_MMX
  #   define STRIDE_ALIGN 16
  #else
@@@ -465,76 -348,169 +402,191 @@@ static int update_frame_pool(AVCodecCon
              size[i] = picture.data[i + 1] - picture.data[i];
          size[i] = tmpsize - (picture.data[i] - picture.data[0]);
  
-         memset(buf->base, 0, sizeof(buf->base));
-         memset(buf->data, 0, sizeof(buf->data));
-         for (i = 0; i < 4 && size[i]; i++) {
-             const int h_shift = i == 0 ? 0 : h_chroma_shift;
-             const int v_shift = i == 0 ? 0 : v_chroma_shift;
+         for (i = 0; i < 4; i++) {
+             av_buffer_pool_uninit(&pool->pools[i]);
+             pool->linesize[i] = picture.linesize[i];
+             if (size[i]) {
+                 pool->pools[i] = av_buffer_pool_init(size[i] + 16, NULL);
+                 if (!pool->pools[i]) {
+                     ret = AVERROR(ENOMEM);
+                     goto fail;
+                 }
+             }
+         }
+         pool->format = frame->format;
+         pool->width  = frame->width;
+         pool->height = frame->height;
  
-             buf->linesize[i] = picture.linesize[i];
+         break;
+         }
+     case AVMEDIA_TYPE_AUDIO: {
+         int ch     = av_get_channel_layout_nb_channels(frame->channel_layout);
+         int planar = av_sample_fmt_is_planar(frame->format);
+         int planes = planar ? ch : 1;
+         if (pool->format == frame->format && pool->planes == planes &&
+             pool->channels == ch && frame->nb_samples == pool->samples)
+             return 0;
+         av_buffer_pool_uninit(&pool->pools[0]);
+         ret = av_samples_get_buffer_size(&pool->linesize[0], ch,
+                                          frame->nb_samples, frame->format, 0);
+         if (ret < 0)
+             goto fail;
  
-             buf->base[i] = av_malloc(size[i] + 16); //FIXME 16
-             if (buf->base[i] == NULL)
-                 return AVERROR(ENOMEM);
+         pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL);
+         if (!pool->pools[0]) {
+             ret = AVERROR(ENOMEM);
+             goto fail;
+         }
  
-             // no edge if EDGE EMU or not planar YUV
-             if ((s->flags & CODEC_FLAG_EMU_EDGE) || !size[2])
-                 buf->data[i] = buf->base[i];
-             else
-                 buf->data[i] = buf->base[i] + FFALIGN((buf->linesize[i] * EDGE_WIDTH >> v_shift) + (pixel_size * EDGE_WIDTH >> h_shift), stride_align[i]);
+         pool->format     = frame->format;
+         pool->planes     = planes;
+         pool->channels   = ch;
+         pool->samples = frame->nb_samples;
+         break;
          }
-         for (; i < AV_NUM_DATA_POINTERS; i++) {
-             buf->base[i]     = buf->data[i] = NULL;
-             buf->linesize[i] = 0;
+     default: av_assert0(0);
+     }
+     return 0;
+ fail:
+     for (i = 0; i < 4; i++)
+         av_buffer_pool_uninit(&pool->pools[i]);
+     pool->format = -1;
+     pool->planes = pool->channels = pool->samples = 0;
+     pool->width  = pool->height = 0;
+     return ret;
+ }
+ static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame)
+ {
+     FramePool *pool = avctx->internal->pool;
+     int planes = pool->planes;
+     int i;
+     frame->linesize[0] = pool->linesize[0];
+     if (planes > AV_NUM_DATA_POINTERS) {
+         frame->extended_data = av_mallocz(planes * sizeof(*frame->extended_data));
+         frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS;
+         frame->extended_buf  = av_mallocz(frame->nb_extended_buf *
+                                           sizeof(*frame->extended_buf));
+         if (!frame->extended_data || !frame->extended_buf) {
+             av_freep(&frame->extended_data);
+             av_freep(&frame->extended_buf);
+             return AVERROR(ENOMEM);
          }
-         if (size[1] && !size[2])
-             avpriv_set_systematic_pal2((uint32_t *)buf->data[1], s->pix_fmt);
-         buf->width   = s->width;
-         buf->height  = s->height;
-         buf->pix_fmt = s->pix_fmt;
+     } else
+         frame->extended_data = frame->data;
+     for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) {
+         frame->buf[i] = av_buffer_pool_get(pool->pools[0]);
+         if (!frame->buf[i])
+             goto fail;
+         frame->extended_data[i] = frame->data[i] = frame->buf[i]->data;
+     }
+     for (i = 0; i < frame->nb_extended_buf; i++) {
+         frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]);
+         if (!frame->extended_buf[i])
+             goto fail;
+         frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data;
      }
  
-     for (i = 0; i < AV_NUM_DATA_POINTERS; i++) {
-         pic->base[i]     = buf->base[i];
-         pic->data[i]     = buf->data[i];
-         pic->linesize[i] = buf->linesize[i];
+     if (avctx->debug & FF_DEBUG_BUFFERS)
+         av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame);
+     return 0;
+ fail:
+     av_frame_unref(frame);
+     return AVERROR(ENOMEM);
+ }
+ static int video_get_buffer(AVCodecContext *s, AVFrame *pic)
+ {
+     FramePool *pool = s->internal->pool;
+     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format);
+     int pixel_size = desc->comp[0].step_minus1 + 1;
+     int h_chroma_shift, v_chroma_shift;
+     int i;
+     if (pic->data[0] != NULL) {
+         av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");
+         return -1;
      }
+     memset(pic->data, 0, sizeof(pic->data));
      pic->extended_data = pic->data;
-     avci->buffer_count++;
+     av_pix_fmt_get_chroma_sub_sample(s->pix_fmt, &h_chroma_shift, &v_chroma_shift);
+     for (i = 0; i < 4 && pool->pools[i]; i++) {
+         const int h_shift = i == 0 ? 0 : h_chroma_shift;
+         const int v_shift = i == 0 ? 0 : v_chroma_shift;
+         pic->linesize[i] = pool->linesize[i];
+         pic->buf[i] = av_buffer_pool_get(pool->pools[i]);
+         if (!pic->buf[i])
+             goto fail;
+         // no edge if EDGE EMU or not planar YUV
+         if ((s->flags & CODEC_FLAG_EMU_EDGE) || !pool->pools[2])
+             pic->data[i] = pic->buf[i]->data;
+         else {
+             pic->data[i] = pic->buf[i]->data +
+                 FFALIGN((pic->linesize[i] * EDGE_WIDTH >> v_shift) +
+                         (pixel_size * EDGE_WIDTH >> h_shift), pool->stride_align[i]);
+         }
+     }
+     for (; i < AV_NUM_DATA_POINTERS; i++) {
+         pic->data[i] = NULL;
+         pic->linesize[i] = 0;
+     }
+     if (pic->data[1] && !pic->data[2])
+         avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt);
  
      if (s->debug & FF_DEBUG_BUFFERS)
-         av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d "
-                                 "buffers used\n", pic, avci->buffer_count);
+         av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic);
  
      return 0;
+ fail:
+     av_frame_unref(pic);
+     return AVERROR(ENOMEM);
  }
  
- int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
 +void avpriv_color_frame(AVFrame *frame, const int c[4])
 +{
 +    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
 +    int p, y, x;
 +
 +    av_assert0(desc->flags & PIX_FMT_PLANAR);
 +
 +    for (p = 0; p<desc->nb_components; p++) {
 +        uint8_t *dst = frame->data[p];
 +        int is_chroma = p == 1 || p == 2;
 +        int bytes = -((-frame->width) >> (is_chroma ? desc->log2_chroma_w : 0));
 +        for (y = 0; y<-((-frame->height) >> (is_chroma ? desc->log2_chroma_h : 0)); y++){
 +            if (desc->comp[0].depth_minus1 >= 8) {
 +                for (x = 0; x<bytes; x++)
 +                    ((uint16_t*)dst)[x] = c[p];
 +            }else
 +                memset(dst, c[p], bytes);
 +            dst += frame->linesize[p];
 +        }
 +    }
 +}
 +
+ int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags)
  {
+     int ret;
+     if ((ret = update_frame_pool(avctx, frame)) < 0)
+         return ret;
+ #if FF_API_GET_BUFFER
      frame->type = FF_BUFFER_TYPE_INTERNAL;
+ #endif
      switch (avctx->codec_type) {
      case AVMEDIA_TYPE_VIDEO:
          return video_get_buffer(avctx, frame);
      }
  }
  
- int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame)
 +void ff_init_buffer_info(AVCodecContext *s, AVFrame *frame)
 +{
 +    if (s->pkt) {
 +        frame->pkt_pts = s->pkt->pts;
 +        av_frame_set_pkt_pos     (frame, s->pkt->pos);
 +        av_frame_set_pkt_duration(frame, s->pkt->duration);
 +        av_frame_set_pkt_size    (frame, s->pkt->size);
 +    } else {
 +        frame->pkt_pts = AV_NOPTS_VALUE;
 +        av_frame_set_pkt_pos     (frame, -1);
 +        av_frame_set_pkt_duration(frame, 0);
 +        av_frame_set_pkt_size    (frame, -1);
 +    }
 +    frame->reordered_opaque = s->reordered_opaque;
 +
 +    switch (s->codec->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        frame->width               = s->width;
 +        frame->height              = s->height;
 +        frame->format              = s->pix_fmt;
 +        frame->sample_aspect_ratio = s->sample_aspect_ratio;
 +        break;
 +    case AVMEDIA_TYPE_AUDIO:
 +        frame->sample_rate    = s->sample_rate;
 +        frame->format         = s->sample_fmt;
 +        frame->channel_layout = s->channel_layout;
 +        av_frame_set_channels(frame, s->channels);
 +        break;
 +    }
 +}
 +
+ #if FF_API_GET_BUFFER
+ int avcodec_default_get_buffer(AVCodecContext *avctx, AVFrame *frame)
  {
-     ff_init_buffer_info(avctx, frame);
+     return avcodec_default_get_buffer2(avctx, frame, 0);
+ }
  
-     return avctx->get_buffer(avctx, frame);
+ typedef struct CompatReleaseBufPriv {
+     AVCodecContext avctx;
+     AVFrame frame;
+ } CompatReleaseBufPriv;
+ static void compat_free_buffer(void *opaque, uint8_t *data)
+ {
+     CompatReleaseBufPriv *priv = opaque;
+     priv->avctx.release_buffer(&priv->avctx, &priv->frame);
+     av_freep(&priv);
  }
  
void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)
static void compat_release_buffer(void *opaque, uint8_t *data)
  {
-     int i;
-     InternalBuffer *buf, *last;
-     AVCodecInternal *avci = s->internal;
+     AVBufferRef *buf = opaque;
+     av_buffer_unref(&buf);
+ }
+ #endif
  
-     av_assert0(s->codec_type == AVMEDIA_TYPE_VIDEO);
+ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
+ {
+     int ret;
 -    switch (avctx->codec_type) {
 -    case AVMEDIA_TYPE_VIDEO:
 -        frame->width               = avctx->width;
 -        frame->height              = avctx->height;
 -        frame->format              = avctx->pix_fmt;
 -        frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
 -
 -        if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
 -            return ret;
 -        break;
 -    case AVMEDIA_TYPE_AUDIO:
 -        frame->sample_rate    = avctx->sample_rate;
 -        frame->format         = avctx->sample_fmt;
 -        frame->channel_layout = avctx->channel_layout;
 -        break;
 -    default: return AVERROR(EINVAL);
++    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
++        if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0 || avctx->pix_fmt<0) {
++            av_log(avctx, AV_LOG_ERROR, "video_get_buffer: image parameters invalid\n");
++            return AVERROR(EINVAL);
++        }
+     }
 -
 -    frame->pkt_pts = avctx->pkt ? avctx->pkt->pts : AV_NOPTS_VALUE;
 -    frame->reordered_opaque = avctx->reordered_opaque;
++    ff_init_buffer_info(avctx, frame);
  
-     assert(pic->type == FF_BUFFER_TYPE_INTERNAL);
-     assert(avci->buffer_count);
+ #if FF_API_GET_BUFFER
+     /*
+      * Wrap an old get_buffer()-allocated buffer in an bunch of AVBuffers.
+      * We wrap each plane in its own AVBuffer. Each of those has a reference to
+      * a dummy AVBuffer as its private data, unreffing it on free.
+      * When all the planes are freed, the dummy buffer's free callback calls
+      * release_buffer().
+      */
+     if (avctx->get_buffer) {
+         CompatReleaseBufPriv *priv = NULL;
+         AVBufferRef *dummy_buf = NULL;
+         int planes, i, ret;
  
-     if (avci->buffer) {
-         buf = NULL; /* avoids warning */
-         for (i = 0; i < avci->buffer_count; i++) { //just 3-5 checks so is not worth to optimize
-             buf = &avci->buffer[i];
-             if (buf->data[0] == pic->data[0])
-                 break;
+         if (flags & AV_GET_BUFFER_FLAG_REF)
+             frame->reference    = 1;
+         ret = avctx->get_buffer(avctx, frame);
+         if (ret < 0)
+             return ret;
+         /* return if the buffers are already set up
+          * this would happen e.g. when a custom get_buffer() calls
+          * avcodec_default_get_buffer
+          */
+         if (frame->buf[0])
+             return 0;
+         priv = av_mallocz(sizeof(*priv));
+         if (!priv) {
+             ret = AVERROR(ENOMEM);
+             goto fail;
          }
-         av_assert0(i < avci->buffer_count);
-         avci->buffer_count--;
-         last = &avci->buffer[avci->buffer_count];
+         priv->avctx = *avctx;
+         priv->frame = *frame;
  
-         if (buf != last)
-             FFSWAP(InternalBuffer, *buf, *last);
-     }
+         dummy_buf = av_buffer_create(NULL, 0, compat_free_buffer, priv, 0);
+         if (!dummy_buf) {
+             ret = AVERROR(ENOMEM);
+             goto fail;
+         }
  
-     for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
-         pic->data[i] = NULL;
- //        pic->base[i]=NULL;
+ #define WRAP_PLANE(ref_out, data, data_size)                            \
+ do {                                                                    \
+     AVBufferRef *dummy_ref = av_buffer_ref(dummy_buf);                  \
+     if (!dummy_ref) {                                                   \
+         ret = AVERROR(ENOMEM);                                          \
+         goto fail;                                                      \
+     }                                                                   \
+     ref_out = av_buffer_create(data, data_size, compat_release_buffer,  \
+                                dummy_ref, 0);                           \
+     if (!ref_out) {                                                     \
+         av_frame_unref(frame);                                          \
+         ret = AVERROR(ENOMEM);                                          \
+         goto fail;                                                      \
+     }                                                                   \
+ } while (0)
+         if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
+             const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
+             if (!desc) {
+                 ret = AVERROR(EINVAL);
+                 goto fail;
+             }
+             planes = (desc->flags & PIX_FMT_PLANAR) ? desc->nb_components : 1;
  
-     if (s->debug & FF_DEBUG_BUFFERS)
-         av_log(s, AV_LOG_DEBUG, "default_release_buffer called on pic %p, %d "
-                                 "buffers used\n", pic, avci->buffer_count);
- }
+             for (i = 0; i < planes; i++) {
+                 int h_shift    = (i == 1 || i == 2) ? desc->log2_chroma_h : 0;
+                 int plane_size = (frame->width >> h_shift) * frame->linesize[i];
  
- int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
- {
-     AVFrame temp_pic;
-     int i, ret;
+                 WRAP_PLANE(frame->buf[i], frame->data[i], plane_size);
+             }
+         } else {
+             int planar = av_sample_fmt_is_planar(frame->format);
+             planes = planar ? avctx->channels : 1;
+             if (planes > FF_ARRAY_ELEMS(frame->buf)) {
+                 frame->nb_extended_buf = planes - FF_ARRAY_ELEMS(frame->buf);
+                 frame->extended_buf = av_malloc(sizeof(*frame->extended_buf) *
+                                                 frame->nb_extended_buf);
+                 if (!frame->extended_buf) {
+                     ret = AVERROR(ENOMEM);
+                     goto fail;
+                 }
+             }
  
-     av_assert0(s->codec_type == AVMEDIA_TYPE_VIDEO);
+             for (i = 0; i < FFMIN(planes, FF_ARRAY_ELEMS(frame->buf)); i++)
+                 WRAP_PLANE(frame->buf[i], frame->extended_data[i], frame->linesize[0]);
  
-     if (pic->data[0] && (pic->width != s->width || pic->height != s->height || pic->format != s->pix_fmt)) {
-         av_log(s, AV_LOG_WARNING, "Picture changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s in reget buffer()\n",
-                pic->width, pic->height, av_get_pix_fmt_name(pic->format), s->width, s->height, av_get_pix_fmt_name(s->pix_fmt));
-         s->release_buffer(s, pic);
+             for (i = 0; i < planes - FF_ARRAY_ELEMS(frame->buf); i++)
+                 WRAP_PLANE(frame->extended_buf[i],
+                            frame->extended_data[i + FF_ARRAY_ELEMS(frame->buf)],
+                            frame->linesize[0]);
+         }
+         av_buffer_unref(&dummy_buf);
+         return 0;
+ fail:
+         avctx->release_buffer(avctx, frame);
+         av_freep(&priv);
+         av_buffer_unref(&dummy_buf);
+         return ret;
      }
+ #endif
+     return avctx->get_buffer2(avctx, frame, flags);
+ }
+ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
+ {
+     AVFrame tmp;
+     int ret;
  
-     ff_init_buffer_info(s, pic);
+     av_assert0(avctx->codec_type == AVMEDIA_TYPE_VIDEO);
  
-     /* If no picture return a new buffer */
-     if (pic->data[0] == NULL) {
-         /* We will copy from buffer, so must be readable */
-         pic->buffer_hints |= FF_BUFFER_HINTS_READABLE;
-         return ff_get_buffer(s, pic);
++    if (frame->data[0] && (frame->width != avctx->width || frame->height != avctx->height || frame->format != avctx->pix_fmt)) {
++        av_log(avctx, AV_LOG_WARNING, "Picture changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s in reget buffer()\n",
++               frame->width, frame->height, av_get_pix_fmt_name(frame->format), avctx->width, avctx->height, av_get_pix_fmt_name(avctx->pix_fmt));
++        av_frame_unref(frame);
 +    }
 +
-     assert(s->pix_fmt == pic->format);
++    ff_init_buffer_info(avctx, frame);
 +
-     /* If internal buffer type return the same buffer */
-     if (pic->type == FF_BUFFER_TYPE_INTERNAL) {
+     if (!frame->data[0])
+         return ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
+     if (av_frame_is_writable(frame))
          return 0;
-     }
  
-     /*
-      * Not internal type and reget_buffer not overridden, emulate cr buffer
-      */
-     temp_pic = *pic;
-     for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
-         pic->data[i] = pic->base[i] = NULL;
-     pic->opaque = NULL;
-     /* Allocate new frame */
-     if ((ret = ff_get_buffer(s, pic)))
+     av_frame_move_ref(&tmp, frame);
+     ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
+     if (ret < 0) {
+         av_frame_unref(&tmp);
          return ret;
-     /* Copy image data from old buffer to new buffer */
-     av_picture_copy((AVPicture *)pic, (AVPicture *)&temp_pic, s->pix_fmt, s->width,
-                     s->height);
-     s->release_buffer(s, &temp_pic); // Release old frame
+     }
+     av_image_copy(frame->data, frame->linesize, tmp.data, tmp.linesize,
+                   frame->format, frame->width, frame->height);
+     av_frame_unref(&tmp);
      return 0;
  }
  
+ #if FF_API_GET_BUFFER
+ void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic)
+ {
++    av_assert0(s->codec_type == AVMEDIA_TYPE_VIDEO);
++
+     av_frame_unref(pic);
+ }
+ int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic)
+ {
+     av_assert0(0);
+ }
+ #endif
  int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size)
  {
      int i;
@@@ -1641,43 -1437,12 +1811,44 @@@ static void apply_param_change(AVCodecC
      }
  }
  
 +static int add_metadata_from_side_data(AVCodecContext *avctx, AVFrame *frame)
 +{
 +    int size, ret = 0;
 +    const uint8_t *side_metadata;
 +    const uint8_t *end;
 +
 +    av_dict_free(&avctx->metadata);
 +    side_metadata = av_packet_get_side_data(avctx->pkt,
 +                                            AV_PKT_DATA_STRINGS_METADATA, &size);
 +    if (!side_metadata)
 +        goto end;
 +    end = side_metadata + size;
 +    while (side_metadata < end) {
 +        const uint8_t *key = side_metadata;
 +        const uint8_t *val = side_metadata + strlen(key) + 1;
 +        int ret = av_dict_set(avpriv_frame_get_metadatap(frame), key, val, 0);
 +        if (ret < 0)
 +            break;
 +        side_metadata = val + strlen(val) + 1;
 +    }
 +end:
 +    avctx->metadata = av_frame_get_metadata(frame);
 +    return ret;
 +}
 +
  int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                                                int *got_picture_ptr,
 -                                              AVPacket *avpkt)
 +                                              const AVPacket *avpkt)
  {
+     AVCodecInternal *avci = avctx->internal;
      int ret;
 +    // copy to ensure we do not change avpkt
 +    AVPacket tmp = *avpkt;
 +
 +    if (avctx->codec->type != AVMEDIA_TYPE_VIDEO) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid media type for video\n");
 +        return AVERROR(EINVAL);
 +    }
  
      *got_picture_ptr = 0;
      if ((avctx->coded_width || avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
  
      avcodec_get_frame_defaults(picture);
  
+     if (!avctx->refcounted_frames)
+         av_frame_unref(&avci->to_free);
      if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type & FF_THREAD_FRAME)) {
 +        int did_split = av_packet_split_side_data(&tmp);
 +        apply_param_change(avctx, &tmp);
 +        avctx->pkt = &tmp;
          if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
              ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
 -                                         avpkt);
 +                                         &tmp);
          else {
              ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
 -                                       avpkt);
 +                                       &tmp);
              picture->pkt_dts = avpkt->dts;
 +
 +            if(!avctx->has_b_frames){
 +                av_frame_set_pkt_pos(picture, avpkt->pos);
 +            }
 +            //FIXME these should be under if(!avctx->has_b_frames)
              /* get_buffer is supposed to set frame parameters */
              if (!(avctx->codec->capabilities & CODEC_CAP_DR1)) {
 -                picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
 -                picture->width               = avctx->width;
 -                picture->height              = avctx->height;
 -                picture->format              = avctx->pix_fmt;
 +                if (!picture->sample_aspect_ratio.num)    picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
 +                if (!picture->width)                      picture->width               = avctx->width;
 +                if (!picture->height)                     picture->height              = avctx->height;
 +                if (picture->format == AV_PIX_FMT_NONE)   picture->format              = avctx->pix_fmt;
              }
          }
 +        add_metadata_from_side_data(avctx, picture);
  
          emms_c(); //needed to avoid an emms_c() call before every return;
  
-         if (*got_picture_ptr){
 +        avctx->pkt = NULL;
 +        if (did_split) {
 +            ff_packet_free_side_data(&tmp);
 +            if(ret == tmp.size)
 +                ret = avpkt->size;
 +        }
 +
+         if (ret < 0 && picture->data[0])
+             av_frame_unref(picture);
+         if (*got_picture_ptr) {
+             if (!avctx->refcounted_frames) {
+                 avci->to_free = *picture;
+                 avci->to_free.extended_data = avci->to_free.data;
+             }
              avctx->frame_number++;
 +            av_frame_set_best_effort_timestamp(picture,
 +                                               guess_correct_pts(avctx,
 +                                                                 picture->pkt_pts,
 +                                                                 picture->pkt_dts));
          }
      } else
          ret = 0;
@@@ -1789,8 -1547,9 +1971,9 @@@ int attribute_align_arg avcodec_decode_
  int attribute_align_arg avcodec_decode_audio4(AVCodecContext *avctx,
                                                AVFrame *frame,
                                                int *got_frame_ptr,
 -                                              AVPacket *avpkt)
 +                                              const AVPacket *avpkt)
  {
+     AVCodecInternal *avci = avctx->internal;
      int planar, channels;
      int ret = 0;
  
  
      avcodec_get_frame_defaults(frame);
  
+     if (!avctx->refcounted_frames)
+         av_frame_unref(&avci->to_free);
      if ((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size) {
 -        ret = avctx->codec->decode(avctx, frame, got_frame_ptr, avpkt);
 +        uint8_t *side;
 +        int side_size;
 +        // copy to ensure we do not change avpkt
 +        AVPacket tmp = *avpkt;
 +        int did_split = av_packet_split_side_data(&tmp);
 +        apply_param_change(avctx, &tmp);
 +
 +        avctx->pkt = &tmp;
 +        ret = avctx->codec->decode(avctx, frame, got_frame_ptr, &tmp);
          if (ret >= 0 && *got_frame_ptr) {
              avctx->frame_number++;
              frame->pkt_dts = avpkt->dts;
 +            av_frame_set_best_effort_timestamp(frame,
 +                                               guess_correct_pts(avctx,
 +                                                                 frame->pkt_pts,
 +                                                                 frame->pkt_dts));
              if (frame->format == AV_SAMPLE_FMT_NONE)
                  frame->format = avctx->sample_fmt;
 -
 +            if (!frame->channel_layout)
 +                frame->channel_layout = avctx->channel_layout;
 +            if (!av_frame_get_channels(frame))
 +                av_frame_set_channels(frame, avctx->channels);
 +            if (!frame->sample_rate)
 +                frame->sample_rate = avctx->sample_rate;
+             if (!avctx->refcounted_frames) {
+                 avci->to_free = *frame;
+                 avci->to_free.extended_data = avci->to_free.data;
+             }
          }
 +        add_metadata_from_side_data(avctx, frame);
 +
 +        side= av_packet_get_side_data(avctx->pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
 +        if(side && side_size>=10) {
 +            avctx->internal->skip_samples = AV_RL32(side);
 +            av_log(avctx, AV_LOG_DEBUG, "skip %d samples due to side data\n",
 +                   avctx->internal->skip_samples);
 +        }
 +        if (avctx->internal->skip_samples && *got_frame_ptr) {
 +            if(frame->nb_samples <= avctx->internal->skip_samples){
 +                *got_frame_ptr = 0;
 +                avctx->internal->skip_samples -= frame->nb_samples;
 +                av_log(avctx, AV_LOG_DEBUG, "skip whole frame, skip left: %d\n",
 +                       avctx->internal->skip_samples);
 +            } else {
 +                av_samples_copy(frame->extended_data, frame->extended_data, 0, avctx->internal->skip_samples,
 +                                frame->nb_samples - avctx->internal->skip_samples, avctx->channels, frame->format);
 +                if(avctx->pkt_timebase.num && avctx->sample_rate) {
 +                    int64_t diff_ts = av_rescale_q(avctx->internal->skip_samples,
 +                                                   (AVRational){1, avctx->sample_rate},
 +                                                   avctx->pkt_timebase);
 +                    if(frame->pkt_pts!=AV_NOPTS_VALUE)
 +                        frame->pkt_pts += diff_ts;
 +                    if(frame->pkt_dts!=AV_NOPTS_VALUE)
 +                        frame->pkt_dts += diff_ts;
 +                    if (av_frame_get_pkt_duration(frame) >= diff_ts)
 +                        av_frame_set_pkt_duration(frame, av_frame_get_pkt_duration(frame) - diff_ts);
 +                } else {
 +                    av_log(avctx, AV_LOG_WARNING, "Could not update timestamps for skipped samples.\n");
 +                }
 +                av_log(avctx, AV_LOG_DEBUG, "skip %d/%d samples\n",
 +                       avctx->internal->skip_samples, frame->nb_samples);
 +                frame->nb_samples -= avctx->internal->skip_samples;
 +                avctx->internal->skip_samples = 0;
 +            }
 +        }
 +
 +        avctx->pkt = NULL;
 +        if (did_split) {
 +            ff_packet_free_side_data(&tmp);
 +            if(ret == tmp.size)
 +                ret = avpkt->size;
 +        }
+         if (ret < 0 && frame->data[0])
+             av_frame_unref(frame);
      }
  
      /* many decoders assign whole AVFrames, thus overwriting extended_data;
@@@ -2021,40 -1631,35 +2214,46 @@@ void avsubtitle_free(AVSubtitle *sub
      memset(sub, 0, sizeof(AVSubtitle));
  }
  
 -av_cold int avcodec_close(AVCodecContext *avctx)
 +av_cold int ff_codec_close_recursive(AVCodecContext *avctx)
  {
 -    /* If there is a user-supplied mutex locking routine, call it. */
 -    if (ff_lockmgr_cb) {
 -        if ((*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_OBTAIN))
 -            return -1;
 -    }
 +    int ret = 0;
  
 -    entangled_thread_counter++;
 -    if (entangled_thread_counter != 1) {
 -        av_log(avctx, AV_LOG_ERROR, "insufficient thread locking around avcodec_open/close()\n");
 -        entangled_thread_counter--;
 -        return -1;
 -    }
 +    ff_unlock_avcodec();
 +
 +    ret = avcodec_close(avctx);
 +
 +    ff_lock_avcodec(NULL);
 +    return ret;
 +}
 +
 +av_cold int avcodec_close(AVCodecContext *avctx)
 +{
 +    int ret = ff_lock_avcodec(avctx);
 +    if (ret < 0)
 +        return ret;
  
      if (avcodec_is_open(avctx)) {
+         FramePool *pool = avctx->internal->pool;
+         int i;
 +        if (HAVE_THREADS && avctx->internal->frame_thread_encoder && avctx->thread_count > 1) {
 +            ff_unlock_avcodec();
 +            ff_frame_thread_encoder_free(avctx);
 +            ff_lock_avcodec(avctx);
 +        }
          if (HAVE_THREADS && avctx->thread_opaque)
              ff_thread_free(avctx);
          if (avctx->codec && avctx->codec->close)
              avctx->codec->close(avctx);
-         avcodec_default_free_buffers(avctx);
          avctx->coded_frame = NULL;
 +        avctx->internal->byte_buffer_size = 0;
 +        av_freep(&avctx->internal->byte_buffer);
+         if (!avctx->refcounted_frames)
+             av_frame_unref(&avctx->internal->to_free);
+         for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++)
+             av_buffer_pool_uninit(&pool->pools[i]);
+         av_freep(&avctx->internal->pool);
          av_freep(&avctx->internal);
 +        av_dict_free(&avctx->metadata);
      }
  
      if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
@@@ -2331,54 -1930,8 +2530,11 @@@ void avcodec_flush_buffers(AVCodecConte
          ff_thread_flush(avctx);
      else if (avctx->codec->flush)
          avctx->codec->flush(avctx);
 +
 +    avctx->pts_correction_last_pts =
 +    avctx->pts_correction_last_dts = INT64_MIN;
  }
  
- static void video_free_buffers(AVCodecContext *s)
- {
-     AVCodecInternal *avci = s->internal;
-     int i, j;
-     if (!avci->buffer)
-         return;
-     if (avci->buffer_count)
-         av_log(s, AV_LOG_WARNING, "Found %i unreleased buffers!\n",
-                avci->buffer_count);
-     for (i = 0; i < INTERNAL_BUFFER_SIZE; i++) {
-         InternalBuffer *buf = &avci->buffer[i];
-         for (j = 0; j < 4; j++) {
-             av_freep(&buf->base[j]);
-             buf->data[j] = NULL;
-         }
-     }
-     av_freep(&avci->buffer);
-     avci->buffer_count = 0;
- }
- static void audio_free_buffers(AVCodecContext *avctx)
- {
-     AVCodecInternal *avci = avctx->internal;
-     av_freep(&avci->audio_data);
- }
- void avcodec_default_free_buffers(AVCodecContext *avctx)
- {
-     switch (avctx->codec_type) {
-     case AVMEDIA_TYPE_VIDEO:
-         video_free_buffers(avctx);
-         break;
-     case AVMEDIA_TYPE_AUDIO:
-         audio_free_buffers(avctx);
-         break;
-     default:
-         break;
-     }
- }
  int av_get_exact_bits_per_sample(enum AVCodecID codec_id)
  {
      switch (codec_id) {
@@@ -2784,29 -2267,47 +2940,48 @@@ unsigned int avpriv_toupper4(unsigned i
            (av_toupper((x >> 24) & 0xFF) << 24);
  }
  
+ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src)
+ {
+     int ret;
+     dst->owner = src->owner;
+     ret = av_frame_ref(dst->f, src->f);
+     if (ret < 0)
+         return ret;
+     if (src->progress &&
+         !(dst->progress = av_buffer_ref(src->progress))) {
+         ff_thread_release_buffer(dst->owner, dst);
+         return AVERROR(ENOMEM);
+     }
+     return 0;
+ }
  #if !HAVE_THREADS
  
- int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f)
 -int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags)
++int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
  {
      f->owner = avctx;
 -    return ff_get_buffer(avctx, f, flags);
 +
-     return ff_get_buffer(avctx, f);
++    return ff_get_buffer(avctx, f->f, flags);
  }
  
--void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f)
++void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f)
  {
-     f->owner->release_buffer(f->owner, f);
 -    av_frame_unref(f);
++    av_frame_unref(f->f);
  }
  
  void ff_thread_finish_setup(AVCodecContext *avctx)
  {
  }
  
--void ff_thread_report_progress(AVFrame *f, int progress, int field)
++void ff_thread_report_progress(ThreadFrame *f, int progress, int field)
  {
  }
  
--void ff_thread_await_progress(AVFrame *f, int progress, int field)
++void ff_thread_await_progress(ThreadFrame *f, int progress, int field)
  {
  }
  
Simple merge
Simple merge
@@@ -60,59 -36,25 +60,51 @@@ static av_cold int decode_init(AVCodecC
      avctx->pix_fmt             = AV_PIX_FMT_YUV422P10;
      avctx->bits_per_raw_sample = 10;
  
-     avctx->coded_frame         = avcodec_alloc_frame();
-     if (!avctx->coded_frame)
-         return AVERROR(ENOMEM);
 +    s->unpack_frame            = v210_planar_unpack_c;
 +
 +    if (HAVE_MMX)
 +        v210_x86_init(s);
 +
      return 0;
  }
  
  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                          AVPacket *avpkt)
  {
 -    int h, w, ret;
 +    V210DecContext *s = avctx->priv_data;
 +
 +    int h, w, ret, stride, aligned_input;
-     AVFrame *pic = avctx->coded_frame;
+     AVFrame *pic = data;
      const uint8_t *psrc = avpkt->data;
      uint16_t *y, *u, *v;
 -    int aligned_width = ((avctx->width + 47) / 48) * 48;
 -    int stride = aligned_width * 8 / 3;
 +
 +    if (s->custom_stride )
 +        stride = s->custom_stride;
 +    else {
 +        int aligned_width = ((avctx->width + 47) / 48) * 48;
 +        stride = aligned_width * 8 / 3;
 +    }
  
      if (avpkt->size < stride * avctx->height) {
 -        av_log(avctx, AV_LOG_ERROR, "packet too small\n");
 -        return AVERROR_INVALIDDATA;
 +        if ((((avctx->width + 23) / 24) * 24 * 8) / 3 * avctx->height == avpkt->size) {
 +            stride = avpkt->size / avctx->height;
 +            if (!s->stride_warning_shown)
 +                av_log(avctx, AV_LOG_WARNING, "Broken v210 with too small padding (64 byte) detected\n");
 +            s->stride_warning_shown = 1;
 +        } else {
 +            av_log(avctx, AV_LOG_ERROR, "packet too small\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +    }
 +
 +    aligned_input = !((uintptr_t)psrc & 0xf) && !(stride & 0xf);
 +    if (aligned_input != s->aligned_input) {
 +        s->aligned_input = aligned_input;
 +        if (HAVE_MMX)
 +            v210_x86_init(s);
      }
  
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
-     pic->reference = 0;
-     if ((ret = ff_get_buffer(avctx, pic)) < 0)
+     if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
          return ret;
  
      y = (uint16_t*)pic->data[0];
      return avpkt->size;
  }
  
- static av_cold int decode_close(AVCodecContext *avctx)
- {
-     AVFrame *pic = avctx->coded_frame;
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
-     av_freep(&avctx->coded_frame);
-     return 0;
- }
 +#define V210DEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
 +static const AVOption v210dec_options[] = {
 +    {"custom_stride", "Custom V210 stride", offsetof(V210DecContext, custom_stride), FF_OPT_TYPE_INT,
 +     {.i64 = 0}, INT_MIN, INT_MAX, V210DEC_FLAGS},
 +    {NULL}
 +};
 +
 +static const AVClass v210dec_class = {
 +    "V210 Decoder",
 +    av_default_item_name,
 +    v210dec_options,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
  AVCodec ff_v210_decoder = {
      .name           = "v210",
      .type           = AVMEDIA_TYPE_VIDEO,
      .id             = AV_CODEC_ID_V210,
 +    .priv_data_size = sizeof(V210DecContext),
      .init           = decode_init,
-     .close          = decode_close,
      .decode         = decode_frame,
      .capabilities   = CODEC_CAP_DR1,
      .long_name      = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"),
Simple merge
index b5567f8,0000000..a85d655
mode 100644,000000..100644
--- /dev/null
@@@ -1,109 -1,0 +1,93 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame) {
-         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-         return AVERROR(ENOMEM);
-     }
 +/*
 + * v308 decoder
 + * Copyright (c) 2011 Carl Eugen Hoyos
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +
 +static av_cold int v308_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt = AV_PIX_FMT_YUV444P;
 +
 +    if (avctx->width & 1)
 +        av_log(avctx, AV_LOG_WARNING, "v308 requires width to be even.\n");
 +
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int v308_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame, AVPacket *avpkt)
 +{
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    const uint8_t *src = avpkt->data;
 +    uint8_t *y, *u, *v;
 +    int i, j;
 +
-     pic->reference = 0;
-     if (ff_get_buffer(avctx, pic) < 0) {
 +    if (avpkt->size < 3 * avctx->height * avctx->width) {
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
++    if (ff_get_buffer(avctx, pic, 0) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    pic->key_frame = 1;
 +    pic->pict_type = AV_PICTURE_TYPE_I;
 +
 +    y = pic->data[0];
 +    u = pic->data[1];
 +    v = pic->data[2];
 +
 +    for (i = 0; i < avctx->height; i++) {
 +        for (j = 0; j < avctx->width; j++) {
 +            v[j] = *src++;
 +            y[j] = *src++;
 +            u[j] = *src++;
 +        }
 +
 +        y += pic->linesize[0];
 +        u += pic->linesize[1];
 +        v += pic->linesize[2];
 +    }
 +
 +    *got_frame = 1;
 +    *(AVFrame *)data = *pic;
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int v308_decode_close(AVCodecContext *avctx)
 +{
 +
 +    return 0;
 +}
 +
 +AVCodec ff_v308_decoder = {
 +    .name         = "v308",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_V308,
 +    .init         = v308_decode_init,
 +    .decode       = v308_decode_frame,
 +    .close        = v308_decode_close,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"),
 +};
index 470853d,0000000..b295d4a
mode 100644,000000..100644
--- /dev/null
@@@ -1,130 -1,0 +1,113 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame) {
-         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-         return AVERROR(ENOMEM);
-     }
 +/*
 + * v408 decoder
 + * Copyright (c) 2012 Carl Eugen Hoyos
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +
 +static av_cold int v408_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt = AV_PIX_FMT_YUVA444P;
 +
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int v408_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame, AVPacket *avpkt)
 +{
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    const uint8_t *src = avpkt->data;
 +    uint8_t *y, *u, *v, *a;
 +    int i, j;
 +
-     pic->reference = 0;
-     if (ff_get_buffer(avctx, pic) < 0) {
 +    if (avpkt->size < 4 * avctx->height * avctx->width) {
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     *(AVFrame *)data = *pic;
++    if (ff_get_buffer(avctx, pic, 0) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    pic->key_frame = 1;
 +    pic->pict_type = AV_PICTURE_TYPE_I;
 +
 +    y = pic->data[0];
 +    u = pic->data[1];
 +    v = pic->data[2];
 +    a = pic->data[3];
 +
 +    for (i = 0; i < avctx->height; i++) {
 +        for (j = 0; j < avctx->width; j++) {
 +            if (avctx->codec_id==AV_CODEC_ID_AYUV) {
 +                v[j] = *src++;
 +                u[j] = *src++;
 +                y[j] = *src++;
 +                a[j] = *src++;
 +            } else {
 +                u[j] = *src++;
 +                y[j] = *src++;
 +                v[j] = *src++;
 +                a[j] = *src++;
 +            }
 +        }
 +
 +        y += pic->linesize[0];
 +        u += pic->linesize[1];
 +        v += pic->linesize[2];
 +        a += pic->linesize[3];
 +    }
 +
 +    *got_frame = 1;
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int v408_decode_close(AVCodecContext *avctx)
 +{
 +
 +    return 0;
 +}
 +
 +#if CONFIG_AYUV_DECODER
 +AVCodec ff_ayuv_decoder = {
 +    .name         = "ayuv",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_AYUV,
 +    .init         = v408_decode_init,
 +    .decode       = v408_decode_frame,
 +    .close        = v408_decode_close,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"),
 +};
 +#endif
 +#if CONFIG_V408_DECODER
 +AVCodec ff_v408_decoder = {
 +    .name         = "v408",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_V408,
 +    .init         = v408_decode_init,
 +    .decode       = v408_decode_frame,
 +    .close        = v408_decode_close,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"),
 +};
 +#endif
Simple merge
Simple merge
diff --cc libavcodec/vb.c
Simple merge
@@@ -80,10 -84,10 +80,10 @@@ static int vble_unpack(VBLEContext *ctx
      return 0;
  }
  
- static void vble_restore_plane(VBLEContext *ctx, GetBitContext *gb, int plane,
+ static void vble_restore_plane(VBLEContext *ctx, AVFrame *pic,
 -                               int plane, int offset,
 -                               int width, int height)
++                               GetBitContext *gb, int plane,
 +                               int offset, int width, int height)
  {
-     AVFrame *pic = ctx->avctx->coded_frame;
      uint8_t *dst = pic->data[plane];
      uint8_t *val = ctx->val + offset;
      int stride = pic->linesize[plane];
@@@ -122,19 -123,8 +122,13 @@@ static int vble_decode_frame(AVCodecCon
      int offset = 0;
      int width_uv = avctx->width / 2, height_uv = avctx->height / 2;
  
-     pic->reference = 0;
-     /* Clear buffer if need be */
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
 +    if (avpkt->size < 4 || avpkt->size - 4 > INT_MAX/8) {
 +        av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      /* Allocate buffer */
-     if (ff_get_buffer(avctx, pic) < 0) {
+     if (ff_get_buffer(avctx, pic, 0) < 0) {
          av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
          return AVERROR(ENOMEM);
      }
      }
  
      /* Restore planes. Should be almost identical to Huffyuv's. */
-     vble_restore_plane(ctx, &gb, 0, offset, avctx->width, avctx->height);
 -    vble_restore_plane(ctx, pic, 0, offset, avctx->width, avctx->height);
++    vble_restore_plane(ctx, pic, &gb, 0, offset, avctx->width, avctx->height);
  
      /* Chroma */
      if (!(ctx->avctx->flags & CODEC_FLAG_GRAY)) {
          offset += avctx->width * avctx->height;
-         vble_restore_plane(ctx, &gb, 1, offset, width_uv, height_uv);
 -        vble_restore_plane(ctx, pic, 1, offset, width_uv, height_uv);
++        vble_restore_plane(ctx, pic, &gb, 1, offset, width_uv, height_uv);
  
          offset += width_uv * height_uv;
-         vble_restore_plane(ctx, &gb, 2, offset, width_uv, height_uv);
 -        vble_restore_plane(ctx, pic, 2, offset, width_uv, height_uv);
++        vble_restore_plane(ctx, pic, &gb, 2, offset, width_uv, height_uv);
      }
  
      *got_frame       = 1;
@@@ -618,11 -603,9 +618,11 @@@ static void vc1_mc_4mv_luma(VC1Context 
              tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2;
              ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2;
              break;
 +        default:
 +            av_assert2(0);
          }
-         s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx;
-         s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty;
+         s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx;
+         s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty;
          for (k = 0; k < 4; k++)
              v->mv_f[1][s->block_index[k] + v->blocks_off] = f;
      }
@@@ -34,26 -33,10 +33,14 @@@ typedef struct VCR1Context 
      int offset[4];
  } VCR1Context;
  
- static av_cold int vcr1_common_init(AVCodecContext *avctx)
- {
-     VCR1Context *const a = avctx->priv_data;
-     avctx->coded_frame = &a->picture;
-     avcodec_get_frame_defaults(&a->picture);
-     return 0;
- }
  static av_cold int vcr1_decode_init(AVCodecContext *avctx)
  {
-     vcr1_common_init(avctx);
      avctx->pix_fmt = AV_PIX_FMT_YUV410P;
  
 +    if (avctx->width % 8 || avctx->height%4) {
 +        av_log_ask_for_sample(avctx, "odd dimensions are not supported\n");
 +        return AVERROR_PATCHWELCOME;
 +    }
      return 0;
  }
  
@@@ -78,16 -50,7 +54,12 @@@ static int vcr1_decode_frame(AVCodecCon
      const uint8_t *bytestream = buf;
      int i, x, y, ret;
  
-     if (p->data[0])
-         avctx->release_buffer(avctx, p);
 +    if(buf_size < 16 + avctx->height + avctx->width*avctx->height*5/8){
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     p->reference = 0;
-     if ((ret = ff_get_buffer(avctx, p)) < 0) {
+     if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
Simple merge
Simple merge
Simple merge
index 604e0ce,0000000..658c6ce
mode 100644,000000..100644
--- /dev/null
@@@ -1,235 -1,0 +1,235 @@@
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
 +/*
 + * LucasArts VIMA decoder
 + * Copyright (c) 2012 Paul B Mahol
 + *
 + * 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/channel_layout.h"
 +#include "avcodec.h"
 +#include "get_bits.h"
 +#include "internal.h"
 +#include "adpcm_data.h"
 +
 +typedef struct {
 +    uint16_t    predict_table[5786 * 2];
 +} VimaContext;
 +
 +static const uint8_t size_table[] =
 +{
 +    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 +    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 +    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 +    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
 +};
 +
 +static const int8_t index_table1[] =
 +{
 +    -1, 4, -1, 4
 +};
 +
 +static const int8_t index_table2[] =
 +{
 +    -1, -1, 2, 6, -1, -1, 2, 6
 +};
 +
 +static const int8_t index_table3[] =
 +{
 +    -1, -1, -1, -1, 1, 2, 4, 6,
 +    -1, -1, -1, -1, 1, 2, 4, 6
 +};
 +
 +static const int8_t index_table4[] =
 +{
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +     1,  1,  1,  2,  2,  4,  5,  6,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +     1,  1,  1,  2,  2,  4,  5,  6
 +};
 +
 +static const int8_t index_table5[] =
 +{
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +     1,  1,  1,  1,  1,  2,  2,  2,
 +     2,  4,  4,  4,  5,  5,  6,  6,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +     1,  1,  1,  1,  1,  2,  2,  2,
 +     2,  4,  4,  4,  5,  5,  6,  6
 +};
 +
 +static const int8_t index_table6[] =
 +{
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +     1,  1,  1,  1,  1,  1,  1,  1,
 +     1,  1,  2,  2,  2,  2,  2,  2,
 +     2,  2,  4,  4,  4,  4,  4,  4,
 +     5,  5,  5,  5,  6,  6,  6,  6,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +    -1, -1, -1, -1, -1, -1, -1, -1,
 +     1,  1,  1,  1,  1,  1,  1,  1,
 +     1,  1,  2,  2,  2,  2,  2,  2,
 +     2,  2,  4,  4,  4,  4,  4,  4,
 +     5,  5,  5,  5,  6,  6,  6,  6
 +};
 +
 +static const int8_t* const step_index_tables[] =
 +{
 +    index_table1, index_table2, index_table3,
 +    index_table4, index_table5, index_table6
 +};
 +
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
 +    VimaContext *vima = avctx->priv_data;
 +    int         start_pos;
 +
 +    for (start_pos = 0; start_pos < 64; start_pos++) {
 +        unsigned int dest_pos, table_pos;
 +
 +        for (table_pos = 0, dest_pos = start_pos;
 +             table_pos < FF_ARRAY_ELEMS(ff_adpcm_step_table);
 +             table_pos++, dest_pos += 64) {
 +            int put = 0, count, table_value;
 +
 +            table_value = ff_adpcm_step_table[table_pos];
 +            for (count = 32; count != 0; count >>= 1) {
 +                if (start_pos & count)
 +                    put += table_value;
 +                table_value >>= 1;
 +            }
 +            vima->predict_table[dest_pos] = put;
 +        }
 +    }
 +
 +    avctx->sample_fmt  = AV_SAMPLE_FMT_S16;
 +
 +    return 0;
 +}
 +
 +static int decode_frame(AVCodecContext *avctx, void *data,
 +                        int *got_frame_ptr, AVPacket *pkt)
 +{
 +    GetBitContext  gb;
 +    VimaContext    *vima = avctx->priv_data;
 +    AVFrame        *frame = data;
 +    int16_t        pcm_data[2];
 +    uint32_t       samples;
 +    int8_t         channel_hint[2];
 +    int            ret, chan, channels = 1;
 +
 +    if (pkt->size < 13)
 +        return AVERROR_INVALIDDATA;
 +
 +    if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0)
 +        return ret;
 +
 +    samples = get_bits_long(&gb, 32);
 +    if (samples == 0xffffffff) {
 +        skip_bits_long(&gb, 32);
 +        samples = get_bits_long(&gb, 32);
 +    }
 +
 +    if (samples > pkt->size * 2)
 +        return AVERROR_INVALIDDATA;
 +
 +    channel_hint[0] = get_sbits(&gb, 8);
 +    if (channel_hint[0] & 0x80) {
 +        channel_hint[0] = ~channel_hint[0];
 +        channels = 2;
 +    }
 +    avctx->channels = channels;
 +    avctx->channel_layout = (channels == 2) ? AV_CH_LAYOUT_STEREO :
 +                                              AV_CH_LAYOUT_MONO;
 +    pcm_data[0] = get_sbits(&gb, 16);
 +    if (channels > 1) {
 +        channel_hint[1] = get_sbits(&gb, 8);
 +        pcm_data[1] = get_sbits(&gb, 16);
 +    }
 +
 +    frame->nb_samples = samples;
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +
 +    for (chan = 0; chan < channels; chan++) {
 +        uint16_t *dest = (uint16_t*)frame->data[0] + chan;
 +        int step_index = channel_hint[chan];
 +        int output = pcm_data[chan];
 +        int sample;
 +
 +        for (sample = 0; sample < samples; sample++) {
 +            int lookup_size, lookup, highbit, lowbits;
 +
 +            step_index  = av_clip(step_index, 0, 88);
 +            lookup_size = size_table[step_index];
 +            lookup      = get_bits(&gb, lookup_size);
 +            highbit     = 1 << (lookup_size - 1);
 +            lowbits     = highbit - 1;
 +
 +            if (lookup & highbit)
 +                lookup ^= highbit;
 +            else
 +                highbit = 0;
 +
 +            if (lookup == lowbits) {
 +                output = get_sbits(&gb, 16);
 +            } else {
 +                int predict_index, diff;
 +
 +                predict_index = (lookup << (7 - lookup_size)) | (step_index << 6);
 +                predict_index = av_clip(predict_index, 0, 5785);
 +                diff          = vima->predict_table[predict_index];
 +                if (lookup)
 +                    diff += ff_adpcm_step_table[step_index] >> (lookup_size - 1);
 +                if (highbit)
 +                    diff  = -diff;
 +
 +                output  = av_clip_int16(output + diff);
 +            }
 +
 +            *dest = output;
 +            dest += channels;
 +
 +            step_index += step_index_tables[lookup_size - 2][lookup];
 +        }
 +    }
 +
 +    *got_frame_ptr   = 1;
 +
 +    return pkt->size;
 +}
 +
 +AVCodec ff_vima_decoder = {
 +    .name           = "vima",
 +    .type           = AVMEDIA_TYPE_AUDIO,
 +    .id             = AV_CODEC_ID_VIMA,
 +    .priv_data_size = sizeof(VimaContext),
 +    .init           = decode_init,
 +    .decode         = decode_frame,
 +    .capabilities   = CODEC_CAP_DR1,
 +    .long_name      = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"),
 +};
@@@ -267,23 -268,26 +266,23 @@@ static void vmd_decode(VmdVideoContext 
              r = *p++ * 4;
              g = *p++ * 4;
              b = *p++ * 4;
 -            palette32[i] = (r << 16) | (g << 8) | (b);
 +            palette32[i] = 0xFFU << 24 | r << 16 | g << 8 | b;
 +            palette32[i] |= palette32[i] >> 6 & 0x30303;
          }
 -        s->size -= (256 * 3 + 2);
      }
 -    if (s->size > 0) {
 +    if (p < p_end) {
          /* originally UnpackFrame in VAG's code */
          pb = p;
 -        pb_size = s->buf + s->size - pb;
 -        if (pb_size < 1)
 -            return;
 -        meth = *pb++; pb_size--;
 +        pb_end = p_end;
 +        meth = *pb++;
          if (meth & 0x80) {
 -            lz_unpack(pb, pb_size,
 -                      s->unpack_buffer, s->unpack_buffer_size);
 +            lz_unpack(pb, p_end - pb, s->unpack_buffer, s->unpack_buffer_size);
              meth &= 0x7F;
              pb = s->unpack_buffer;
 -            pb_size = s->unpack_buffer_size;
 +            pb_end = s->unpack_buffer + s->unpack_buffer_size;
          }
  
-         dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
+         dp = &frame->data[0][frame_y * frame->linesize[0] + frame_x];
          pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
          switch (meth) {
          case 1:
                      return;
                  memcpy(dp, pb, frame_width);
                  pb += frame_width;
-                 dp += s->frame.linesize[0];
 -                pb_size -= frame_width;
+                 dp += frame->linesize[0];
                  pp += s->prev_frame.linesize[0];
              }
              break;
                      }
                  } while (ofs < frame_width);
                  if (ofs > frame_width) {
 -                    av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
 +                    av_log(s->avctx, AV_LOG_ERROR, "offset > width (%d > %d)\n",
                          ofs, frame_width);
                  }
-                 dp += s->frame.linesize[0];
+                 dp += frame->linesize[0];
                  pp += s->prev_frame.linesize[0];
              }
              break;
@@@ -405,9 -414,6 +404,8 @@@ static av_cold int vmdvideo_decode_init
          palette32[i] = (r << 16) | (g << 8) | (b);
      }
  
-     avcodec_get_frame_defaults(&s->frame);
 +    avcodec_get_frame_defaults(&s->prev_frame);
 +
      return 0;
  }
  
@@@ -425,24 -433,22 +425,22 @@@ static int vmdvideo_decode_frame(AVCode
      if (buf_size < 16)
          return buf_size;
  
-     s->frame.reference = 3;
-     if (ff_get_buffer(avctx, &s->frame)) {
+     if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) {
 -        av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
 +        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-         return -1;
+         return ret;
      }
  
-     vmd_decode(s);
+     vmd_decode(s, frame);
  
      /* make the palette available on the way out */
-     memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
+     memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4);
  
      /* shuffle frames */
-     FFSWAP(AVFrame, s->frame, s->prev_frame);
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
+     av_frame_unref(&s->prev_frame);
+     if ((ret = av_frame_ref(&s->prev_frame, frame)) < 0)
+         return ret;
  
      *got_frame      = 1;
-     *(AVFrame*)data = s->prev_frame;
  
      /* report that the buffer was completely consumed */
      return buf_size;
Simple merge
@@@ -1688,48 -1682,9 +1688,48 @@@ static int vorbis_decode_frame(AVCodecC
  
      av_dlog(NULL, "packet length %d \n", buf_size);
  
 +    if (*buf == 1 && buf_size > 7) {
 +        init_get_bits(gb, buf+1, buf_size*8 - 8);
 +        vorbis_free(vc);
 +        if ((ret = vorbis_parse_id_hdr(vc))) {
 +            av_log(avctx, AV_LOG_ERROR, "Id header corrupt.\n");
 +            vorbis_free(vc);
 +            return ret;
 +        }
 +
 +        if (vc->audio_channels > 8)
 +            avctx->channel_layout = 0;
 +        else
 +            avctx->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1];
 +
 +        avctx->channels    = vc->audio_channels;
 +        avctx->sample_rate = vc->audio_samplerate;
 +        return buf_size;
 +    }
 +
 +    if (*buf == 3 && buf_size > 7) {
 +        av_log(avctx, AV_LOG_DEBUG, "Ignoring comment header\n");
 +        return buf_size;
 +    }
 +
 +    if (*buf == 5 && buf_size > 7 && vc->channel_residues && !vc->modes) {
 +        init_get_bits(gb, buf+1, buf_size*8 - 8);
 +        if ((ret = vorbis_parse_setup_hdr(vc))) {
 +            av_log(avctx, AV_LOG_ERROR, "Setup header corrupt.\n");
 +            vorbis_free(vc);
 +            return ret;
 +        }
 +        return buf_size;
 +    }
 +
 +    if (!vc->channel_residues || !vc->modes) {
 +        av_log(avctx, AV_LOG_ERROR, "Data packet before valid headers\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      /* get output buffer */
      frame->nb_samples = vc->blocksize[1] / 2;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
@@@ -135,11 -131,10 +135,11 @@@ typedef struct Vp3DecodeContext 
      int version;
      int width, height;
      int chroma_x_shift, chroma_y_shift;
-     AVFrame golden_frame;
-     AVFrame last_frame;
-     AVFrame current_frame;
+     ThreadFrame golden_frame;
+     ThreadFrame last_frame;
+     ThreadFrame current_frame;
      int keyframe;
 +    uint8_t idct_permutation[64];
      DSPContext dsp;
      VideoDSPContext vdsp;
      VP3DSPContext vp3dsp;
@@@ -297,8 -284,12 +289,14 @@@ static av_cold int vp3_decode_end(AVCod
      av_freep(&s->motion_val[1]);
      av_freep(&s->edge_emu_buffer);
  
 +    s->theora_tables = 0;
 +
+     /* release all frames */
+     vp3_decode_flush(avctx);
+     av_frame_free(&s->current_frame.f);
+     av_frame_free(&s->last_frame.f);
+     av_frame_free(&s->golden_frame.f);
      if (avctx->internal->is_copy)
          return 0;
  
@@@ -1992,10 -1991,8 +2022,9 @@@ static int vp3_decode_frame(AVCodecCont
      if (avctx->skip_frame >= AVDISCARD_NONKEY && !s->keyframe)
          return buf_size;
  
-     s->current_frame.reference = 3;
-     s->current_frame.pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
-     s->current_frame.key_frame = s->keyframe;
-     if (ff_thread_get_buffer(avctx, &s->current_frame) < 0) {
+     s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
++    s->current_frame.f->key_frame = s->keyframe;
+     if (ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF) < 0) {
          av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          goto error;
      }
Simple merge
@@@ -453,10 -452,10 +452,10 @@@ static void vp56_decode_mb(VP56Context 
      }
  }
  
 -static int vp56_size_changed(AVCodecContext *avctx)
 +static int vp56_size_changed(VP56Context *s)
  {
 -    VP56Context *s = avctx->priv_data;
 +    AVCodecContext *avctx = s->avctx;
-     int stride = s->framep[VP56_FRAME_CURRENT]->linesize[0];
+     int stride = s->frames[VP56_FRAME_CURRENT]->linesize[0];
      int i;
  
      s->plane_width[0]  = s->plane_width[3]  = avctx->coded_width;
@@@ -500,23 -493,11 +498,11 @@@ int ff_vp56_decode_frame(AVCodecContex
  {
      const uint8_t *buf = avpkt->data;
      VP56Context *s = avctx->priv_data;
-     AVFrame *p = 0;
+     AVFrame *const p = s->frames[VP56_FRAME_CURRENT];
      int remaining_buf_size = avpkt->size;
 -    int is_alpha, av_uninit(alpha_offset);
 -    int res;
 +    int av_uninit(alpha_offset);
 +    int i, res;
  
-     /* select a current frame from the unused frames */
-     for (i = 0; i < 4; ++i) {
-         if (!s->frames[i].data[0]) {
-             p = &s->frames[i];
-             break;
-         }
-     }
-     av_assert0(p != 0);
-     s->framep[VP56_FRAME_CURRENT] = p;
-     if (s->alpha_context)
-         s->alpha_context->framep[VP56_FRAME_CURRENT] = p;
      if (s->has_alpha) {
          if (remaining_buf_size < 3)
              return -1;
              return -1;
      }
  
 -    for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) {
 -        int mb_row, mb_col, mb_row_flip, mb_offset = 0;
 -        int block, y, uv, stride_y, stride_uv;
 -        int golden_frame = 0;
 +    res = s->parse_header(s, buf, remaining_buf_size);
 +    if (res < 0)
 +        return res;
  
 -        s->modelp = &s->models[is_alpha];
 +    if (res == VP56_SIZE_CHANGE) {
 +        for (i = 0; i < 4; i++) {
-             if (s->frames[i].data[0])
-                 avctx->release_buffer(avctx, &s->frames[i]);
++            av_frame_unref(s->frames[i]);
++            if (s->alpha_context)
++                av_frame_unref(s->alpha_context->frames[i]);
 +        }
 +    }
  
-     p->reference = 3;
-     if (ff_get_buffer(avctx, p) < 0) {
 -        res = s->parse_header(s, buf, remaining_buf_size, &golden_frame);
 -        if (res < 0) {
 -            int i;
 -            for (i = 0; i < 4; i++)
 -                av_frame_unref(s->frames[i]);
 -            return res;
++    if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return -1;
 +    }
 +
++    if (s->has_alpha) {
++        av_frame_unref(s->alpha_context->frames[VP56_FRAME_CURRENT]);
++        av_frame_ref(s->alpha_context->frames[VP56_FRAME_CURRENT], p);
++    }
++
 +    if (res == VP56_SIZE_CHANGE) {
 +        if (vp56_size_changed(s)) {
-             avctx->release_buffer(avctx, p);
++            av_frame_unref(p);
 +            return -1;
          }
 +    }
  
 -        if (res == VP56_SIZE_CHANGE) {
 -            int i;
 -            for (i = 0; i < 4; i++)
 -                av_frame_unref(s->frames[i]);
 -            if (is_alpha) {
 -                avcodec_set_dimensions(avctx, 0, 0);
 -                return -1;
 +    if (s->has_alpha) {
 +        int bak_w = avctx->width;
 +        int bak_h = avctx->height;
 +        int bak_cw = avctx->coded_width;
 +        int bak_ch = avctx->coded_height;
 +        buf += alpha_offset;
 +        remaining_buf_size -= alpha_offset;
 +
 +        res = s->alpha_context->parse_header(s->alpha_context, buf, remaining_buf_size);
 +        if (res != 0) {
 +            if(res==VP56_SIZE_CHANGE) {
 +                av_log(avctx, AV_LOG_ERROR, "Alpha reconfiguration\n");
 +                avctx->width  = bak_w;
 +                avctx->height = bak_h;
 +                avctx->coded_width  = bak_cw;
 +                avctx->coded_height = bak_ch;
              }
-             avctx->release_buffer(avctx, p);
++            av_frame_unref(p);
 +            return -1;
          }
 +    }
  
 -        if (!is_alpha) {
 -            if (ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF) < 0) {
 -                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -                return -1;
 -            }
 +    avctx->execute2(avctx, ff_vp56_decode_mbs, 0, 0, s->has_alpha + 1);
  
-     /* release frames that aren't in use */
-     for (i = 0; i < 4; ++i) {
-         AVFrame *victim = &s->frames[i];
-         if (!victim->data[0])
-             continue;
-         if (victim != s->framep[VP56_FRAME_PREVIOUS] &&
-             victim != s->framep[VP56_FRAME_GOLDEN] &&
-             (!s->has_alpha || victim != s->alpha_context->framep[VP56_FRAME_GOLDEN]))
-             avctx->release_buffer(avctx, victim);
-     }
-     p->qstride = 0;
-     p->qscale_table = s->qscale_table;
-     p->qscale_type = FF_QSCALE_TYPE_VP56;
-     *(AVFrame*)data = *p;
 -            if (res == VP56_SIZE_CHANGE)
 -                if (vp56_size_changed(avctx)) {
 -                    av_frame_unref(p);
 -                    return -1;
 -                }
 -        }
++    if ((res = av_frame_ref(data, p)) < 0)
++        return res;
 +    *got_frame = 1;
  
 -        if (p->key_frame) {
 -            p->pict_type = AV_PICTURE_TYPE_I;
 -            s->default_models_init(s);
 -            for (block=0; block<s->mb_height*s->mb_width; block++)
 -                s->macroblocks[block].type = VP56_MB_INTRA;
 -        } else {
 -            p->pict_type = AV_PICTURE_TYPE_P;
 -            vp56_parse_mb_type_models(s);
 -            s->parse_vector_models(s);
 -            s->mb_type = VP56_MB_INTER_NOVEC_PF;
 -        }
 +    return avpkt->size;
 +}
 +
 +static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
 +                              int jobnr, int threadnr)
 +{
 +    VP56Context *s0 = avctx->priv_data;
 +    int is_alpha = (jobnr == 1);
 +    VP56Context *s = is_alpha ? s0->alpha_context : s0;
-     AVFrame *const p = s->framep[VP56_FRAME_CURRENT];
++    AVFrame *const p = s->frames[VP56_FRAME_CURRENT];
 +    int mb_row, mb_col, mb_row_flip, mb_offset = 0;
 +    int block, y, uv, stride_y, stride_uv;
++    int res;
  
 -        if (s->parse_coeff_models(s))
 -            goto next;
 +    if (p->key_frame) {
 +        p->pict_type = AV_PICTURE_TYPE_I;
 +        s->default_models_init(s);
 +        for (block=0; block<s->mb_height*s->mb_width; block++)
 +            s->macroblocks[block].type = VP56_MB_INTRA;
 +    } else {
 +        p->pict_type = AV_PICTURE_TYPE_P;
 +        vp56_parse_mb_type_models(s);
 +        s->parse_vector_models(s);
 +        s->mb_type = VP56_MB_INTER_NOVEC_PF;
 +    }
  
 -        memset(s->prev_dc, 0, sizeof(s->prev_dc));
 -        s->prev_dc[1][VP56_FRAME_CURRENT] = 128;
 -        s->prev_dc[2][VP56_FRAME_CURRENT] = 128;
 +    if (s->parse_coeff_models(s))
 +        goto next;
  
 -        for (block=0; block < 4*s->mb_width+6; block++) {
 -            s->above_blocks[block].ref_frame = VP56_FRAME_NONE;
 -            s->above_blocks[block].dc_coeff = 0;
 -            s->above_blocks[block].not_null_dc = 0;
 -        }
 -        s->above_blocks[2*s->mb_width + 2].ref_frame = VP56_FRAME_CURRENT;
 -        s->above_blocks[3*s->mb_width + 4].ref_frame = VP56_FRAME_CURRENT;
 +    memset(s->prev_dc, 0, sizeof(s->prev_dc));
 +    s->prev_dc[1][VP56_FRAME_CURRENT] = 128;
 +    s->prev_dc[2][VP56_FRAME_CURRENT] = 128;
 +
 +    for (block=0; block < 4*s->mb_width+6; block++) {
 +        s->above_blocks[block].ref_frame = VP56_FRAME_NONE;
 +        s->above_blocks[block].dc_coeff = 0;
 +        s->above_blocks[block].not_null_dc = 0;
 +    }
 +    s->above_blocks[2*s->mb_width + 2].ref_frame = VP56_FRAME_CURRENT;
 +    s->above_blocks[3*s->mb_width + 4].ref_frame = VP56_FRAME_CURRENT;
 +
 +    stride_y  = p->linesize[0];
 +    stride_uv = p->linesize[1];
  
 -        stride_y  = p->linesize[0];
 -        stride_uv = p->linesize[1];
 +    if (s->flip < 0)
 +        mb_offset = 7;
  
 +    /* main macroblocks loop */
 +    for (mb_row=0; mb_row<s->mb_height; mb_row++) {
          if (s->flip < 0)
 -            mb_offset = 7;
 -
 -        /* main macroblocks loop */
 -        for (mb_row=0; mb_row<s->mb_height; mb_row++) {
 -            if (s->flip < 0)
 -                mb_row_flip = s->mb_height - mb_row - 1;
 -            else
 -                mb_row_flip = mb_row;
 -
 -            for (block=0; block<4; block++) {
 -                s->left_block[block].ref_frame = VP56_FRAME_NONE;
 -                s->left_block[block].dc_coeff = 0;
 -                s->left_block[block].not_null_dc = 0;
 -            }
 -            memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx));
 -            memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));
 -
 -            s->above_block_idx[0] = 1;
 -            s->above_block_idx[1] = 2;
 -            s->above_block_idx[2] = 1;
 -            s->above_block_idx[3] = 2;
 -            s->above_block_idx[4] = 2*s->mb_width + 2 + 1;
 -            s->above_block_idx[5] = 3*s->mb_width + 4 + 1;
 -
 -            s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;
 -            s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;
 -            s->block_offset[1] = s->block_offset[0] + 8;
 -            s->block_offset[3] = s->block_offset[2] + 8;
 -            s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;
 -            s->block_offset[5] = s->block_offset[4];
 -
 -            for (mb_col=0; mb_col<s->mb_width; mb_col++) {
 -                vp56_decode_mb(s, mb_row, mb_col, is_alpha);
 -
 -                for (y=0; y<4; y++) {
 -                    s->above_block_idx[y] += 2;
 -                    s->block_offset[y] += 16;
 -                }
 +            mb_row_flip = s->mb_height - mb_row - 1;
 +        else
 +            mb_row_flip = mb_row;
  
 -                for (uv=4; uv<6; uv++) {
 -                    s->above_block_idx[uv] += 1;
 -                    s->block_offset[uv] += 8;
 -                }
 -            }
 +        for (block=0; block<4; block++) {
 +            s->left_block[block].ref_frame = VP56_FRAME_NONE;
 +            s->left_block[block].dc_coeff = 0;
 +            s->left_block[block].not_null_dc = 0;
          }
 +        memset(s->coeff_ctx, 0, sizeof(s->coeff_ctx));
 +        memset(s->coeff_ctx_last, 24, sizeof(s->coeff_ctx_last));
 +
 +        s->above_block_idx[0] = 1;
 +        s->above_block_idx[1] = 2;
 +        s->above_block_idx[2] = 1;
 +        s->above_block_idx[3] = 2;
 +        s->above_block_idx[4] = 2*s->mb_width + 2 + 1;
 +        s->above_block_idx[5] = 3*s->mb_width + 4 + 1;
 +
 +        s->block_offset[s->frbi] = (mb_row_flip*16 + mb_offset) * stride_y;
 +        s->block_offset[s->srbi] = s->block_offset[s->frbi] + 8*stride_y;
 +        s->block_offset[1] = s->block_offset[0] + 8;
 +        s->block_offset[3] = s->block_offset[2] + 8;
 +        s->block_offset[4] = (mb_row_flip*8 + mb_offset) * stride_uv;
 +        s->block_offset[5] = s->block_offset[4];
 +
 +        for (mb_col=0; mb_col<s->mb_width; mb_col++) {
 +            vp56_decode_mb(s, mb_row, mb_col, is_alpha);
 +
 +            for (y=0; y<4; y++) {
 +                s->above_block_idx[y] += 2;
 +                s->block_offset[y] += 16;
 +            }
  
 -    next:
 -        if (p->key_frame || golden_frame) {
 -            av_frame_unref(s->frames[VP56_FRAME_GOLDEN]);
 -            if ((res = av_frame_ref(s->frames[VP56_FRAME_GOLDEN], p)) < 0)
 -                return res;
 +            for (uv=4; uv<6; uv++) {
 +                s->above_block_idx[uv] += 1;
 +                s->block_offset[uv] += 8;
 +            }
          }
 +    }
  
 -        if (s->has_alpha) {
 -            FFSWAP(AVFrame *, s->frames[VP56_FRAME_GOLDEN],
 -                              s->frames[VP56_FRAME_GOLDEN2]);
 -            buf += alpha_offset;
 -            remaining_buf_size -= alpha_offset;
 -        }
 +next:
 +    if (p->key_frame || s->golden_frame) {
-         s->framep[VP56_FRAME_GOLDEN] = p;
++        av_frame_unref(s->frames[VP56_FRAME_GOLDEN]);
++        if ((res = av_frame_ref(s->frames[VP56_FRAME_GOLDEN], p)) < 0)
++            return res;
      }
  
-     FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT],
-                       s->framep[VP56_FRAME_PREVIOUS]);
+     av_frame_unref(s->frames[VP56_FRAME_PREVIOUS]);
+     FFSWAP(AVFrame *, s->frames[VP56_FRAME_CURRENT],
+                       s->frames[VP56_FRAME_PREVIOUS]);
 -
 -    if ((res = av_frame_ref(data, p)) < 0)
 -        return res;
 -    *got_frame = 1;
 -
 -    return avpkt->size;
 +    return 0;
  }
  
- av_cold void ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
+ av_cold int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
  {
      VP56Context *s = avctx->priv_data;
-     ff_vp56_init_context(avctx, s, flip, has_alpha);
++    return ff_vp56_init_context(avctx, s, flip, has_alpha);
 +}
 +
- av_cold void ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s,
++av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s,
 +                                  int flip, int has_alpha)
 +{
      int i;
  
      s->avctx = avctx;
  av_cold int ff_vp56_free(AVCodecContext *avctx)
  {
      VP56Context *s = avctx->priv_data;
 +    return ff_vp56_free_context(s);
 +}
 +
 +av_cold int ff_vp56_free_context(VP56Context *s)
 +{
 +    AVCodecContext *avctx = s->avctx;
      int i;
  
-     av_freep(&s->qscale_table);
      av_freep(&s->above_blocks);
      av_freep(&s->macroblocks);
      av_freep(&s->edge_emu_buffer_alloc);
@@@ -183,11 -177,8 +181,11 @@@ struct vp56_context 
  };
  
  
- void ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha);
- void ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s,
+ int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha);
++int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s,
 +                          int flip, int has_alpha);
  int ff_vp56_free(AVCodecContext *avctx);
 +int ff_vp56_free_context(VP56Context *s);
  void ff_vp56_init_dequant(VP56Context *s, int quantizer);
  int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                           AVPacket *avpkt);
Simple merge
@@@ -594,28 -592,12 +594,29 @@@ static av_cold void vp6_decode_init_con
  static av_cold int vp6_decode_init(AVCodecContext *avctx)
  {
      VP56Context *s = avctx->priv_data;
+     int ret;
+     if ((ret = ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6,
+                             avctx->codec->id == AV_CODEC_ID_VP6A)) < 0)
+         return ret;
  
-     ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6,
-                         avctx->codec->id == AV_CODEC_ID_VP6A);
 +    vp6_decode_init_context(s);
 +
 +    if (s->has_alpha) {
 +        int i;
 +
 +        s->alpha_context = av_mallocz(sizeof(VP56Context));
 +        ff_vp56_init_context(avctx, s->alpha_context,
 +                             s->flip == -1, s->has_alpha);
 +        vp6_decode_init_context(s->alpha_context);
-         for (i = 0; i < 6; ++i)
-             s->alpha_context->framep[i] = s->framep[i];
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold void vp6_decode_init_context(VP56Context *s)
 +{
 +    s->deblock_filtering = 0;
      s->vp56_coord_div = vp6_coord_div;
      s->parse_vector_adjustment = vp6_parse_vector_adjustment;
      s->filter = vp6_filter;
Simple merge
Simple merge
@@@ -599,13 -593,11 +595,11 @@@ static int vqa_decode_frame(AVCodecCont
                              AVPacket *avpkt)
  {
      VqaContext *s = avctx->priv_data;
+     AVFrame *frame = data;
      int res;
  
-     if (s->frame.data[0])
-         avctx->release_buffer(avctx, &s->frame);
-     if ((res = ff_get_buffer(avctx, &s->frame)) < 0) {
+     if ((res = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(s->avctx, AV_LOG_ERROR, "  VQA Video: get_buffer() failed\n");
 +        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return res;
      }
  
@@@ -1215,8 -1204,8 +1215,8 @@@ static int wavpack_decode_frame(AVCodec
      }
  
      /* get output buffer */
 -    frame->nb_samples = s->samples;
 +    frame->nb_samples = s->samples + 1;
-     if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
Simple merge
@@@ -1264,8 -1264,8 +1264,9 @@@ static int decode_packet(AVCodecContex
          save_bits(s, gb, remaining_bits(s, gb), 0);
      }
  
--    *(AVFrame *)data = s->frame;
      *got_frame_ptr   = s->frame.nb_samples > 0;
++    av_frame_move_ref(data, &s->frame);
++
      s->packet_offset = get_bits_count(gb) & 7;
  
      return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -91,8 -90,6 +90,7 @@@ static av_cold int xan_decode_init(AVCo
          av_freep(&s->buffer1);
          return AVERROR(ENOMEM);
      }
-     avcodec_get_frame_defaults(&s->current_frame);
 +    avcodec_get_frame_defaults(&s->last_frame);
  
      return 0;
  }
index 8632db7,0000000..51f88a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,139 -1,0 +1,127 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame)
-         return AVERROR(ENOMEM);
 +/*
 + * XBM image format
 + *
 + * Copyright (c) 2012 Paul B Mahol
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "mathops.h"
 +#include "libavutil/avstring.h"
 +
 +static av_cold int xbm_decode_init(AVCodecContext *avctx)
 +{
-     AVFrame *p = avctx->coded_frame;
 +
 +    return 0;
 +}
 +
 +static int convert(uint8_t x)
 +{
 +    if (x >= 'a')
 +        x -= 87;
 +    else if (x >= 'A')
 +        x -= 55;
 +    else
 +        x -= '0';
 +    return x;
 +}
 +
 +static int xbm_decode_frame(AVCodecContext *avctx, void *data,
 +                            int *got_frame, AVPacket *avpkt)
 +{
-     if (p->data[0])
-         avctx->release_buffer(avctx, p);
-     p->reference = 0;
-     if ((ret = ff_get_buffer(avctx, p)) < 0)
++    AVFrame *p = data;
 +    const uint8_t *end, *ptr = avpkt->data;
 +    uint8_t *dst;
 +    int ret, linesize, i, j;
 +
 +    end = avpkt->data + avpkt->size;
 +    while (!avctx->width || !avctx->height) {
 +        char name[256];
 +        int number, len;
 +
 +        ptr += strcspn(ptr, "#");
 +        if (sscanf(ptr, "#define %256s %u", name, &number) != 2) {
 +            av_log(avctx, AV_LOG_ERROR, "Unexpected preprocessor directive\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        len = strlen(name);
 +        if ((len > 6) && !avctx->height && !memcmp(name + len - 7, "_height", 7)) {
 +                avctx->height = number;
 +        } else if ((len > 5) && !avctx->width && !memcmp(name + len - 6, "_width", 6)) {
 +                avctx->width = number;
 +        } else {
 +            av_log(avctx, AV_LOG_ERROR, "Unknown define '%s'\n", name);
 +            return AVERROR_INVALIDDATA;
 +        }
 +        ptr += strcspn(ptr, "\n\r") + 1;
 +    }
 +
 +    avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
 +
-     *(AVFrame *)data = *p;
++    if ((ret = ff_get_buffer(avctx, p, 0)) < 0)
 +        return ret;
 +
 +    // goto start of image data
 +    ptr += strcspn(ptr, "{") + 1;
 +
 +    linesize = (avctx->width + 7) / 8;
 +    for (i = 0; i < avctx->height; i++) {
 +        dst = p->data[0] + i * p->linesize[0];
 +        for (j = 0; j < linesize; j++) {
 +            uint8_t val;
 +
 +            ptr += strcspn(ptr, "x") + 1;
 +            if (ptr < end && av_isxdigit(*ptr)) {
 +                val = convert(*ptr);
 +                ptr++;
 +                if (av_isxdigit(*ptr))
 +                    val = (val << 4) + convert(*ptr);
 +                *dst++ = ff_reverse[val];
 +            } else {
 +                av_log(avctx, AV_LOG_ERROR, "Unexpected data at '%.8s'\n", ptr);
 +                return AVERROR_INVALIDDATA;
 +            }
 +        }
 +    }
 +
 +    p->key_frame = 1;
 +    p->pict_type = AV_PICTURE_TYPE_I;
 +
 +    *got_frame       = 1;
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int xbm_decode_close(AVCodecContext *avctx)
 +{
 +
 +    return 0;
 +}
 +
 +AVCodec ff_xbm_decoder = {
 +    .name         = "xbm",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_XBM,
 +    .init         = xbm_decode_init,
 +    .close        = xbm_decode_close,
 +    .decode       = xbm_decode_frame,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"),
 +};
index a2f8636,0000000..2711b12
mode 100644,000000..100644
--- /dev/null
@@@ -1,208 -1,0 +1,198 @@@
-     AVFrame frame;
 +/*
 + * Copyright (c) 1990 James Ashton - Sydney University
 + * Copyright (c) 2012 Stefano Sabatini
 + *
 + * 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
 + * X-Face decoder, based on libcompface, by James Ashton.
 + */
 +
 +#include "libavutil/pixdesc.h"
 +#include "avcodec.h"
 +#include "bytestream.h"
 +#include "internal.h"
 +#include "xface.h"
 +
 +static int pop_integer(BigInt *b, const ProbRange *pranges)
 +{
 +    uint8_t r;
 +    int i;
 +
 +    /* extract the last byte into r, and shift right b by 8 bits */
 +    ff_big_div(b, 0, &r);
 +
 +    i = 0;
 +    while (r < pranges->offset || r >= pranges->range + pranges->offset) {
 +        pranges++;
 +        i++;
 +    }
 +    ff_big_mul(b, pranges->range);
 +    ff_big_add(b, r - pranges->offset);
 +    return i;
 +}
 +
 +static void pop_greys(BigInt *b, char *bitmap, int w, int h)
 +{
 +    if (w > 3) {
 +        w /= 2;
 +        h /= 2;
 +        pop_greys(b, bitmap,                       w, h);
 +        pop_greys(b, bitmap + w,                   w, h);
 +        pop_greys(b, bitmap + XFACE_WIDTH * h,     w, h);
 +        pop_greys(b, bitmap + XFACE_WIDTH * h + w, w, h);
 +    } else {
 +        w = pop_integer(b, ff_xface_probranges_2x2);
 +        if (w & 1) bitmap[0]               = 1;
 +        if (w & 2) bitmap[1]               = 1;
 +        if (w & 4) bitmap[XFACE_WIDTH]     = 1;
 +        if (w & 8) bitmap[XFACE_WIDTH + 1] = 1;
 +    }
 +}
 +
 +static void decode_block(BigInt *b, char *bitmap, int w, int h, int level)
 +{
 +    switch (pop_integer(b, &ff_xface_probranges_per_level[level][0])) {
 +    case XFACE_COLOR_WHITE:
 +        return;
 +    case XFACE_COLOR_BLACK:
 +        pop_greys(b, bitmap, w, h);
 +        return;
 +    default:
 +        w /= 2;
 +        h /= 2;
 +        level++;
 +        decode_block(b, bitmap,                       w, h, level);
 +        decode_block(b, bitmap + w,                   w, h, level);
 +        decode_block(b, bitmap + h * XFACE_WIDTH,     w, h, level);
 +        decode_block(b, bitmap + w + h * XFACE_WIDTH, w, h, level);
 +        return;
 +    }
 +}
 +
 +typedef struct XFaceContext {
-     avcodec_get_frame_defaults(&xface->frame);
 +    uint8_t bitmap[XFACE_PIXELS]; ///< image used internally for decoding
 +} XFaceContext;
 +
 +static av_cold int xface_decode_init(AVCodecContext *avctx)
 +{
 +    XFaceContext *xface = avctx->priv_data;
 +
-     if (xface->frame.data[0])
-         avctx->release_buffer(avctx, &xface->frame);
 +    if (avctx->width || avctx->height) {
 +        if (avctx->width != XFACE_WIDTH || avctx->height != XFACE_HEIGHT) {
 +            av_log(avctx, AV_LOG_ERROR,
 +                   "Size value %dx%d not supported, only accepts a size of %dx%d\n",
 +                   avctx->width, avctx->height, XFACE_WIDTH, XFACE_HEIGHT);
 +            return AVERROR(EINVAL);
 +        }
 +    }
 +
 +    avctx->width   = XFACE_WIDTH;
 +    avctx->height  = XFACE_HEIGHT;
 +    avctx->pix_fmt = AV_PIX_FMT_MONOWHITE;
 +
 +    return 0;
 +}
 +
 +static av_cold int xface_decode_close(AVCodecContext *avctx)
 +{
 +    XFaceContext *xface = avctx->priv_data;
 +
-     if (xface->frame.data[0])
-         avctx->release_buffer(avctx, &xface->frame);
-     xface->frame.data[0] = NULL;
-     if ((ret = ff_get_buffer(avctx, &xface->frame)) < 0)
 +    return 0;
 +}
 +
 +static int xface_decode_frame(AVCodecContext *avctx,
 +                              void *data, int *got_frame,
 +                              AVPacket *avpkt)
 +{
 +    XFaceContext *xface = avctx->priv_data;
 +    int ret, i, j, k;
 +    uint8_t byte;
 +    BigInt b = {0};
 +    char *buf;
 +    int64_t c;
++    AVFrame *frame = data;
 +
-     xface->frame.reference = 0;
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
 +        return ret;
-     buf = xface->frame.data[0];
 +
 +    for (i = 0, k = 0; avpkt->data[i] && i < avpkt->size; i++) {
 +        c = avpkt->data[i];
 +
 +        /* ignore invalid digits */
 +        if (c < XFACE_FIRST_PRINT || c > XFACE_LAST_PRINT)
 +            continue;
 +
 +        if (++k > XFACE_MAX_DIGITS) {
 +            av_log(avctx, AV_LOG_WARNING,
 +                   "Buffer is longer than expected, truncating at byte %d\n", i);
 +            break;
 +        }
 +        ff_big_mul(&b, XFACE_PRINTS);
 +        ff_big_add(&b, c - XFACE_FIRST_PRINT);
 +    }
 +
 +    /* decode image and put it in bitmap */
 +    memset(xface->bitmap, 0, XFACE_PIXELS);
 +    buf = xface->bitmap;
 +    decode_block(&b, buf,                         16, 16, 0);
 +    decode_block(&b, buf + 16,                    16, 16, 0);
 +    decode_block(&b, buf + 32,                    16, 16, 0);
 +    decode_block(&b, buf + XFACE_WIDTH * 16,      16, 16, 0);
 +    decode_block(&b, buf + XFACE_WIDTH * 16 + 16, 16, 16, 0);
 +    decode_block(&b, buf + XFACE_WIDTH * 16 + 32, 16, 16, 0);
 +    decode_block(&b, buf + XFACE_WIDTH * 32     , 16, 16, 0);
 +    decode_block(&b, buf + XFACE_WIDTH * 32 + 16, 16, 16, 0);
 +    decode_block(&b, buf + XFACE_WIDTH * 32 + 32, 16, 16, 0);
 +
 +    ff_xface_generate_face(xface->bitmap, xface->bitmap);
 +
 +    /* convert image from 1=black 0=white bitmap to MONOWHITE */
-             buf += xface->frame.linesize[0];
++    buf = frame->data[0];
 +    for (i = 0, j = 0, k = 0, byte = 0; i < XFACE_PIXELS; i++) {
 +        byte += xface->bitmap[i];
 +        if (k == 7) {
 +            buf[j++] = byte;
 +            byte = k = 0;
 +        } else {
 +            k++;
 +            byte <<= 1;
 +        }
 +        if (j == XFACE_WIDTH/8) {
 +            j = 0;
-     *(AVFrame*)data = xface->frame;
++            buf += frame->linesize[0];
 +        }
 +    }
 +
 +    *got_frame = 1;
 +
 +    return avpkt->size;
 +}
 +
 +AVCodec ff_xface_decoder = {
 +    .name           = "xface",
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_XFACE,
 +    .priv_data_size = sizeof(XFaceContext),
 +    .init           = xface_decode_init,
 +    .close          = xface_decode_close,
 +    .decode         = xface_decode_frame,
 +    .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE },
 +    .long_name      = NULL_IF_CONFIG_SMALL("X-face image"),
 +};
diff --cc libavcodec/xl.c
@@@ -55,30 -48,16 +49,26 @@@ static int decode_frame(AVCodecContext 
      uint32_t val;
      int y0, y1, y2, y3 = 0, c0 = 0, c1 = 0;
  
 -    if ((ret = ff_get_buffer(avctx, p, 0)) < 0){
 +    if (avctx->width & 3) {
 +        av_log(avctx, AV_LOG_ERROR, "width is not a multiple of 4\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
 +    if (buf_size < avctx->width * avctx->height) {
 +        av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
-     if (p->data[0])
-         avctx->release_buffer(avctx, p);
-     p->reference = 0;
-     if ((ret = ff_get_buffer(avctx, p)) < 0){
++    if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
          av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
          return ret;
      }
 -    p->pict_type= AV_PICTURE_TYPE_I;
 -    p->key_frame= 1;
 +    p->pict_type = AV_PICTURE_TYPE_I;
 +    p->key_frame = 1;
  
-     Y = a->pic.data[0];
-     U = a->pic.data[1];
-     V = a->pic.data[2];
+     Y = p->data[0];
+     U = p->data[1];
+     V = p->data[2];
  
      stride = avctx->width - 4;
  
      return buf_size;
  }
  
 -static av_cold int decode_init(AVCodecContext *avctx){
 -    avctx->pix_fmt= AV_PIX_FMT_YUV411P;
 +static av_cold int decode_init(AVCodecContext *avctx)
 +{
-     VideoXLContext * const a = avctx->priv_data;
-     avcodec_get_frame_defaults(&a->pic);
 +    avctx->pix_fmt = AV_PIX_FMT_YUV411P;
  
      return 0;
  }
Simple merge
Simple merge
index 655a426,0000000..e53fe16
mode 100644,000000..100644
--- /dev/null
@@@ -1,117 -1,0 +1,101 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame) {
-         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-         return AVERROR(ENOMEM);
-     }
 +/*
 + * y41p decoder
 + *
 + * Copyright (c) 2012 Paul B Mahol
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +
 +static av_cold int y41p_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt             = AV_PIX_FMT_YUV411P;
 +    avctx->bits_per_raw_sample = 12;
 +
 +    if (avctx->width & 7) {
 +        av_log(avctx, AV_LOG_WARNING, "y41p requires width to be divisible by 8.\n");
 +    }
 +
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int y41p_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame, AVPacket *avpkt)
 +{
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    uint8_t *src = avpkt->data;
 +    uint8_t *y, *u, *v;
 +    int i, j;
 +
-     pic->reference = 0;
-     if (ff_get_buffer(avctx, pic) < 0) {
 +    if (avpkt->size < 1.5 * avctx->height * avctx->width) {
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     *(AVFrame *)data = *pic;
++    if (ff_get_buffer(avctx, pic, 0) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    pic->key_frame = 1;
 +    pic->pict_type = AV_PICTURE_TYPE_I;
 +
 +    for (i = avctx->height - 1; i >= 0 ; i--) {
 +        y = &pic->data[0][i * pic->linesize[0]];
 +        u = &pic->data[1][i * pic->linesize[1]];
 +        v = &pic->data[2][i * pic->linesize[2]];
 +        for (j = 0; j < avctx->width; j += 8) {
 +            *(u++) = *src++;
 +            *(y++) = *src++;
 +            *(v++) = *src++;
 +            *(y++) = *src++;
 +
 +            *(u++) = *src++;
 +            *(y++) = *src++;
 +            *(v++) = *src++;
 +            *(y++) = *src++;
 +
 +            *(y++) = *src++;
 +            *(y++) = *src++;
 +            *(y++) = *src++;
 +            *(y++) = *src++;
 +        }
 +    }
 +
 +    *got_frame = 1;
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int y41p_decode_close(AVCodecContext *avctx)
 +{
 +
 +    return 0;
 +}
 +
 +AVCodec ff_y41p_decoder = {
 +    .name         = "y41p",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_Y41P,
 +    .init         = y41p_decode_init,
 +    .decode       = y41p_decode_frame,
 +    .close        = y41p_decode_close,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"),
 +};
@@@ -152,9 -142,10 +142,9 @@@ static int yop_copy_previous_block(YopD
  
      // Calculate position for the copy source
      bufptr = s->dstptr + motion_vector[copy_tag][0] +
-              s->frame.linesize[0] * motion_vector[copy_tag][1];
+              linesize * motion_vector[copy_tag][1];
      if (bufptr < s->dstbuf) {
 -        av_log(s->avctx, AV_LOG_ERROR,
 -               "YOP: cannot decode, file probably corrupt\n");
 +        av_log(s->avctx, AV_LOG_ERROR, "File probably corrupt\n");
          return AVERROR_INVALIDDATA;
      }
  
@@@ -216,22 -205,15 +204,22 @@@ static int yop_decode_frame(AVCodecCont
      s->low_nibble = NULL;
  
      is_odd_frame = avpkt->data[0];
 +    if(is_odd_frame>1){
 +        av_log(avctx, AV_LOG_ERROR, "frame is too odd %d\n", is_odd_frame);
 +        return AVERROR_INVALIDDATA;
 +    }
      firstcolor   = s->first_color[is_odd_frame];
-     palette      = (uint32_t *)s->frame.data[1];
+     palette      = (uint32_t *)frame->data[1];
  
 -    for (i = 0; i < s->num_pal_colors; i++, s->srcptr += 3)
 +    for (i = 0; i < s->num_pal_colors; i++, s->srcptr += 3) {
          palette[i + firstcolor] = (s->srcptr[0] << 18) |
                                    (s->srcptr[1] << 10) |
                                    (s->srcptr[2] << 2);
 +        palette[i + firstcolor] |= 0xFFU << 24 |
 +                                   (palette[i + firstcolor] >> 6) & 0x30303;
 +    }
  
-     s->frame.palette_has_changed = 1;
+     frame->palette_has_changed = 1;
  
      for (y = 0; y < avctx->height; y += 2) {
          for (x = 0; x < avctx->width; x += 2) {
@@@ -270,7 -249,7 +255,6 @@@ AVCodec ff_yop_decoder = 
      .id             = AV_CODEC_ID_YOP,
      .priv_data_size = sizeof(YopDecContext),
      .init           = yop_decode_init,
-     .close          = yop_decode_close,
      .decode         = yop_decode_frame,
      .long_name      = NULL_IF_CONFIG_SMALL("Psygnosis YOP Video"),
 -    .capabilities   = CODEC_CAP_DR1,
  };
index 8eb72c2,0000000..95cacbe
mode 100644,000000..100644
--- /dev/null
@@@ -1,110 -1,0 +1,93 @@@
-     avctx->coded_frame = avcodec_alloc_frame();
-     if (!avctx->coded_frame) {
-         av_log(avctx, AV_LOG_ERROR, "Could not allocate frame.\n");
-         return AVERROR(ENOMEM);
-     }
 +/*
 + * libquicktime yuv4 decoder
 + *
 + * Copyright (c) 2011 Carl Eugen Hoyos
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avcodec.h"
 +#include "internal.h"
 +
 +static av_cold int yuv4_decode_init(AVCodecContext *avctx)
 +{
 +    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
 +
-     AVFrame *pic = avctx->coded_frame;
 +    return 0;
 +}
 +
 +static int yuv4_decode_frame(AVCodecContext *avctx, void *data,
 +                             int *got_frame, AVPacket *avpkt)
 +{
-     if (pic->data[0])
-         avctx->release_buffer(avctx, pic);
++    AVFrame *pic = data;
 +    const uint8_t *src = avpkt->data;
 +    uint8_t *y, *u, *v;
 +    int i, j;
 +
-     pic->reference = 0;
-     if (ff_get_buffer(avctx, pic) < 0) {
 +    if (avpkt->size < 6 * (avctx->width + 1 >> 1) * (avctx->height + 1 >> 1)) {
 +        av_log(avctx, AV_LOG_ERROR, "Insufficient input data.\n");
 +        return AVERROR(EINVAL);
 +    }
 +
-     *(AVFrame *)data = *pic;
++    if (ff_get_buffer(avctx, pic, 0) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer.\n");
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    pic->key_frame = 1;
 +    pic->pict_type = AV_PICTURE_TYPE_I;
 +
 +    y = pic->data[0];
 +    u = pic->data[1];
 +    v = pic->data[2];
 +
 +    for (i = 0; i < (avctx->height + 1) >> 1; i++) {
 +        for (j = 0; j < (avctx->width + 1) >> 1; j++) {
 +            u[j] = *src++ ^ 0x80;
 +            v[j] = *src++ ^ 0x80;
 +            y[                   2 * j    ] = *src++;
 +            y[                   2 * j + 1] = *src++;
 +            y[pic->linesize[0] + 2 * j    ] = *src++;
 +            y[pic->linesize[0] + 2 * j + 1] = *src++;
 +        }
 +
 +        y += 2 * pic->linesize[0];
 +        u +=     pic->linesize[1];
 +        v +=     pic->linesize[2];
 +    }
 +
 +    *got_frame = 1;
-     if (avctx->coded_frame->data[0])
-         avctx->release_buffer(avctx, avctx->coded_frame);
-     av_freep(&avctx->coded_frame);
 +
 +    return avpkt->size;
 +}
 +
 +static av_cold int yuv4_decode_close(AVCodecContext *avctx)
 +{
 +
 +    return 0;
 +}
 +
 +AVCodec ff_yuv4_decoder = {
 +    .name         = "yuv4",
 +    .type         = AVMEDIA_TYPE_VIDEO,
 +    .id           = AV_CODEC_ID_YUV4,
 +    .init         = yuv4_decode_init,
 +    .decode       = yuv4_decode_frame,
 +    .close        = yuv4_decode_close,
 +    .capabilities = CODEC_CAP_DR1,
 +    .long_name    = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"),
 +};
@@@ -407,10 -406,13 +407,7 @@@ static int decode_frame(AVCodecContext 
      int zret = Z_OK; // Zlib return code
      int len = buf_size;
      int hi_ver, lo_ver, ret;
 -    uint8_t *tmp;
 -
 -    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -        return ret;
 -    }
  
-     if (c->pic.data[0])
-             avctx->release_buffer(avctx, &c->pic);
      /* parse header */
      c->flags = buf[0];
      buf++; len--;
          return AVERROR_INVALIDDATA;
      }
  
-     c->pic.reference = 3;
-     c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
-     if ((ret = ff_get_buffer(avctx, &c->pic)) < 0) {
++    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +        return ret;
 +    }
 +
      if (c->comp == 0) { //Uncompressed data
 +        if (c->decomp_size < len) {
 +            av_log(avctx, AV_LOG_ERROR, "decomp buffer too small\n");
 +            return AVERROR_INVALIDDATA;
 +        }
          memcpy(c->decomp_buf, buf, len);
 -        c->decomp_size = 1;
      } else { // ZLIB-compressed data
          c->zstream.total_in = c->zstream.total_out = 0;
 -        c->zstream.next_in = buf;
 +        c->zstream.next_in = (uint8_t*)buf;
          c->zstream.avail_in = len;
          c->zstream.next_out = c->decomp_buf;
          c->zstream.avail_out = c->decomp_size;
      /* update frames */
      {
          uint8_t *out, *src;
 -        int i, j;
 +        int j;
  
-         out = c->pic.data[0];
+         out = frame->data[0];
          src = c->cur;
          switch (c->fmt) {
          case ZMBV_FMT_8BPP:
 -            for (j = 0; j < c->height; j++) {
 -                for (i = 0; i < c->width; i++) {
 -                    out[i * 3 + 0] = c->pal[(*src) * 3 + 0];
 -                    out[i * 3 + 1] = c->pal[(*src) * 3 + 1];
 -                    out[i * 3 + 2] = c->pal[(*src) * 3 + 2];
 -                    src++;
 -                }
 -                out += frame->linesize[0];
 -            }
 -            break;
 +            for (j = 0; j < 256; j++)
-                 AV_WN32(&c->pic.data[1][j * 4], 0xFFU << 24 | AV_RB24(&c->pal[j * 3]));
++                AV_WN32(&frame->data[1][j * 4], 0xFFU << 24 | AV_RB24(&c->pal[j * 3]));
          case ZMBV_FMT_15BPP:
 -            for (j = 0; j < c->height; j++) {
 -                for (i = 0; i < c->width; i++) {
 -                    uint16_t tmp = AV_RL16(src);
 -                    src += 2;
 -                    out[i * 3 + 0] = (tmp & 0x7C00) >> 7;
 -                    out[i * 3 + 1] = (tmp & 0x03E0) >> 2;
 -                    out[i * 3 + 2] = (tmp & 0x001F) << 3;
 -                }
 -                out += frame->linesize[0];
 -            }
 -            break;
          case ZMBV_FMT_16BPP:
 -            for (j = 0; j < c->height; j++) {
 -                for (i = 0; i < c->width; i++) {
 -                    uint16_t tmp = AV_RL16(src);
 -                    src += 2;
 -                    out[i * 3 + 0] = (tmp & 0xF800) >> 8;
 -                    out[i * 3 + 1] = (tmp & 0x07E0) >> 3;
 -                    out[i * 3 + 2] = (tmp & 0x001F) << 3;
 -                }
 -                out += frame->linesize[0];
 -            }
 -            break;
  #ifdef ZMBV_ENABLE_24BPP
          case ZMBV_FMT_24BPP:
 -            for (j = 0; j < c->height; j++) {
 -                memcpy(out, src, c->width * 3);
 -                src += c->width * 3;
 -                out += frame->linesize[0];
 -            }
 -            break;
 -#endif //ZMBV_ENABLE_24BPP
 +#endif
          case ZMBV_FMT_32BPP:
              for (j = 0; j < c->height; j++) {
 -                for (i = 0; i < c->width; i++) {
 -                    uint32_t tmp = AV_RL32(src);
 -                    src += 4;
 -                    AV_WB24(out+(i*3), tmp);
 -                }
 +                memcpy(out, src, c->stride);
 +                src += c->stride;
-                 out += c->pic.linesize[0];
+                 out += frame->linesize[0];
              }
              break;
          default: