Merge commit 'e66fa35392cd45d0a80774cd057fb765d60def43'
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Mon, 11 Apr 2016 14:06:18 +0000 (15:06 +0100)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Mon, 11 Apr 2016 14:06:18 +0000 (15:06 +0100)
* commit 'e66fa35392cd45d0a80774cd057fb765d60def43':
  vc1dec: Check group allocations separatedly

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
1  2 
libavcodec/vc1dec.c

diff --combined libavcodec/vc1dec.c
@@@ -4,20 -4,20 +4,20 @@@
   * Copyright (c) 2006-2007 Konstantin Shishkov
   * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
   *
 - * 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
   */
  
@@@ -37,9 -37,6 +37,9 @@@
  #include "profiles.h"
  #include "vc1.h"
  #include "vc1data.h"
 +#include "vdpau_compat.h"
 +#include "libavutil/avassert.h"
 +
  
  #if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER
  
@@@ -101,7 -98,7 +101,7 @@@ static void vc1_sprite_parse_transform(
          c[6] = 1 << 16;
  }
  
 -static void vc1_parse_sprites(VC1Context *v, GetBitContext* gb, SpriteData* sd)
 +static int vc1_parse_sprites(VC1Context *v, GetBitContext* gb, SpriteData* sd)
  {
      AVCodecContext *avctx = v->s.avctx;
      int sprite, i;
          sd->effect_pcount2 = get_bits(gb, 16);
          if (sd->effect_pcount2 > 10) {
              av_log(avctx, AV_LOG_ERROR, "Too many effect parameters\n");
 -            return;
 +            return AVERROR_INVALIDDATA;
          } else if (sd->effect_pcount2) {
              i = -1;
              av_log(avctx, AV_LOG_DEBUG, "Effect params 2: ");
          av_log(avctx, AV_LOG_DEBUG, "Effect flag set\n");
  
      if (get_bits_count(gb) >= gb->size_in_bits +
 -       (avctx->codec_id == AV_CODEC_ID_WMV3IMAGE ? 64 : 0))
 +       (avctx->codec_id == AV_CODEC_ID_WMV3IMAGE ? 64 : 0)) {
          av_log(avctx, AV_LOG_ERROR, "Buffer overrun\n");
 +        return AVERROR_INVALIDDATA;
 +    }
      if (get_bits_count(gb) < gb->size_in_bits - 8)
          av_log(avctx, AV_LOG_WARNING, "Buffer not fully read\n");
 +
 +    return 0;
  }
  
  static void vc1_draw_sprites(VC1Context *v, SpriteData* sd)
      int ysub[2];
      MpegEncContext *s = &v->s;
  
 -    for (i = 0; i < 2; i++) {
 +    for (i = 0; i <= v->two_sprites; i++) {
          xoff[i] = av_clip(sd->coefs[i][2], 0, v->sprite_width-1 << 16);
          xadv[i] = sd->coefs[i][0];
          if (xadv[i] != 1<<16 || (v->sprite_width << 16) - (v->output_width << 16) - xoff[i])
      }
      alpha = av_clip_uint16(sd->coefs[1][6]);
  
 -    for (plane = 0; plane < (s->avctx->flags & AV_CODEC_FLAG_GRAY ? 1 : 3); plane++) {
 +    for (plane = 0; plane < (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY ? 1 : 3); plane++) {
          int width = v->output_width>>!!plane;
  
          for (row = 0; row < v->output_height>>!!plane; row++) {
          }
  
          if (!plane) {
 -            for (i = 0; i < 2; i++) {
 +            for (i = 0; i <= v->two_sprites; i++) {
                  xoff[i] >>= 1;
                  yoff[i] >>= 1;
              }
  
  static int vc1_decode_sprites(VC1Context *v, GetBitContext* gb)
  {
 +    int ret;
      MpegEncContext *s     = &v->s;
      AVCodecContext *avctx = s->avctx;
      SpriteData sd;
  
 -    vc1_parse_sprites(v, gb, &sd);
 +    memset(&sd, 0, sizeof(sd));
  
 -    if (!s->current_picture.f->data[0]) {
 +    ret = vc1_parse_sprites(v, gb, &sd);
 +    if (ret < 0)
 +        return ret;
 +
 +    if (!s->current_picture.f || !s->current_picture.f->data[0]) {
          av_log(avctx, AV_LOG_ERROR, "Got no sprites\n");
 -        return -1;
 +        return AVERROR_UNKNOWN;
      }
  
      if (v->two_sprites && (!s->last_picture_ptr || !s->last_picture.f->data[0])) {
      }
  
      av_frame_unref(v->sprite_output_frame);
 -    if (ff_get_buffer(avctx, v->sprite_output_frame, 0) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 -        return -1;
 -    }
 +    if ((ret = ff_get_buffer(avctx, v->sprite_output_frame, 0)) < 0)
 +        return ret;
  
      vc1_draw_sprites(v, &sd);
  
@@@ -313,7 -303,7 +313,7 @@@ static void vc1_sprite_flush(AVCodecCon
         wrong but it looks better than doing nothing. */
  
      if (f && f->data[0])
 -        for (plane = 0; plane < (s->avctx->flags & AV_CODEC_FLAG_GRAY ? 1 : 3); plane++)
 +        for (plane = 0; plane < (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY ? 1 : 3); plane++)
              for (i = 0; i < v->sprite_height>>!!plane; i++)
                  memset(f->data[plane] + i * f->linesize[plane],
                         plane ? 128 : 0, f->linesize[plane]);
@@@ -334,48 -324,63 +334,61 @@@ av_cold int ff_vc1_decode_init_alloc_ta
      v->fieldtx_plane    = av_mallocz(s->mb_stride * mb_height);
      v->acpred_plane     = av_malloc (s->mb_stride * mb_height);
      v->over_flags_plane = av_malloc (s->mb_stride * mb_height);
+     if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->forward_mb_plane ||
+         !v->fieldtx_plane || !v->acpred_plane || !v->over_flags_plane)
+         goto error;
  
      v->n_allocated_blks = s->mb_width + 2;
      v->block            = av_malloc(sizeof(*v->block) * v->n_allocated_blks);
      v->cbp_base         = av_malloc(sizeof(v->cbp_base[0]) * 2 * s->mb_stride);
+     if (!v->block || !v->cbp_base)
+         goto error;
      v->cbp              = v->cbp_base + s->mb_stride;
      v->ttblk_base       = av_malloc(sizeof(v->ttblk_base[0]) * 2 * s->mb_stride);
+     if (!v->ttblk_base)
+         goto error;
      v->ttblk            = v->ttblk_base + s->mb_stride;
      v->is_intra_base    = av_mallocz(sizeof(v->is_intra_base[0]) * 2 * s->mb_stride);
+     if (!v->is_intra_base)
+         goto error;
      v->is_intra         = v->is_intra_base + s->mb_stride;
 -    v->luma_mv_base     = av_malloc(sizeof(v->luma_mv_base[0]) * 2 * s->mb_stride);
 +    v->luma_mv_base     = av_mallocz(sizeof(v->luma_mv_base[0]) * 2 * s->mb_stride);
+     if (!v->luma_mv_base)
+         goto error;
      v->luma_mv          = v->luma_mv_base + s->mb_stride;
  
      /* allocate block type info in that way so it could be used with s->block_index[] */
      v->mb_type_base = av_malloc(s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
+     if (!v->mb_type_base)
+         goto error;
      v->mb_type[0]   = v->mb_type_base + s->b8_stride + 1;
      v->mb_type[1]   = v->mb_type_base + s->b8_stride * (mb_height * 2 + 1) + s->mb_stride + 1;
      v->mb_type[2]   = v->mb_type[1] + s->mb_stride * (mb_height + 1);
  
      /* allocate memory to store block level MV info */
      v->blk_mv_type_base = av_mallocz(     s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
+     if (!v->blk_mv_type_base)
+         goto error;
      v->blk_mv_type      = v->blk_mv_type_base + s->b8_stride + 1;
      v->mv_f_base        = av_mallocz(2 * (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2));
+     if (!v->mv_f_base)
+         goto error;
      v->mv_f[0]          = v->mv_f_base + s->b8_stride + 1;
      v->mv_f[1]          = v->mv_f[0] + (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
      v->mv_f_next_base   = av_mallocz(2 * (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2));
+     if (!v->mv_f_next_base)
+         goto error;
      v->mv_f_next[0]     = v->mv_f_next_base + s->b8_stride + 1;
      v->mv_f_next[1]     = v->mv_f_next[0] + (s->b8_stride * (mb_height * 2 + 1) + s->mb_stride * (mb_height + 1) * 2);
  
      ff_intrax8_common_init(&v->x8,s);
  
      if (s->avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || s->avctx->codec_id == AV_CODEC_ID_VC1IMAGE) {
 -        for (i = 0; i < 4; i++) {
 -            v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width);
 -            if (!v->sr_rows[i >> 1][i & 1])
 -                goto error;
 -        }
 +        for (i = 0; i < 4; i++)
 +            if (!(v->sr_rows[i >> 1][i & 1] = av_malloc(v->output_width)))
 +                return AVERROR(ENOMEM);
      }
  
-     if (!v->mv_type_mb_plane || !v->direct_mb_plane || !v->acpred_plane || !v->over_flags_plane ||
-         !v->block || !v->cbp_base || !v->ttblk_base || !v->is_intra_base || !v->luma_mv_base ||
-         !v->mb_type_base) {
-         goto error;
-     }
      return 0;
  
  error:
@@@ -387,7 -392,7 +400,7 @@@ av_cold void ff_vc1_init_transposed_sca
  {
      int i;
      for (i = 0; i < 64; i++) {
 -#define transpose(x) ((x >> 3) | ((x & 7) << 3))
 +#define transpose(x) (((x) >> 3) | (((x) & 7) << 3))
          v->zz_8x8[0][i] = transpose(ff_wmv1_scantable[0][i]);
          v->zz_8x8[1][i] = transpose(ff_wmv1_scantable[1][i]);
          v->zz_8x8[2][i] = transpose(ff_wmv1_scantable[2][i]);
@@@ -407,7 -412,6 +420,7 @@@ static av_cold int vc1_decode_init(AVCo
      VC1Context *v = avctx->priv_data;
      MpegEncContext *s = &v->s;
      GetBitContext gb;
 +    int ret;
  
      /* save the container output size for WMImage */
      v->output_width  = avctx->width;
  
      if (!avctx->extradata_size || !avctx->extradata)
          return -1;
 -    if (!(avctx->flags & AV_CODEC_FLAG_GRAY))
 -        avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
 -    else
 -        avctx->pix_fmt = AV_PIX_FMT_GRAY8;
      v->s.avctx = avctx;
  
 -    if (ff_vc1_init_common(v) < 0)
 -        return -1;
 -    ff_blockdsp_init(&s->bdsp, avctx);
 -    ff_h264chroma_init(&v->h264chroma, 8);
 -    ff_qpeldsp_init(&s->qdsp);
 +    if ((ret = ff_vc1_init_common(v)) < 0)
 +        return ret;
  
      if (avctx->codec_id == AV_CODEC_ID_WMV3 || avctx->codec_id == AV_CODEC_ID_WMV3IMAGE) {
          int count = 0;
  
          init_get_bits(&gb, avctx->extradata, avctx->extradata_size*8);
  
 -        if (ff_vc1_decode_sequence_header(avctx, v, &gb) < 0)
 -          return -1;
 +        if ((ret = ff_vc1_decode_sequence_header(avctx, v, &gb)) < 0)
 +          return ret;
  
          count = avctx->extradata_size*8 - get_bits_count(&gb);
          if (count > 0) {
          }
  
          buf2  = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
 +        if (!buf2)
 +            return AVERROR(ENOMEM);
 +
          start = find_next_marker(start, end); // in WVC1 extradata first byte is its size, but can be 0 in mkv
          next  = start;
          for (; next < end; start = next) {
              init_get_bits(&gb, buf2, buf2_size * 8);
              switch (AV_RB32(start)) {
              case VC1_CODE_SEQHDR:
 -                if (ff_vc1_decode_sequence_header(avctx, v, &gb) < 0) {
 +                if ((ret = ff_vc1_decode_sequence_header(avctx, v, &gb)) < 0) {
                      av_free(buf2);
 -                    return -1;
 +                    return ret;
                  }
                  seq_initialized = 1;
                  break;
              case VC1_CODE_ENTRYPOINT:
 -                if (ff_vc1_decode_entry_point(avctx, v, &gb) < 0) {
 +                if ((ret = ff_vc1_decode_entry_point(avctx, v, &gb)) < 0) {
                      av_free(buf2);
 -                    return -1;
 +                    return ret;
                  }
                  ep_initialized = 1;
                  break;
          v->res_sprite = (avctx->codec_id == AV_CODEC_ID_VC1IMAGE);
      }
  
 -    v->sprite_output_frame = av_frame_alloc();
 -    if (!v->sprite_output_frame)
 -        return AVERROR(ENOMEM);
 -
      avctx->profile = v->profile;
      if (v->profile == PROFILE_ADVANCED)
          avctx->level = v->level;
  
 +    if (!CONFIG_GRAY || !(avctx->flags & AV_CODEC_FLAG_GRAY))
 +        avctx->pix_fmt = ff_get_format(avctx, avctx->codec->pix_fmts);
 +    else {
 +        avctx->pix_fmt = AV_PIX_FMT_GRAY8;
 +        if (avctx->color_range == AVCOL_RANGE_UNSPECIFIED)
 +            avctx->color_range = AVCOL_RANGE_MPEG;
 +    }
 +
 +    // ensure static VLC tables are initialized
 +    if ((ret = ff_msmpeg4_decode_init(avctx)) < 0)
 +        return ret;
 +    if ((ret = ff_vc1_decode_init_alloc_tables(v)) < 0)
 +        return ret;
 +    // Hack to ensure the above functions will be called
 +    // again once we know all necessary settings.
 +    // That this is necessary might indicate a bug.
 +    ff_vc1_decode_end(avctx);
 +
 +    ff_blockdsp_init(&s->bdsp, avctx);
 +    ff_h264chroma_init(&v->h264chroma, 8);
 +    ff_qpeldsp_init(&s->qdsp);
 +
 +    // Must happen after calling ff_vc1_decode_end
 +    // to avoid de-allocating the sprite_output_frame
 +    v->sprite_output_frame = av_frame_alloc();
 +    if (!v->sprite_output_frame)
 +        return AVERROR(ENOMEM);
 +
      avctx->has_b_frames = !!avctx->max_b_frames;
  
      if (v->color_prim == 1 || v->color_prim == 5 || v->color_prim == 6)
              v->sprite_height > 1 << 14 ||
              v->output_width  > 1 << 14 ||
              v->output_height > 1 << 14) return -1;
 +
 +        if ((v->sprite_width&1) || (v->sprite_height&1)) {
 +            avpriv_request_sample(avctx, "odd sprites support");
 +            return AVERROR_PATCHWELCOME;
 +        }
      }
      return 0;
  }
@@@ -611,19 -590,14 +624,19 @@@ static int vc1_decode_frame(AVCodecCont
      MpegEncContext *s = &v->s;
      AVFrame *pict = data;
      uint8_t *buf2 = NULL;
 -    const uint8_t *buf_start = buf;
 -    int mb_height, n_slices1;
 +    const uint8_t *buf_start = buf, *buf_start_second_field = NULL;
 +    int mb_height, n_slices1=-1;
      struct {
          uint8_t *buf;
          GetBitContext gb;
          int mby_start;
      } *slices = NULL, *tmp;
  
 +    v->second_field = 0;
 +
 +    if(s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY)
 +        s->low_delay = 1;
 +
      /* no supplementary picture */
      if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) {
          /* special case for last picture */
              *got_frame = 1;
          }
  
 -        return 0;
 +        return buf_size;
      }
  
 +#if FF_API_CAP_VDPAU
 +    if (s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU) {
 +        if (v->profile < PROFILE_ADVANCED)
 +            avctx->pix_fmt = AV_PIX_FMT_VDPAU_WMV3;
 +        else
 +            avctx->pix_fmt = AV_PIX_FMT_VDPAU_VC1;
 +    }
 +#endif
 +
      //for advanced profile we may need to parse and unescape data
      if (avctx->codec_id == AV_CODEC_ID_VC1 || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) {
          int buf_size2 = 0;
          buf2 = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 +        if (!buf2)
 +            return AVERROR(ENOMEM);
  
          if (IS_MARKER(AV_RB32(buf))) { /* frame starts with marker and needs to be parsed */
              const uint8_t *start, *end, *next;
                  if (size <= 0) continue;
                  switch (AV_RB32(start)) {
                  case VC1_CODE_FRAME:
 -                    if (avctx->hwaccel)
 +                    if (avctx->hwaccel
 +#if FF_API_CAP_VDPAU
 +                        || s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU
 +#endif
 +                        )
                          buf_start = start;
                      buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
                      break;
                  case VC1_CODE_FIELD: {
                      int buf_size3;
 -                    tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
 -                    if (!tmp)
 +                    if (avctx->hwaccel
 +#if FF_API_CAP_VDPAU
 +                        || s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU
 +#endif
 +                        )
 +                        buf_start_second_field = start;
 +                    tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1));
 +                    if (!tmp) {
 +                        ret = AVERROR(ENOMEM);
                          goto err;
 +                    }
                      slices = tmp;
                      slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 -                    if (!slices[n_slices].buf)
 +                    if (!slices[n_slices].buf) {
 +                        ret = AVERROR(ENOMEM);
                          goto err;
 +                    }
                      buf_size3 = vc1_unescape_buffer(start + 4, size,
                                                      slices[n_slices].buf);
                      init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
                                    buf_size3 << 3);
                      /* assuming that the field marker is at the exact middle,
                         hope it's correct */
 -                    slices[n_slices].mby_start = s->mb_height >> 1;
 +                    slices[n_slices].mby_start = s->mb_height + 1 >> 1;
                      n_slices1 = n_slices - 1; // index of the last slice of the first field
                      n_slices++;
                      break;
                      break;
                  case VC1_CODE_SLICE: {
                      int buf_size3;
 -                    tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
 -                    if (!tmp)
 +                    tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1));
 +                    if (!tmp) {
 +                        ret = AVERROR(ENOMEM);
                          goto err;
 +                    }
                      slices = tmp;
                      slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 -                    if (!slices[n_slices].buf)
 +                    if (!slices[n_slices].buf) {
 +                        ret = AVERROR(ENOMEM);
                          goto err;
 +                    }
                      buf_size3 = vc1_unescape_buffer(start + 4, size,
                                                      slices[n_slices].buf);
                      init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
              divider = find_next_marker(buf, buf + buf_size);
              if ((divider == (buf + buf_size)) || AV_RB32(divider) != VC1_CODE_FIELD) {
                  av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n");
 +                ret = AVERROR_INVALIDDATA;
                  goto err;
              } else { // found field marker, unescape second field
 -                tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
 -                if (!tmp)
 +                if (avctx->hwaccel
 +#if FF_API_CAP_VDPAU
 +                    || s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU
 +#endif
 +                    )
 +                    buf_start_second_field = divider;
 +                tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1));
 +                if (!tmp) {
 +                    ret = AVERROR(ENOMEM);
                      goto err;
 +                }
                  slices = tmp;
                  slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
 -                if (!slices[n_slices].buf)
 +                if (!slices[n_slices].buf) {
 +                    ret = AVERROR(ENOMEM);
                      goto err;
 +                }
                  buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf);
                  init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
                                buf_size3 << 3);
 -                slices[n_slices].mby_start = s->mb_height >> 1;
 +                slices[n_slices].mby_start = s->mb_height + 1 >> 1;
                  n_slices1 = n_slices - 1;
                  n_slices++;
              }
      }
  
      if (!s->context_initialized) {
 -        if (ff_msmpeg4_decode_init(avctx) < 0)
 +        if ((ret = ff_msmpeg4_decode_init(avctx)) < 0)
              goto err;
 -        if (ff_vc1_decode_init_alloc_tables(v) < 0) {
 +        if ((ret = ff_vc1_decode_init_alloc_tables(v)) < 0) {
              ff_mpv_common_end(s);
              goto err;
          }
          s->low_delay = !avctx->has_b_frames || v->res_sprite;
  
          if (v->profile == PROFILE_ADVANCED) {
 +            if(avctx->coded_width<=1 || avctx->coded_height<=1) {
 +                ret = AVERROR_INVALIDDATA;
 +                goto err;
 +            }
              s->h_edge_pos = avctx->coded_width;
              s->v_edge_pos = avctx->coded_height;
          }
      v->pic_header_flag = 0;
      v->first_pic_header_flag = 1;
      if (v->profile < PROFILE_ADVANCED) {
 -        if (ff_vc1_parse_frame_header(v, &s->gb) < 0) {
 +        if ((ret = ff_vc1_parse_frame_header(v, &s->gb)) < 0) {
              goto err;
          }
      } else {
 -        if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
 +        if ((ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) {
              goto err;
          }
      }
      v->first_pic_header_flag = 0;
  
 +    if (avctx->debug & FF_DEBUG_PICT_INFO)
 +        av_log(v->s.avctx, AV_LOG_DEBUG, "pict_type: %c\n", av_get_picture_type_char(s->pict_type));
 +
      if ((avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE)
          && s->pict_type != AV_PICTURE_TYPE_I) {
          av_log(v->s.avctx, AV_LOG_ERROR, "Sprite decoder: expected I-frame\n");
 +        ret = AVERROR_INVALIDDATA;
 +        goto err;
 +    }
 +
 +    if ((s->mb_height >> v->field_mode) == 0) {
 +        av_log(v->s.avctx, AV_LOG_ERROR, "image too short\n");
 +        ret = AVERROR_INVALIDDATA;
          goto err;
      }
  
  
      /* skip B-frames if we don't have reference frames */
      if (!s->last_picture_ptr && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) {
 +        av_log(v->s.avctx, AV_LOG_DEBUG, "Skipping B frame without reference frames\n");
          goto end;
      }
      if ((avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B) ||
              s->next_p_frame_damaged = 0;
      }
  
 -    if (ff_mpv_frame_start(s, avctx) < 0) {
 +    if ((ret = ff_mpv_frame_start(s, avctx)) < 0) {
          goto err;
      }
  
 +    v->s.current_picture_ptr->field_picture = v->field_mode;
 +    v->s.current_picture_ptr->f->interlaced_frame = (v->fcm != PROGRESSIVE);
 +    v->s.current_picture_ptr->f->top_field_first  = v->tff;
 +
      // process pulldown flags
      s->current_picture_ptr->f->repeat_pict = 0;
      // Pulldown flags are only valid when 'broadcast' has been set.
      s->me.qpel_put = s->qdsp.put_qpel_pixels_tab;
      s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab;
  
 +#if FF_API_CAP_VDPAU
 +    if ((CONFIG_VC1_VDPAU_DECODER)
 +        &&s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU) {
 +        if (v->field_mode && buf_start_second_field) {
 +            ff_vdpau_vc1_decode_picture(s, buf_start, buf_start_second_field - buf_start);
 +            ff_vdpau_vc1_decode_picture(s, buf_start_second_field, (buf + buf_size) - buf_start_second_field);
 +        } else {
 +            ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start);
 +        }
 +    } else
 +#endif
      if (avctx->hwaccel) {
 -        if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0)
 -            goto err;
 -        if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
 -            goto err;
 -        if (avctx->hwaccel->end_frame(avctx) < 0)
 -            goto err;
 +        if (v->field_mode && buf_start_second_field) {
 +            // decode first field
 +            s->picture_structure = PICT_BOTTOM_FIELD - v->tff;
 +            if ((ret = avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
 +                goto err;
 +            if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
 +                goto err;
 +            if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
 +                goto err;
 +
 +            // decode second field
 +            s->gb = slices[n_slices1 + 1].gb;
 +            s->picture_structure = PICT_TOP_FIELD + v->tff;
 +            v->second_field = 1;
 +            v->pic_header_flag = 0;
 +            if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
 +                av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed");
 +                ret = AVERROR_INVALIDDATA;
 +                goto err;
 +            }
 +            v->s.current_picture_ptr->f->pict_type = v->s.pict_type;
 +
 +            if ((ret = avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
 +                goto err;
 +            if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
 +                goto err;
 +            if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
 +                goto err;
 +        } else {
 +            s->picture_structure = PICT_FRAME;
 +            if ((ret = avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start)) < 0)
 +                goto err;
 +            if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start)) < 0)
 +                goto err;
 +            if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
 +                goto err;
 +        }
      } else {
          int header_ret = 0;
  
          }
          mb_height = s->mb_height >> v->field_mode;
  
 -        if (!mb_height) {
 -            av_log(v->s.avctx, AV_LOG_ERROR, "Invalid mb_height.\n");
 -            goto err;
 -        }
 +        av_assert0 (mb_height > 0);
  
          for (i = 0; i <= n_slices; i++) {
              if (i > 0 &&  slices[i - 1].mby_start >= mb_height) {
                      continue;
                  }
                  v->second_field = 1;
 -                v->blocks_off   = s->mb_width  * s->mb_height << 1;
 +                av_assert0((s->mb_height & 1) == 0);
 +                v->blocks_off   = s->b8_stride * (s->mb_height&~1);
                  v->mb_off       = s->mb_stride * s->mb_height >> 1;
              } else {
                  v->second_field = 0;
                  if (v->field_mode && i == n_slices1 + 2) {
                      if ((header_ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) {
                          av_log(v->s.avctx, AV_LOG_ERROR, "Field header damaged\n");
 +                        ret = AVERROR_INVALIDDATA;
                          if (avctx->err_recognition & AV_EF_EXPLODE)
                              goto err;
                          continue;
                      v->pic_header_flag = 1;
                      if ((header_ret = ff_vc1_parse_frame_header_adv(v, &s->gb)) < 0) {
                          av_log(v->s.avctx, AV_LOG_ERROR, "Slice header damaged\n");
 +                        ret = AVERROR_INVALIDDATA;
                          if (avctx->err_recognition & AV_EF_EXPLODE)
                              goto err;
                          continue;
              s->start_mb_y = (i == 0) ? 0 : FFMAX(0, slices[i-1].mby_start % mb_height);
              if (!v->field_mode || v->second_field)
                  s->end_mb_y = (i == n_slices     ) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height);
 -            else
 +            else {
 +                if (i >= n_slices) {
 +                    av_log(v->s.avctx, AV_LOG_ERROR, "first field slice count too large\n");
 +                    continue;
 +                }
                  s->end_mb_y = (i <= n_slices1 + 1) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height);
 +            }
 +            if (s->end_mb_y <= s->start_mb_y) {
 +                av_log(v->s.avctx, AV_LOG_ERROR, "end mb y %d %d invalid\n", s->end_mb_y, s->start_mb_y);
 +                continue;
 +            }
 +            if (!v->p_frame_skipped && s->pict_type != AV_PICTURE_TYPE_I && !v->cbpcy_vlc) {
 +                av_log(v->s.avctx, AV_LOG_ERROR, "missing cbpcy_vlc\n");
 +                continue;
 +            }
              ff_vc1_decode_blocks(v);
              if (i != n_slices)
                  s->gb = slices[i].gb;
                  get_bits_count(&s->gb), s->gb.size_in_bits);
  //  if (get_bits_count(&s->gb) > buf_size * 8)
  //      return -1;
 +        if(s->er.error_occurred && s->pict_type == AV_PICTURE_TYPE_B) {
 +            ret = AVERROR_INVALIDDATA;
 +            goto err;
 +        }
          if (!v->field_mode)
              ff_er_frame_end(&s->er);
      }
@@@ -1054,7 -910,7 +1067,7 @@@ image
          if (avctx->skip_frame >= AVDISCARD_NONREF)
              goto end;
  #if CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER
 -        if (vc1_decode_sprites(v, &s->gb))
 +        if ((ret = vc1_decode_sprites(v, &s->gb)) < 0)
              goto err;
  #endif
          if ((ret = av_frame_ref(pict, v->sprite_output_frame)) < 0)
          if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
              if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0)
                  goto err;
 -            ff_print_debug_info(s, s->current_picture_ptr);
 +            ff_print_debug_info(s, s->current_picture_ptr, pict);
              *got_frame = 1;
          } else if (s->last_picture_ptr) {
              if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0)
                  goto err;
 -            ff_print_debug_info(s, s->last_picture_ptr);
 +            ff_print_debug_info(s, s->last_picture_ptr, pict);
              *got_frame = 1;
          }
      }
@@@ -1086,7 -942,7 +1099,7 @@@ err
      for (i = 0; i < n_slices; i++)
          av_free(slices[i].buf);
      av_free(slices);
 -    return -1;
 +    return ret;
  }
  
  
@@@ -1098,7 -954,7 +1111,7 @@@ static const enum AVPixelFormat vc1_hwa
      AV_PIX_FMT_D3D11VA_VLD,
  #endif
  #if CONFIG_VC1_VAAPI_HWACCEL
 -    AV_PIX_FMT_VAAPI_VLD,
 +    AV_PIX_FMT_VAAPI,
  #endif
  #if CONFIG_VC1_VDPAU_HWACCEL
      AV_PIX_FMT_VDPAU,
@@@ -1139,38 -995,6 +1152,38 @@@ AVCodec ff_wmv3_decoder = 
  };
  #endif
  
 +#if CONFIG_WMV3_VDPAU_DECODER && FF_API_VDPAU
 +AVCodec ff_wmv3_vdpau_decoder = {
 +    .name           = "wmv3_vdpau",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Windows Media Video 9 VDPAU"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_WMV3,
 +    .priv_data_size = sizeof(VC1Context),
 +    .init           = vc1_decode_init,
 +    .close          = ff_vc1_decode_end,
 +    .decode         = vc1_decode_frame,
 +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HWACCEL_VDPAU,
 +    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU_WMV3, AV_PIX_FMT_NONE },
 +    .profiles       = NULL_IF_CONFIG_SMALL(ff_vc1_profiles)
 +};
 +#endif
 +
 +#if CONFIG_VC1_VDPAU_DECODER && FF_API_VDPAU
 +AVCodec ff_vc1_vdpau_decoder = {
 +    .name           = "vc1_vdpau",
 +    .long_name      = NULL_IF_CONFIG_SMALL("SMPTE VC-1 VDPAU"),
 +    .type           = AVMEDIA_TYPE_VIDEO,
 +    .id             = AV_CODEC_ID_VC1,
 +    .priv_data_size = sizeof(VC1Context),
 +    .init           = vc1_decode_init,
 +    .close          = ff_vc1_decode_end,
 +    .decode         = vc1_decode_frame,
 +    .capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HWACCEL_VDPAU,
 +    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_VDPAU_VC1, AV_PIX_FMT_NONE },
 +    .profiles       = NULL_IF_CONFIG_SMALL(ff_vc1_profiles)
 +};
 +#endif
 +
  #if CONFIG_WMV3IMAGE_DECODER
  AVCodec ff_wmv3image_decoder = {
      .name           = "wmv3image",