Merge commit '721d57e608dc4fd6c86f27c5ae76ef559d646220'
authorJames Almer <jamrial@gmail.com>
Sun, 19 Mar 2017 18:36:37 +0000 (15:36 -0300)
committerJames Almer <jamrial@gmail.com>
Sun, 19 Mar 2017 20:15:24 +0000 (17:15 -0300)
* commit '721d57e608dc4fd6c86f27c5ae76ef559d646220':
  vp56: Separate VP5 and VP6 dsp initialization

Merged-by: James Almer <jamrial@gmail.com>
1  2 
libavcodec/arm/vp6dsp_init_arm.c
libavcodec/vp5.c
libavcodec/vp56.c
libavcodec/vp56.h
libavcodec/vp56dsp.c
libavcodec/vp56dsp.h
libavcodec/vp6.c
libavcodec/x86/vp6dsp_init.c

@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  
  #include "libavutil/attributes.h"
  #include "libavutil/arm/cpu.h"
- #include "libavcodec/avcodec.h"
  #include "libavcodec/vp56dsp.h"
  
  void ff_vp6_edge_filter_hor_neon(uint8_t *yuv, ptrdiff_t stride, int t);
  void ff_vp6_edge_filter_ver_neon(uint8_t *yuv, ptrdiff_t stride, int t);
  
- av_cold void ff_vp6dsp_init_arm(VP56DSPContext *s, enum AVCodecID codec)
+ av_cold void ff_vp6dsp_init_arm(VP56DSPContext *s)
  {
      int cpu_flags = av_get_cpu_flags();
  
diff --combined libavcodec/vp5.c
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (C) 2006  Aurelien Jacobs <aurel@gnuage.org>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "vp5data.h"
  
  
 -static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
 -                            int *golden_frame)
 +static int vp5_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
  {
      VP56RangeCoder *c = &s->c;
      int rows, cols;
 +    int ret;
  
 -    ff_vp56_init_range_decoder(&s->c, buf, buf_size);
 +    ret = ff_vp56_init_range_decoder(&s->c, buf, buf_size);
 +    if (ret < 0)
 +        return ret;
      s->frames[VP56_FRAME_CURRENT]->key_frame = !vp56_rac_get(c);
      vp56_rac_get(c);
      ff_vp56_init_dequant(s, vp56_rac_gets(c, 6));
@@@ -87,7 -85,7 +87,7 @@@ static void vp5_parse_vector_adjustment
  
      for (comp=0; comp<2; comp++) {
          int delta = 0;
 -        if (vp56_rac_get_prob(c, model->vector_dct[comp])) {
 +        if (vp56_rac_get_prob_branchy(c, model->vector_dct[comp])) {
              int sign = vp56_rac_get_prob(c, model->vector_sig[comp]);
              di  = vp56_rac_get_prob(c, model->vector_pdi[comp][0]);
              di |= vp56_rac_get_prob(c, model->vector_pdi[comp][1]) << 1;
@@@ -110,19 -108,19 +110,19 @@@ static void vp5_parse_vector_models(VP5
      int comp, node;
  
      for (comp=0; comp<2; comp++) {
 -        if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][0]))
 +        if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][0]))
              model->vector_dct[comp] = vp56_rac_gets_nn(c, 7);
 -        if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][1]))
 +        if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][1]))
              model->vector_sig[comp] = vp56_rac_gets_nn(c, 7);
 -        if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][2]))
 +        if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][2]))
              model->vector_pdi[comp][0] = vp56_rac_gets_nn(c, 7);
 -        if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][3]))
 +        if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][3]))
              model->vector_pdi[comp][1] = vp56_rac_gets_nn(c, 7);
      }
  
      for (comp=0; comp<2; comp++)
          for (node=0; node<7; node++)
 -            if (vp56_rac_get_prob(c, vp5_vmc_pct[comp][4 + node]))
 +            if (vp56_rac_get_prob_branchy(c, vp5_vmc_pct[comp][4 + node]))
                  model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7);
  }
  
@@@ -139,7 -137,7 +139,7 @@@ static int vp5_parse_coeff_models(VP56C
  
      for (pt=0; pt<2; pt++)
          for (node=0; node<11; node++)
 -            if (vp56_rac_get_prob(c, vp5_dccv_pct[pt][node])) {
 +            if (vp56_rac_get_prob_branchy(c, vp5_dccv_pct[pt][node])) {
                  def_prob[node] = vp56_rac_gets_nn(c, 7);
                  model->coeff_dccv[pt][node] = def_prob[node];
              } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) {
          for (pt=0; pt<2; pt++)
              for (cg=0; cg<6; cg++)
                  for (node=0; node<11; node++)
 -                    if (vp56_rac_get_prob(c, vp5_ract_pct[ct][pt][cg][node])) {
 +                    if (vp56_rac_get_prob_branchy(c, vp5_ract_pct[ct][pt][cg][node])) {
                          def_prob[node] = vp56_rac_gets_nn(c, 7);
                          model->coeff_ract[pt][ct][cg][node] = def_prob[node];
                      } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) {
      return 0;
  }
  
 -static void vp5_parse_coeff(VP56Context *s)
 +static int vp5_parse_coeff(VP56Context *s)
  {
      VP56RangeCoder *c = &s->c;
      VP56Model *model = s->modelp;
      int b, i, cg, idx, ctx, ctx_last;
      int pt = 0;    /* plane type (0 for Y, 1 for U or V) */
  
 +    if (c->end <= c->buffer && c->bits >= 0) {
 +        av_log(s->avctx, AV_LOG_ERROR, "End of AC stream reached in vp5_parse_coeff\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      for (b=0; b<6; b++) {
          int ct = 1;    /* code type */
  
  
          coeff_idx = 0;
          for (;;) {
 -            if (vp56_rac_get_prob(c, model2[0])) {
 -                if (vp56_rac_get_prob(c, model2[2])) {
 -                    if (vp56_rac_get_prob(c, model2[3])) {
 +            if (vp56_rac_get_prob_branchy(c, model2[0])) {
 +                if (vp56_rac_get_prob_branchy(c, model2[2])) {
 +                    if (vp56_rac_get_prob_branchy(c, model2[3])) {
                          s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 4;
                          idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1);
                          sign = vp56_rac_get(c);
                          for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--)
                              coeff += vp56_rac_get_prob(c, ff_vp56_coeff_parse_table[idx][i]) << i;
                      } else {
 -                        if (vp56_rac_get_prob(c, model2[4])) {
 +                        if (vp56_rac_get_prob_branchy(c, model2[4])) {
                              coeff = 3 + vp56_rac_get_prob(c, model1[5]);
                              s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 3;
                          } else {
                      coeff *= s->dequant_ac;
                  s->block_coeff[b][permute[coeff_idx]] = coeff;
              } else {
 -                if (ct && !vp56_rac_get_prob(c, model2[1]))
 +                if (ct && !vp56_rac_get_prob_branchy(c, model2[1]))
                      break;
                  ct = 0;
                  s->coeff_ctx[ff_vp56_b6to4[b]][coeff_idx] = 0;
                  s->coeff_ctx[ff_vp56_b6to4[b]][i] = 5;
          s->above_blocks[s->above_block_idx[b]].not_null_dc = s->coeff_ctx[ff_vp56_b6to4[b]][0];
      }
 +    return 0;
  }
  
  static void vp5_default_models_init(VP56Context *s)
@@@ -278,6 -270,7 +278,7 @@@ static av_cold int vp5_decode_init(AVCo
  
      if ((ret = ff_vp56_init(avctx, 1, 0)) < 0)
          return ret;
+     ff_vp5dsp_init(&s->vp56dsp);
      s->vp56_coord_div = vp5_coord_div;
      s->parse_vector_adjustment = vp5_parse_vector_adjustment;
      s->parse_coeff = vp5_parse_coeff;
diff --combined libavcodec/vp56.c
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (C) 2006  Aurelien Jacobs <aurel@gnuage.org>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -83,16 -83,16 +83,16 @@@ static void vp56_parse_mb_type_models(V
      int i, ctx, type;
  
      for (ctx=0; ctx<3; ctx++) {
 -        if (vp56_rac_get_prob(c, 174)) {
 +        if (vp56_rac_get_prob_branchy(c, 174)) {
              int idx = vp56_rac_gets(c, 4);
              memcpy(model->mb_types_stats[ctx],
                     ff_vp56_pre_def_mb_type_stats[idx][ctx],
                     sizeof(model->mb_types_stats[ctx]));
          }
 -        if (vp56_rac_get_prob(c, 254)) {
 +        if (vp56_rac_get_prob_branchy(c, 254)) {
              for (type=0; type<10; type++) {
                  for(i=0; i<2; i++) {
 -                    if (vp56_rac_get_prob(c, 205)) {
 +                    if (vp56_rac_get_prob_branchy(c, 205)) {
                          int delta, sign = vp56_rac_get(c);
  
                          delta = vp56_rac_get_tree(c, ff_vp56_pmbtm_tree,
@@@ -153,7 -153,7 +153,7 @@@ static VP56mb vp56_parse_mb_type(VP56Co
      uint8_t *mb_type_model = s->modelp->mb_type[ctx][prev_type];
      VP56RangeCoder *c = &s->c;
  
 -    if (vp56_rac_get_prob(c, mb_type_model[0]))
 +    if (vp56_rac_get_prob_branchy(c, mb_type_model[0]))
          return prev_type;
      else
          return vp56_rac_get_tree(c, ff_vp56_pmbt_tree, mb_type_model);
@@@ -261,25 -261,6 +261,25 @@@ static VP56mb vp56_decode_mv(VP56Contex
      return s->mb_type;
  }
  
 +static VP56mb vp56_conceal_mv(VP56Context *s, int row, int col)
 +{
 +    VP56mv *mv, vect = {0,0};
 +    int b;
 +
 +    s->mb_type = VP56_MB_INTER_NOVEC_PF;
 +    s->macroblocks[row * s->mb_width + col].type = s->mb_type;
 +
 +    mv = &vect;
 +
 +    s->macroblocks[row*s->mb_width + col].mv = *mv;
 +
 +    /* same vector for all blocks */
 +    for (b=0; b<6; b++)
 +        s->mv[b] = *mv;
 +
 +    return s->mb_type;
 +}
 +
  static void vp56_add_predictors_dc(VP56Context *s, VP56Frame ref_frame)
  {
      int idx = s->idct_scantable[0];
@@@ -359,11 -340,11 +359,11 @@@ static void vp56_mc(VP56Context *s, in
      if (x<0 || x+12>=s->plane_width[plane] ||
          y<0 || y+12>=s->plane_height[plane]) {
          s->vdsp.emulated_edge_mc(s->edge_emu_buffer,
 -                            src + s->block_offset[b] + (dy-2)*stride + (dx-2),
 -                            stride, stride,
 -                            12, 12, x, y,
 -                            s->plane_width[plane],
 -                            s->plane_height[plane]);
 +                                 src + s->block_offset[b] + (dy-2)*stride + (dx-2),
 +                                 stride, stride,
 +                                 12, 12, x, y,
 +                                 s->plane_width[plane],
 +                                 s->plane_height[plane]);
          src_block = s->edge_emu_buffer;
          src_offset = 2 + 2*stride;
      } else if (deblock_filtering) {
      }
  }
  
 -static void vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
 +static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, int is_alpha, VP56mb mb_type)
  {
 -    AVFrame *frame_current, *frame_ref;
 -    VP56mb mb_type;
 -    VP56Frame ref_frame;
      int b, ab, b_max, plane, off;
 -
 -    if (s->frames[VP56_FRAME_CURRENT]->key_frame)
 -        mb_type = VP56_MB_INTRA;
 -    else
 -        mb_type = vp56_decode_mv(s, row, col);
 -    ref_frame = ff_vp56_reference_frame[mb_type];
 -
 -    s->parse_coeff(s);
 +    AVFrame *frame_current, *frame_ref;
 +    VP56Frame ref_frame = ff_vp56_reference_frame[mb_type];
  
      vp56_add_predictors_dc(s, ref_frame);
  
      }
  }
  
 -static int vp56_size_changed(AVCodecContext *avctx)
 +static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
  {
 -    VP56Context *s = avctx->priv_data;
 +    VP56mb mb_type;
 +    int ret;
 +
 +    if (s->frames[VP56_FRAME_CURRENT]->key_frame)
 +        mb_type = VP56_MB_INTRA;
 +    else
 +        mb_type = vp56_decode_mv(s, row, col);
 +
 +    ret = s->parse_coeff(s);
 +    if (ret < 0)
 +        return ret;
 +
 +    vp56_render_mb(s, row, col, is_alpha, mb_type);
 +
 +    return 0;
 +}
 +
 +static int vp56_conceal_mb(VP56Context *s, int row, int col, int is_alpha)
 +{
 +    VP56mb mb_type;
 +
 +    if (s->frames[VP56_FRAME_CURRENT]->key_frame)
 +        mb_type = VP56_MB_INTRA;
 +    else
 +        mb_type = vp56_conceal_mv(s, row, col);
 +
 +    vp56_render_mb(s, row, col, is_alpha, mb_type);
 +
 +    return 0;
 +}
 +
 +static int vp56_size_changed(VP56Context *s)
 +{
 +    AVCodecContext *avctx = s->avctx;
      int stride = s->frames[VP56_FRAME_CURRENT]->linesize[0];
      int i;
  
      s->plane_height[0] = s->plane_height[3] = avctx->coded_height;
      s->plane_height[1] = s->plane_height[2] = avctx->coded_height/2;
  
 +    s->have_undamaged_frame = 0;
 +
      for (i=0; i<4; i++)
          s->stride[i] = s->flip * s->frames[VP56_FRAME_CURRENT]->linesize[i];
  
          return AVERROR_INVALIDDATA;
      }
  
 -    s->above_blocks = av_realloc(s->above_blocks,
 -                                 (4*s->mb_width+6) * sizeof(*s->above_blocks));
 -    s->macroblocks = av_realloc(s->macroblocks,
 -                                s->mb_width*s->mb_height*sizeof(*s->macroblocks));
 +    av_reallocp_array(&s->above_blocks, 4*s->mb_width+6,
 +                      sizeof(*s->above_blocks));
 +    av_reallocp_array(&s->macroblocks, s->mb_width*s->mb_height,
 +                      sizeof(*s->macroblocks));
      av_free(s->edge_emu_buffer_alloc);
      s->edge_emu_buffer_alloc = av_malloc(16*stride);
      s->edge_emu_buffer = s->edge_emu_buffer_alloc;
 +    if (!s->above_blocks || !s->macroblocks || !s->edge_emu_buffer_alloc)
 +        return AVERROR(ENOMEM);
      if (s->flip < 0)
          s->edge_emu_buffer += 15 * stride;
  
 +    if (s->alpha_context)
 +        return vp56_size_changed(s->alpha_context);
 +
      return 0;
  }
  
 +static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *, int, int);
 +
  int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
                           AVPacket *avpkt)
  {
      VP56Context *s = avctx->priv_data;
      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;
 +    int ret;
  
      if (s->has_alpha) {
          if (remaining_buf_size < 3)
              return AVERROR_INVALIDDATA;
      }
  
 -    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;
 -        ptrdiff_t stride_y, stride_uv;
 -        int golden_frame = 0;
 -
 -        s->modelp = &s->models[is_alpha];
 +    res = s->parse_header(s, buf, remaining_buf_size);
 +    if (res < 0)
 +        return res;
  
 -        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 (res == VP56_SIZE_CHANGE) {
 +        for (i = 0; i < 4; i++) {
 +            av_frame_unref(s->frames[i]);
 +            if (s->alpha_context)
 +                av_frame_unref(s->alpha_context->frames[i]);
          }
 +    }
  
 -        if (res == VP56_SIZE_CHANGE) {
 -            int i;
 -            for (i = 0; i < 4; i++)
 -                av_frame_unref(s->frames[i]);
 -            if (is_alpha) {
 +    ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF);
 +    if (ret < 0) {
 +        if (res == VP56_SIZE_CHANGE)
 +            ff_set_dimensions(avctx, 0, 0);
 +        return ret;
 +    }
 +
 +    if (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) {
 +        av_frame_unref(s->alpha_context->frames[VP56_FRAME_CURRENT]);
 +        if ((ret = av_frame_ref(s->alpha_context->frames[VP56_FRAME_CURRENT], p)) < 0) {
 +            av_frame_unref(p);
 +            if (res == VP56_SIZE_CHANGE)
                  ff_set_dimensions(avctx, 0, 0);
 -                return AVERROR_INVALIDDATA;
 -            }
 +            return ret;
          }
 +    }
  
 -        if (!is_alpha) {
 -            int ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF);
 -            if (ret < 0) {
 -                av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -                return ret;
 -            }
 -
 -            if (res == VP56_SIZE_CHANGE)
 -                if (vp56_size_changed(avctx)) {
 -                    av_frame_unref(p);
 -                    return AVERROR_INVALIDDATA;
 -                }
 +    if (res == VP56_SIZE_CHANGE) {
 +        if (vp56_size_changed(s)) {
 +            av_frame_unref(p);
 +            return AVERROR_INVALIDDATA;
          }
 +    }
  
 -        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;
 +    if (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) {
 +        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;
 +            }
 +            av_frame_unref(p);
 +            return AVERROR_INVALIDDATA;
          }
 +    }
  
 -        if (s->parse_coeff_models(s))
 -            goto next;
 +    s->discard_frame = 0;
 +    avctx->execute2(avctx, ff_vp56_decode_mbs, 0, 0, (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) + 1);
  
 -        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->discard_frame)
 +        return AVERROR_INVALIDDATA;
  
 -        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;
 +    if ((res = av_frame_ref(data, p)) < 0)
 +        return res;
 +    *got_frame = 1;
 +
 +    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->frames[VP56_FRAME_CURRENT];
 +    int mb_row, mb_col, mb_row_flip, mb_offset = 0;
 +    int block, y, uv;
 +    ptrdiff_t stride_y, stride_uv;
 +    int res;
 +    int damaged = 0;
 +
 +    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;
 +    }
 +
 +    if (s->parse_coeff_models(s))
 +        goto next;
 +
 +    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++) {
 +            if (!damaged) {
 +                int ret = vp56_decode_mb(s, mb_row, mb_col, is_alpha);
 +                if (ret < 0) {
 +                    damaged = 1;
 +                    if (!s->have_undamaged_frame) {
 +                        s->discard_frame = 1;
 +                        return AVERROR_INVALIDDATA;
 +                    }
                  }
              }
 -        }
 +            if (damaged)
 +                vp56_conceal_mb(s, mb_row, mb_col, is_alpha);
  
 -    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 (y=0; y<4; y++) {
 +                s->above_block_idx[y] += 2;
 +                s->block_offset[y] += 16;
 +            }
  
 -        if (s->has_alpha) {
 -            FFSWAP(AVFrame *, s->frames[VP56_FRAME_GOLDEN],
 -                              s->frames[VP56_FRAME_GOLDEN2]);
 -            buf += alpha_offset;
 -            remaining_buf_size -= alpha_offset;
 +            for (uv=4; uv<6; uv++) {
 +                s->above_block_idx[uv] += 1;
 +                s->block_offset[uv] += 8;
 +            }
          }
      }
  
 +    if (!damaged)
 +        s->have_undamaged_frame = 1;
 +
 +next:
 +    if (p->key_frame || s->golden_frame) {
 +        av_frame_unref(s->frames[VP56_FRAME_GOLDEN]);
 +        if ((res = av_frame_ref(s->frames[VP56_FRAME_GOLDEN], p)) < 0)
 +            return res;
 +    }
 +
      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 int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
  {
      VP56Context *s = avctx->priv_data;
 +    return ff_vp56_init_context(avctx, s, flip, has_alpha);
 +}
 +
 +av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s,
 +                                  int flip, int has_alpha)
 +{
      int i;
  
      s->avctx = avctx;
      avctx->pix_fmt = has_alpha ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P;
 +    if (avctx->skip_alpha) avctx->pix_fmt = AV_PIX_FMT_YUV420P;
  
      ff_h264chroma_init(&s->h264chroma, 8);
      ff_hpeldsp_init(&s->hdsp, avctx->flags);
      ff_videodsp_init(&s->vdsp, 8);
      ff_vp3dsp_init(&s->vp3dsp, avctx->flags);
-     ff_vp56dsp_init(&s->vp56dsp, avctx->codec->id);
      for (i = 0; i < 64; i++) {
 -#define TRANSPOSE(x) (x >> 3) | ((x & 7) << 3)
 +#define TRANSPOSE(x) (((x) >> 3) | (((x) & 7) << 3))
          s->idct_scantable[i] = TRANSPOSE(ff_zigzag_direct[i]);
  #undef TRANSPOSE
      }
      s->macroblocks = NULL;
      s->quantizer = -1;
      s->deblock_filtering = 1;
 +    s->golden_frame = 0;
  
      s->filter = NULL;
  
      s->has_alpha = has_alpha;
 +
 +    s->modelp = &s->model;
 +
      if (flip) {
          s->flip = -1;
          s->frbi = 2;
  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)
 +{
      int i;
  
      av_freep(&s->above_blocks);
diff --combined libavcodec/vp56.h
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (C) 2006  Aurelien Jacobs <aurel@gnuage.org>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -26,6 -26,7 +26,7 @@@
  #ifndef AVCODEC_VP56_H
  #define AVCODEC_VP56_H
  
+ #include "avcodec.h"
  #include "get_bits.h"
  #include "hpeldsp.h"
  #include "bytestream.h"
@@@ -74,12 -75,12 +75,12 @@@ typedef void (*VP56ParseVectorAdjustmen
  typedef void (*VP56Filter)(VP56Context *s, uint8_t *dst, uint8_t *src,
                             int offset1, int offset2, ptrdiff_t stride,
                             VP56mv mv, int mask, int select, int luma);
 -typedef void (*VP56ParseCoeff)(VP56Context *s);
 +typedef int  (*VP56ParseCoeff)(VP56Context *s);
  typedef void (*VP56DefaultModelsInit)(VP56Context *s);
  typedef void (*VP56ParseVectorModels)(VP56Context *s);
  typedef int  (*VP56ParseCoeffModels)(VP56Context *s);
  typedef int  (*VP56ParseHeader)(VP56Context *s, const uint8_t *buf,
 -                                int buf_size, int *golden_frame);
 +                                int buf_size);
  
  typedef struct VP56RangeCoder {
      int high;
@@@ -135,7 -136,6 +136,7 @@@ struct vp56_context 
      int sub_version;
  
      /* frame info */
 +    int golden_frame;
      int plane_width[4];
      int plane_height[4];
      int mb_width;   /* number of horizontal MB */
      VP56ParseCoeffModels parse_coeff_models;
      VP56ParseHeader parse_header;
  
 +    /* for "slice" parallelism between YUV and A */
 +    VP56Context *alpha_context;
 +
      VP56Model *modelp;
 -    VP56Model models[2];
 +    VP56Model model;
  
      /* huffman decoding */
      int use_huffman;
      VLC runv_vlc[2];
      VLC ract_vlc[2][3][6];
      unsigned int nb_null[2][2];       /* number of consecutive NULL DC/AC */
 +
 +    int have_undamaged_frame;
 +    int discard_frame;
  };
  
  
  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);
   */
  
  extern const uint8_t ff_vp56_norm_shift[256];
 -void ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size);
 +int ff_vp56_init_range_decoder(VP56RangeCoder *c, const uint8_t *buf, int buf_size);
  
  static av_always_inline unsigned int vp56_rac_renorm(VP56RangeCoder *c)
  {
@@@ -366,7 -357,7 +367,7 @@@ int vp56_rac_get_tree(VP56RangeCoder *c
                        const uint8_t *probs)
  {
      while (tree->val > 0) {
 -        if (vp56_rac_get_prob(c, probs[tree->prob_idx]))
 +        if (vp56_rac_get_prob_branchy(c, probs[tree->prob_idx]))
              tree += tree->val;
          else
              tree++;
      return -tree->val;
  }
  
 -/**
 - * This is identical to vp8_rac_get_tree except for the possibility of starting
 - * on a node other than the root node, needed for coeff decode where this is
 - * used to save a bit after a 0 token (by disallowing EOB to immediately follow.)
 - */
 -static av_always_inline
 -int vp8_rac_get_tree_with_offset(VP56RangeCoder *c, const int8_t (*tree)[2],
 -                                 const uint8_t *probs, int i)
 +// how probabilities are associated with decisions is different I think
 +// well, the new scheme fits in the old but this way has one fewer branches per decision
 +static av_always_inline int vp8_rac_get_tree(VP56RangeCoder *c, const int8_t (*tree)[2],
 +                                   const uint8_t *probs)
  {
 +    int i = 0;
 +
      do {
          i = tree[i][vp56_rac_get_prob(c, probs[i])];
      } while (i > 0);
      return -i;
  }
  
 -// how probabilities are associated with decisions is different I think
 -// well, the new scheme fits in the old but this way has one fewer branches per decision
 -static av_always_inline
 -int vp8_rac_get_tree(VP56RangeCoder *c, const int8_t (*tree)[2],
 -                     const uint8_t *probs)
 -{
 -    return vp8_rac_get_tree_with_offset(c, tree, probs, 0);
 -}
 -
  // DCTextra
  static av_always_inline int vp8_rac_get_coeff(VP56RangeCoder *c, const uint8_t *prob)
  {
diff --combined libavcodec/vp56dsp.c
@@@ -2,20 -2,20 +2,20 @@@
   * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org>
   * Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #include "vp56dsp.h"
  #include "libavutil/common.h"
  
+ #define VP56_EDGE_FILTER(pfx, suf, pix_inc, line_inc)                   \
+ static void pfx ## _edge_filter_ ## suf(uint8_t *yuv, ptrdiff_t stride, \
+                                         int t)                          \
+ {                                                                       \
+     int pix2_inc = 2 * pix_inc;                                         \
+     int i, v;                                                           \
+                                                                         \
+     for (i=0; i<12; i++) {                                              \
+         v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4)>>3;\
+         v = pfx##_adjust(v, t);                                         \
+         yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v);               \
+         yuv[0] = av_clip_uint8(yuv[0] - v);                             \
+         yuv += line_inc;                                                \
+     }                                                                   \
+ }
+ #if CONFIG_VP5_DECODER
  /* Gives very similar result than the vp6 version except in a few cases */
  static int vp5_adjust(int v, int t)
  {
      return v;
  }
  
+ VP56_EDGE_FILTER(vp5, hor, 1, stride)
+ VP56_EDGE_FILTER(vp5, ver, stride, 1)
+ av_cold void ff_vp5dsp_init(VP56DSPContext *s)
+ {
+     s->edge_filter_hor = vp5_edge_filter_hor;
+     s->edge_filter_ver = vp5_edge_filter_ver;
+ }
+ #endif /* CONFIG_VP5_DECODER */
+ #if CONFIG_VP6_DECODER
  static int vp6_adjust(int v, int t)
  {
      int V = v, s = v >> 31;
      return V;
  }
  
- #define VP56_EDGE_FILTER(pfx, suf, pix_inc, line_inc)                   \
- static void pfx ## _edge_filter_ ## suf(uint8_t *yuv, ptrdiff_t stride, \
-                                         int t)                          \
- {                                                                       \
-     int pix2_inc = 2 * pix_inc;                                         \
-     int i, v;                                                           \
-                                                                         \
-     for (i=0; i<12; i++) {                                              \
-         v = (yuv[-pix2_inc] + 3*(yuv[0]-yuv[-pix_inc]) - yuv[pix_inc] + 4)>>3;\
-         v = pfx##_adjust(v, t);                                         \
-         yuv[-pix_inc] = av_clip_uint8(yuv[-pix_inc] + v);               \
-         yuv[0] = av_clip_uint8(yuv[0] - v);                             \
-         yuv += line_inc;                                                \
-     }                                                                   \
- }
- VP56_EDGE_FILTER(vp5, hor, 1, stride)
- VP56_EDGE_FILTER(vp5, ver, stride, 1)
  VP56_EDGE_FILTER(vp6, hor, 1, stride)
  VP56_EDGE_FILTER(vp6, ver, stride, 1)
  
- av_cold void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec)
+ av_cold void ff_vp6dsp_init(VP56DSPContext *s)
  {
-     if (codec == AV_CODEC_ID_VP5) {
-         s->edge_filter_hor = vp5_edge_filter_hor;
-         s->edge_filter_ver = vp5_edge_filter_ver;
-     } else {
-         s->edge_filter_hor = vp6_edge_filter_hor;
-         s->edge_filter_ver = vp6_edge_filter_ver;
+     s->edge_filter_hor = vp6_edge_filter_hor;
+     s->edge_filter_ver = vp6_edge_filter_ver;
  
-         if (CONFIG_VP6_DECODER) {
-             s->vp6_filter_diag4 = ff_vp6_filter_diag4_c;
+     s->vp6_filter_diag4 = ff_vp6_filter_diag4_c;
  
-             if (ARCH_ARM)
-                 ff_vp6dsp_init_arm(s, codec);
-             if (ARCH_X86)
-                 ff_vp6dsp_init_x86(s, codec);
-         }
-     }
+     if (ARCH_ARM)
+         ff_vp6dsp_init_arm(s);
+     if (ARCH_X86)
+         ff_vp6dsp_init_x86(s);
  }
+ #endif /* CONFIG_VP6_DECODER */
diff --combined libavcodec/vp56dsp.h
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (c) 2010 Mans Rullgard <mans@mansr.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -24,8 -24,6 +24,6 @@@
  #include <stddef.h>
  #include <stdint.h>
  
- #include "avcodec.h"
  typedef struct VP56DSPContext {
      void (*edge_filter_hor)(uint8_t *yuv, ptrdiff_t stride, int t);
      void (*edge_filter_ver)(uint8_t *yuv, ptrdiff_t stride, int t);
  void ff_vp6_filter_diag4_c(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
                             const int16_t *h_weights, const int16_t *v_weights);
  
- void ff_vp56dsp_init(VP56DSPContext *s, enum AVCodecID codec);
- void ff_vp6dsp_init_arm(VP56DSPContext *s, enum AVCodecID codec);
- void ff_vp6dsp_init_x86(VP56DSPContext* c, enum AVCodecID codec);
+ void ff_vp5dsp_init(VP56DSPContext *s);
+ void ff_vp6dsp_init(VP56DSPContext *s);
+ void ff_vp6dsp_init_arm(VP56DSPContext *s);
+ void ff_vp6dsp_init_x86(VP56DSPContext *s);
  
  #endif /* AVCODEC_VP56DSP_H */
diff --combined libavcodec/vp6.c
@@@ -1,20 -1,20 +1,20 @@@
  /*
   * Copyright (C) 2006  Aurelien Jacobs <aurel@gnuage.org>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  
  #define VP6_MAX_HUFF_SIZE 12
  
 -static void vp6_parse_coeff(VP56Context *s);
 -static void vp6_parse_coeff_huffman(VP56Context *s);
 +static int vp6_parse_coeff(VP56Context *s);
 +static int vp6_parse_coeff_huffman(VP56Context *s);
  
 -static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
 -                            int *golden_frame)
 +static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size)
  {
      VP56RangeCoder *c = &s->c;
      int parse_filter_info = 0;
@@@ -52,7 -53,6 +52,7 @@@
      int sub_version;
      int rows, cols;
      int res = 0;
 +    int ret;
      int separated_coeff = buf[0] & 1;
  
      s->frames[VP56_FRAME_CURRENT]->key_frame = !(buf[0] & 0x80);
@@@ -94,7 -94,7 +94,7 @@@
                  s->avctx->coded_width  = 16 * cols;
                  s->avctx->coded_height = 16 * rows;
              } else {
 -                int ret = ff_set_dimensions(s->avctx, 16 * cols, 16 * rows);
 +                ret = ff_set_dimensions(s->avctx, 16 * cols, 16 * rows);
                  if (ret < 0)
                      return ret;
  
              res = VP56_SIZE_CHANGE;
          }
  
 -        ff_vp56_init_range_decoder(c, buf+6, buf_size-6);
 +        ret = ff_vp56_init_range_decoder(c, buf+6, buf_size-6);
 +        if (ret < 0)
 +            goto fail;
          vp56_rac_gets(c, 2);
  
          parse_filter_info = s->filter_header;
          if (sub_version < 8)
              vrt_shift = 5;
          s->sub_version = sub_version;
 +        s->golden_frame = 0;
      } else {
          if (!s->sub_version || !s->avctx->coded_width || !s->avctx->coded_height)
              return AVERROR_INVALIDDATA;
              buf += 2;
              buf_size -= 2;
          }
 -        ff_vp56_init_range_decoder(c, buf+1, buf_size-1);
 +        ret = ff_vp56_init_range_decoder(c, buf+1, buf_size-1);
 +        if (ret < 0)
 +            return ret;
  
 -        *golden_frame = vp56_rac_get(c);
 +        s->golden_frame = vp56_rac_get(c);
          if (s->filter_header) {
              s->deblock_filtering = vp56_rac_get(c);
              if (s->deblock_filtering)
          buf      += coeff_offset;
          buf_size -= coeff_offset;
          if (buf_size < 0) {
 -            if (s->frames[VP56_FRAME_CURRENT]->key_frame)
 -                ff_set_dimensions(s->avctx, 0, 0);
 -            return AVERROR_INVALIDDATA;
 +            ret = AVERROR_INVALIDDATA;
 +            goto fail;
          }
          if (s->use_huffman) {
              s->parse_coeff = vp6_parse_coeff_huffman;
              init_get_bits(&s->gb, buf, buf_size<<3);
          } else {
 -            ff_vp56_init_range_decoder(&s->cc, buf, buf_size);
 +            ret = ff_vp56_init_range_decoder(&s->cc, buf, buf_size);
 +            if (ret < 0)
 +                goto fail;
              s->ccp = &s->cc;
          }
      } else {
      }
  
      return res;
 +fail:
 +    if (res == VP56_SIZE_CHANGE)
 +        ff_set_dimensions(s->avctx, 0, 0);
 +    return ret;
  }
  
  static void vp6_coeff_order_table_init(VP56Context *s)
@@@ -221,20 -211,20 +221,20 @@@ static void vp6_parse_vector_models(VP5
      int comp, node;
  
      for (comp=0; comp<2; comp++) {
 -        if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][0]))
 +        if (vp56_rac_get_prob_branchy(c, vp6_sig_dct_pct[comp][0]))
              model->vector_dct[comp] = vp56_rac_gets_nn(c, 7);
 -        if (vp56_rac_get_prob(c, vp6_sig_dct_pct[comp][1]))
 +        if (vp56_rac_get_prob_branchy(c, vp6_sig_dct_pct[comp][1]))
              model->vector_sig[comp] = vp56_rac_gets_nn(c, 7);
      }
  
      for (comp=0; comp<2; comp++)
          for (node=0; node<7; node++)
 -            if (vp56_rac_get_prob(c, vp6_pdv_pct[comp][node]))
 +            if (vp56_rac_get_prob_branchy(c, vp6_pdv_pct[comp][node]))
                  model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7);
  
      for (comp=0; comp<2; comp++)
          for (node=0; node<8; node++)
 -            if (vp56_rac_get_prob(c, vp6_fdv_pct[comp][node]))
 +            if (vp56_rac_get_prob_branchy(c, vp6_fdv_pct[comp][node]))
                  model->vector_fdv[comp][node] = vp56_rac_gets_nn(c, 7);
  }
  
@@@ -280,7 -270,7 +280,7 @@@ static int vp6_parse_coeff_models(VP56C
  
      for (pt=0; pt<2; pt++)
          for (node=0; node<11; node++)
 -            if (vp56_rac_get_prob(c, vp6_dccv_pct[pt][node])) {
 +            if (vp56_rac_get_prob_branchy(c, vp6_dccv_pct[pt][node])) {
                  def_prob[node] = vp56_rac_gets_nn(c, 7);
                  model->coeff_dccv[pt][node] = def_prob[node];
              } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) {
  
      if (vp56_rac_get(c)) {
          for (pos=1; pos<64; pos++)
 -            if (vp56_rac_get_prob(c, vp6_coeff_reorder_pct[pos]))
 +            if (vp56_rac_get_prob_branchy(c, vp6_coeff_reorder_pct[pos]))
                  model->coeff_reorder[pos] = vp56_rac_gets(c, 4);
          vp6_coeff_order_table_init(s);
      }
  
      for (cg=0; cg<2; cg++)
          for (node=0; node<14; node++)
 -            if (vp56_rac_get_prob(c, vp6_runv_pct[cg][node]))
 +            if (vp56_rac_get_prob_branchy(c, vp6_runv_pct[cg][node]))
                  model->coeff_runv[cg][node] = vp56_rac_gets_nn(c, 7);
  
      for (ct=0; ct<3; ct++)
          for (pt=0; pt<2; pt++)
              for (cg=0; cg<6; cg++)
                  for (node=0; node<11; node++)
 -                    if (vp56_rac_get_prob(c, vp6_ract_pct[ct][pt][cg][node])) {
 +                    if (vp56_rac_get_prob_branchy(c, vp6_ract_pct[ct][pt][cg][node])) {
                          def_prob[node] = vp56_rac_gets_nn(c, 7);
                          model->coeff_ract[pt][ct][cg][node] = def_prob[node];
                      } else if (s->frames[VP56_FRAME_CURRENT]->key_frame) {
@@@ -349,7 -339,7 +349,7 @@@ static void vp6_parse_vector_adjustment
      for (comp=0; comp<2; comp++) {
          int i, delta = 0;
  
 -        if (vp56_rac_get_prob(c, model->vector_dct[comp])) {
 +        if (vp56_rac_get_prob_branchy(c, model->vector_dct[comp])) {
              static const uint8_t prob_order[] = {0, 1, 2, 7, 6, 5, 4};
              for (i=0; i<sizeof(prob_order); i++) {
                  int j = prob_order[i];
                                        model->vector_pdv[comp]);
          }
  
 -        if (delta && vp56_rac_get_prob(c, model->vector_sig[comp]))
 +        if (delta && vp56_rac_get_prob_branchy(c, model->vector_sig[comp]))
              delta = -delta;
  
          if (!comp)
@@@ -390,7 -380,7 +390,7 @@@ static unsigned vp6_get_nb_null(VP56Con
      return val;
  }
  
 -static void vp6_parse_coeff_huffman(VP56Context *s)
 +static int vp6_parse_coeff_huffman(VP56Context *s)
  {
      VP56Model *model = s->modelp;
      uint8_t *permute = s->idct_scantable;
                      break;
              } else {
                  if (get_bits_left(&s->gb) <= 0)
 -                    return;
 +                    return AVERROR_INVALIDDATA;
                  coeff = get_vlc2(&s->gb, vlc_coeff->table, FF_HUFFMAN_BITS, 3);
                  if (coeff == 0) {
                      if (coeff_idx) {
              vlc_coeff = &s->ract_vlc[pt][ct][cg];
          }
      }
 +    return 0;
  }
  
 -static void vp6_parse_coeff(VP56Context *s)
 +static int vp6_parse_coeff(VP56Context *s)
  {
      VP56RangeCoder *c = s->ccp;
      VP56Model *model = s->modelp;
      int b, i, cg, idx, ctx;
      int pt = 0;    /* plane type (0 for Y, 1 for U or V) */
  
 +    if (c->end <= c->buffer && c->bits >= 0) {
 +        av_log(s->avctx, AV_LOG_ERROR, "End of AC stream reached in vp6_parse_coeff\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      for (b=0; b<6; b++) {
          int ct = 1;    /* code type */
          int run = 1;
  
          coeff_idx = 0;
          for (;;) {
 -            if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) {
 +            if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob_branchy(c, model2[0])) {
                  /* parse a coeff */
 -                if (vp56_rac_get_prob(c, model2[2])) {
 -                    if (vp56_rac_get_prob(c, model2[3])) {
 +                if (vp56_rac_get_prob_branchy(c, model2[2])) {
 +                    if (vp56_rac_get_prob_branchy(c, model2[3])) {
                          idx = vp56_rac_get_tree(c, ff_vp56_pc_tree, model1);
                          coeff = ff_vp56_coeff_bias[idx+5];
                          for (i=ff_vp56_coeff_bit_length[idx]; i>=0; i--)
                              coeff += vp56_rac_get_prob(c, ff_vp56_coeff_parse_table[idx][i]) << i;
                      } else {
 -                        if (vp56_rac_get_prob(c, model2[4]))
 +                        if (vp56_rac_get_prob_branchy(c, model2[4]))
                              coeff = 3 + vp56_rac_get_prob(c, model1[5]);
                          else
                              coeff = 2;
                  /* parse a run */
                  ct = 0;
                  if (coeff_idx > 0) {
 -                    if (!vp56_rac_get_prob(c, model2[1]))
 +                    if (!vp56_rac_get_prob_branchy(c, model2[1]))
                          break;
  
                      model3 = model->coeff_runv[coeff_idx >= 6];
          s->left_block[ff_vp56_b6to4[b]].not_null_dc =
          s->above_blocks[s->above_block_idx[b]].not_null_dc = !!s->block_coeff[b][0];
      }
 +    return 0;
  }
  
  static int vp6_block_variance(uint8_t *src, ptrdiff_t stride)
@@@ -621,8 -604,6 +621,8 @@@ static void vp6_filter(VP56Context *s, 
      }
  }
  
 +static av_cold void vp6_decode_init_context(VP56Context *s);
 +
  static av_cold int vp6_decode_init(AVCodecContext *avctx)
  {
      VP56Context *s = avctx->priv_data;
      if ((ret = ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6,
                              avctx->codec->id == AV_CODEC_ID_VP6A)) < 0)
          return ret;
+     ff_vp6dsp_init(&s->vp56dsp);
  
 +    vp6_decode_init_context(s);
 +
 +    if (s->has_alpha) {
 +        s->alpha_context = av_mallocz(sizeof(VP56Context));
 +        ff_vp56_init_context(avctx, s->alpha_context,
 +                             s->flip == -1, s->has_alpha);
++        ff_vp6dsp_init(&s->alpha_context->vp56dsp);
 +        vp6_decode_init_context(s->alpha_context);
 +    }
 +
 +    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;
      s->parse_vector_models = vp6_parse_vector_models;
      s->parse_coeff_models = vp6_parse_coeff_models;
      s->parse_header = vp6_parse_header;
 -
 -    return 0;
  }
  
 +static av_cold void vp6_decode_free_context(VP56Context *s);
 +
  static av_cold int vp6_decode_free(AVCodecContext *avctx)
  {
      VP56Context *s = avctx->priv_data;
 -    int pt, ct, cg;
  
      ff_vp56_free(avctx);
 +    vp6_decode_free_context(s);
 +
 +    if (s->alpha_context) {
 +        ff_vp56_free_context(s->alpha_context);
 +        vp6_decode_free_context(s->alpha_context);
 +        av_freep(&s->alpha_context);
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold void vp6_decode_free_context(VP56Context *s)
 +{
 +    int pt, ct, cg;
  
      for (pt=0; pt<2; pt++) {
          ff_free_vlc(&s->dccv_vlc[pt]);
              for (cg=0; cg<6; cg++)
                  ff_free_vlc(&s->ract_vlc[pt][ct][cg]);
      }
 -    return 0;
  }
  
  AVCodec ff_vp6_decoder = {
@@@ -722,5 -677,5 +724,5 @@@ AVCodec ff_vp6a_decoder = 
      .init           = vp6_decode_init,
      .close          = vp6_decode_free,
      .decode         = ff_vp56_decode_frame,
 -    .capabilities   = AV_CODEC_CAP_DR1,
 +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
  };
@@@ -3,20 -3,20 +3,20 @@@
   * Copyright (C) 2009  Sebastien Lucas <sebastien.lucas@gmail.com>
   * Copyright (C) 2009  Zuxy Meng <zuxy.meng@gmail.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
 - * License along with Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -30,7 -30,7 +30,7 @@@ void ff_vp6_filter_diag4_mmx(uint8_t *d
  void ff_vp6_filter_diag4_sse2(uint8_t *dst, uint8_t *src, ptrdiff_t stride,
                                const int16_t *h_weights,const int16_t *v_weights);
  
- av_cold void ff_vp6dsp_init_x86(VP56DSPContext* c, enum AVCodecID codec)
+ av_cold void ff_vp6dsp_init_x86(VP56DSPContext *c)
  {
      int cpu_flags = av_get_cpu_flags();