Merge commit '312daa15891dc7abb77a404fe927d5ee35c52a71'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 21 Nov 2014 22:18:30 +0000 (23:18 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 21 Nov 2014 22:37:04 +0000 (23:37 +0100)
* commit '312daa15891dc7abb77a404fe927d5ee35c52a71':
  vp9: Use the correct upper bound for seg_id

Conflicts:
libavcodec/vp9.h
libavcodec/vp9block.c

Not merged, the value was correct before as far as i can see

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/vp9.c

  #include "vp56.h"
  #include "vp9.h"
  #include "vp9data.h"
 +#include "vp9dsp.h"
 +#include "libavutil/avassert.h"
  
  #define VP9_SYNCCODE 0x498342
 -#define MAX_PROB 255
  
 -static void vp9_decode_flush(AVCodecContext *avctx)
 +enum CompPredMode {
 +    PRED_SINGLEREF,
 +    PRED_COMPREF,
 +    PRED_SWITCHABLE,
 +};
 +
 +enum BlockLevel {
 +    BL_64X64,
 +    BL_32X32,
 +    BL_16X16,
 +    BL_8X8,
 +};
 +
 +enum BlockSize {
 +    BS_64x64,
 +    BS_64x32,
 +    BS_32x64,
 +    BS_32x32,
 +    BS_32x16,
 +    BS_16x32,
 +    BS_16x16,
 +    BS_16x8,
 +    BS_8x16,
 +    BS_8x8,
 +    BS_8x4,
 +    BS_4x8,
 +    BS_4x4,
 +    N_BS_SIZES,
 +};
 +
 +struct VP9mvrefPair {
 +    VP56mv mv[2];
 +    int8_t ref[2];
 +};
 +
 +typedef struct VP9Frame {
 +    ThreadFrame tf;
 +    AVBufferRef *extradata;
 +    uint8_t *segmentation_map;
 +    struct VP9mvrefPair *mv;
 +} VP9Frame;
 +
 +struct VP9Filter {
 +    uint8_t level[8 * 8];
 +    uint8_t /* bit=col */ mask[2 /* 0=y, 1=uv */][2 /* 0=col, 1=row */]
 +                              [8 /* rows */][4 /* 0=16, 1=8, 2=4, 3=inner4 */];
 +};
 +
 +typedef struct VP9Block {
 +    uint8_t seg_id, intra, comp, ref[2], mode[4], uvmode, skip;
 +    enum FilterMode filter;
 +    VP56mv mv[4 /* b_idx */][2 /* ref */];
 +    enum BlockSize bs;
 +    enum TxfmMode tx, uvtx;
 +    enum BlockLevel bl;
 +    enum BlockPartition bp;
 +} VP9Block;
 +
 +typedef struct VP9Context {
 +    VP9DSPContext dsp;
 +    VideoDSPContext vdsp;
 +    GetBitContext gb;
 +    VP56RangeCoder c;
 +    VP56RangeCoder *c_b;
 +    unsigned c_b_size;
 +    VP9Block *b_base, *b;
 +    int pass, uses_2pass, last_uses_2pass;
 +    int row, row7, col, col7;
 +    uint8_t *dst[3];
 +    ptrdiff_t y_stride, uv_stride;
 +
 +    // bitstream header
 +    uint8_t profile;
 +    uint8_t keyframe, last_keyframe;
 +    uint8_t invisible;
 +    uint8_t use_last_frame_mvs;
 +    uint8_t errorres;
 +    uint8_t colorspace;
 +    uint8_t fullrange;
 +    uint8_t intraonly;
 +    uint8_t resetctx;
 +    uint8_t refreshrefmask;
 +    uint8_t highprecisionmvs;
 +    enum FilterMode filtermode;
 +    uint8_t allowcompinter;
 +    uint8_t fixcompref;
 +    uint8_t refreshctx;
 +    uint8_t parallelmode;
 +    uint8_t framectxid;
 +    uint8_t refidx[3];
 +    uint8_t signbias[3];
 +    uint8_t varcompref[2];
 +    ThreadFrame refs[8], next_refs[8];
 +#define CUR_FRAME 0
 +#define LAST_FRAME 1
 +    VP9Frame frames[2];
 +
 +    struct {
 +        uint8_t level;
 +        int8_t sharpness;
 +        uint8_t lim_lut[64];
 +        uint8_t mblim_lut[64];
 +    } filter;
 +    struct {
 +        uint8_t enabled;
 +        int8_t mode[2];
 +        int8_t ref[4];
 +    } lf_delta;
 +    uint8_t yac_qi;
 +    int8_t ydc_qdelta, uvdc_qdelta, uvac_qdelta;
 +    uint8_t lossless;
++#define MAX_SEGMENT 8
 +    struct {
 +        uint8_t enabled;
 +        uint8_t temporal;
 +        uint8_t absolute_vals;
 +        uint8_t update_map;
 +        struct {
 +            uint8_t q_enabled;
 +            uint8_t lf_enabled;
 +            uint8_t ref_enabled;
 +            uint8_t skip_enabled;
 +            uint8_t ref_val;
 +            int16_t q_val;
 +            int8_t lf_val;
 +            int16_t qmul[2][2];
 +            uint8_t lflvl[4][2];
-         } feat[8];
++        } feat[MAX_SEGMENT];
 +    } segmentation;
 +    struct {
 +        unsigned log2_tile_cols, log2_tile_rows;
 +        unsigned tile_cols, tile_rows;
 +        unsigned tile_row_start, tile_row_end, tile_col_start, tile_col_end;
 +    } tiling;
 +    unsigned sb_cols, sb_rows, rows, cols;
 +    struct {
 +        prob_context p;
 +        uint8_t coef[4][2][2][6][6][3];
 +    } prob_ctx[4];
 +    struct {
 +        prob_context p;
 +        uint8_t coef[4][2][2][6][6][11];
 +        uint8_t seg[7];
 +        uint8_t segpred[3];
 +    } prob;
 +    struct {
 +        unsigned y_mode[4][10];
 +        unsigned uv_mode[10][10];
 +        unsigned filter[4][3];
 +        unsigned mv_mode[7][4];
 +        unsigned intra[4][2];
 +        unsigned comp[5][2];
 +        unsigned single_ref[5][2][2];
 +        unsigned comp_ref[5][2];
 +        unsigned tx32p[2][4];
 +        unsigned tx16p[2][3];
 +        unsigned tx8p[2][2];
 +        unsigned skip[3][2];
 +        unsigned mv_joint[4];
 +        struct {
 +            unsigned sign[2];
 +            unsigned classes[11];
 +            unsigned class0[2];
 +            unsigned bits[10][2];
 +            unsigned class0_fp[2][4];
 +            unsigned fp[4];
 +            unsigned class0_hp[2];
 +            unsigned hp[2];
 +        } mv_comp[2];
 +        unsigned partition[4][4][4];
 +        unsigned coef[4][2][2][6][6][3];
 +        unsigned eob[4][2][2][6][6][2];
 +    } counts;
 +    enum TxfmMode txfmmode;
 +    enum CompPredMode comppredmode;
 +
 +    // contextual (left/above) cache
 +    DECLARE_ALIGNED(16, uint8_t, left_y_nnz_ctx)[16];
 +    DECLARE_ALIGNED(16, uint8_t, left_mode_ctx)[16];
 +    DECLARE_ALIGNED(16, VP56mv, left_mv_ctx)[16][2];
 +    DECLARE_ALIGNED(8, uint8_t, left_uv_nnz_ctx)[2][8];
 +    DECLARE_ALIGNED(8, uint8_t, left_partition_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_skip_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_txfm_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_segpred_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_intra_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_comp_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_ref_ctx)[8];
 +    DECLARE_ALIGNED(8, uint8_t, left_filter_ctx)[8];
 +    uint8_t *above_partition_ctx;
 +    uint8_t *above_mode_ctx;
 +    // FIXME maybe merge some of the below in a flags field?
 +    uint8_t *above_y_nnz_ctx;
 +    uint8_t *above_uv_nnz_ctx[2];
 +    uint8_t *above_skip_ctx; // 1bit
 +    uint8_t *above_txfm_ctx; // 2bit
 +    uint8_t *above_segpred_ctx; // 1bit
 +    uint8_t *above_intra_ctx; // 1bit
 +    uint8_t *above_comp_ctx; // 1bit
 +    uint8_t *above_ref_ctx; // 2bit
 +    uint8_t *above_filter_ctx;
 +    VP56mv (*above_mv_ctx)[2];
 +
 +    // whole-frame cache
 +    uint8_t *intra_pred_data[3];
 +    struct VP9Filter *lflvl;
 +    DECLARE_ALIGNED(32, uint8_t, edge_emu_buffer)[71*80];
 +
 +    // block reconstruction intermediates
 +    int block_alloc_using_2pass;
 +    int16_t *block_base, *block, *uvblock_base[2], *uvblock[2];
 +    uint8_t *eob_base, *uveob_base[2], *eob, *uveob[2];
 +    struct { int x, y; } min_mv, max_mv;
 +    DECLARE_ALIGNED(32, uint8_t, tmp_y)[64*64];
 +    DECLARE_ALIGNED(32, uint8_t, tmp_uv)[2][32*32];
 +} VP9Context;
 +
 +static const uint8_t bwh_tab[2][N_BS_SIZES][2] = {
 +    {
 +        { 16, 16 }, { 16, 8 }, { 8, 16 }, { 8, 8 }, { 8, 4 }, { 4, 8 },
 +        { 4, 4 }, { 4, 2 }, { 2, 4 }, { 2, 2 }, { 2, 1 }, { 1, 2 }, { 1, 1 },
 +    }, {
 +        { 8, 8 }, { 8, 4 }, { 4, 8 }, { 4, 4 }, { 4, 2 }, { 2, 4 },
 +        { 2, 2 }, { 2, 1 }, { 1, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 },
 +    }
 +};
 +
 +static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f)
  {
 -    VP9Context *s = avctx->priv_data;
 -    int i;
 +    VP9Context *s = ctx->priv_data;
 +    int ret, sz;
 +
 +    if ((ret = ff_thread_get_buffer(ctx, &f->tf, AV_GET_BUFFER_FLAG_REF)) < 0)
 +        return ret;
 +    sz = 64 * s->sb_cols * s->sb_rows;
 +    if (!(f->extradata = av_buffer_allocz(sz * (1 + sizeof(struct VP9mvrefPair))))) {
 +        ff_thread_release_buffer(ctx, &f->tf);
 +        return AVERROR(ENOMEM);
 +    }
 +
 +    f->segmentation_map = f->extradata->data;
 +    f->mv = (struct VP9mvrefPair *) (f->extradata->data + sz);
 +
 +    // retain segmentation map if it doesn't update
 +    if (s->segmentation.enabled && !s->segmentation.update_map &&
 +        !s->intraonly && !s->keyframe && !s->errorres) {
 +        memcpy(f->segmentation_map, s->frames[LAST_FRAME].segmentation_map, sz);
 +    }
 +
 +    return 0;
 +}
 +
 +static void vp9_unref_frame(AVCodecContext *ctx, VP9Frame *f)
 +{
 +    ff_thread_release_buffer(ctx, &f->tf);
 +    av_buffer_unref(&f->extradata);
 +}
 +
 +static int vp9_ref_frame(AVCodecContext *ctx, VP9Frame *dst, VP9Frame *src)
 +{
 +    int res;
 +
 +    if ((res = ff_thread_ref_frame(&dst->tf, &src->tf)) < 0) {
 +        return res;
 +    } else if (!(dst->extradata = av_buffer_ref(src->extradata))) {
 +        vp9_unref_frame(ctx, dst);
 +        return AVERROR(ENOMEM);
 +    }
  
 -    for (i = 0; i < FF_ARRAY_ELEMS(s->refs); i++)
 -        av_frame_unref(s->refs[i]);
 +    dst->segmentation_map = src->segmentation_map;
 +    dst->mv = src->mv;
 +
 +    return 0;
  }
  
 -static int update_size(AVCodecContext *avctx, int w, int h)
 +static int update_size(AVCodecContext *ctx, int w, int h)
  {
 -    VP9Context *s = avctx->priv_data;
 +    VP9Context *s = ctx->priv_data;
      uint8_t *p;
  
 -    if (s->above_partition_ctx && w == avctx->width && h == avctx->height)
 -        return 0;
 +    av_assert0(w > 0 && h > 0);
  
 -    vp9_decode_flush(avctx);
 +    if (s->intra_pred_data[0] && w == ctx->width && h == ctx->height)
 +        return 0;
  
 -    if (w <= 0 || h <= 0)
 -        return AVERROR_INVALIDDATA;
 +    ctx->width  = w;
 +    ctx->height = h;
 +    s->sb_cols  = (w + 63) >> 6;
 +    s->sb_rows  = (h + 63) >> 6;
 +    s->cols     = (w + 7) >> 3;
 +    s->rows     = (h + 7) >> 3;
  
 -    avctx->width  = w;
 -    avctx->height = h;
 -    s->sb_cols    = (w + 63) >> 6;
 -    s->sb_rows    = (h + 63) >> 6;
 -    s->cols       = (w +  7) >> 3;
 -    s->rows       = (h +  7) >> 3;
 -
 -#define assign(var, type, n) var = (type)p; p += s->sb_cols * n * sizeof(*var)
 -    av_free(s->above_partition_ctx);
 -    p = av_malloc(s->sb_cols *
 -                  (240 + sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx) +
 -                   64 * s->sb_rows * (1 + sizeof(*s->mv[0]) * 2)));
 +#define assign(var, type, n) var = (type) p; p += s->sb_cols * (n) * sizeof(*var)
 +    av_freep(&s->intra_pred_data[0]);
 +    p = av_malloc(s->sb_cols * (240 + sizeof(*s->lflvl) + 16 * sizeof(*s->above_mv_ctx)));
      if (!p)
          return AVERROR(ENOMEM);
 -    assign(s->above_partition_ctx, uint8_t *,     8);
 -    assign(s->above_skip_ctx,      uint8_t *,     8);
 -    assign(s->above_txfm_ctx,      uint8_t *,     8);
 -    assign(s->above_mode_ctx,      uint8_t *,    16);
 -    assign(s->above_y_nnz_ctx,     uint8_t *,    16);
 -    assign(s->above_uv_nnz_ctx[0], uint8_t *,     8);
 -    assign(s->above_uv_nnz_ctx[1], uint8_t *,     8);
 -    assign(s->intra_pred_data[0],  uint8_t *,    64);
 -    assign(s->intra_pred_data[1],  uint8_t *,    32);
 -    assign(s->intra_pred_data[2],  uint8_t *,    32);
 -    assign(s->above_segpred_ctx,   uint8_t *,     8);
 -    assign(s->above_intra_ctx,     uint8_t *,     8);
 -    assign(s->above_comp_ctx,      uint8_t *,     8);
 -    assign(s->above_ref_ctx,       uint8_t *,     8);
 -    assign(s->above_filter_ctx,    uint8_t *,     8);
 -    assign(s->lflvl,               VP9Filter *,   1);
 -    assign(s->above_mv_ctx,        VP56mv(*)[2], 16);
 -    assign(s->segmentation_map,    uint8_t *,      64 * s->sb_rows);
 -    assign(s->mv[0],               VP9MVRefPair *, 64 * s->sb_rows);
 -    assign(s->mv[1],               VP9MVRefPair *, 64 * s->sb_rows);
 +    assign(s->intra_pred_data[0],  uint8_t *,             64);
 +    assign(s->intra_pred_data[1],  uint8_t *,             32);
 +    assign(s->intra_pred_data[2],  uint8_t *,             32);
 +    assign(s->above_y_nnz_ctx,     uint8_t *,             16);
 +    assign(s->above_mode_ctx,      uint8_t *,             16);
 +    assign(s->above_mv_ctx,        VP56mv(*)[2],          16);
 +    assign(s->above_partition_ctx, uint8_t *,              8);
 +    assign(s->above_skip_ctx,      uint8_t *,              8);
 +    assign(s->above_txfm_ctx,      uint8_t *,              8);
 +    assign(s->above_uv_nnz_ctx[0], uint8_t *,              8);
 +    assign(s->above_uv_nnz_ctx[1], uint8_t *,              8);
 +    assign(s->above_segpred_ctx,   uint8_t *,              8);
 +    assign(s->above_intra_ctx,     uint8_t *,              8);
 +    assign(s->above_comp_ctx,      uint8_t *,              8);
 +    assign(s->above_ref_ctx,       uint8_t *,              8);
 +    assign(s->above_filter_ctx,    uint8_t *,              8);
 +    assign(s->lflvl,               struct VP9Filter *,     1);
  #undef assign
  
 +    // these will be re-allocated a little later
 +    av_freep(&s->b_base);
 +    av_freep(&s->block_base);
 +
 +    return 0;
 +}
 +
 +static int update_block_buffers(AVCodecContext *ctx)
 +{
 +    VP9Context *s = ctx->priv_data;
 +
 +    if (s->b_base && s->block_base && s->block_alloc_using_2pass == s->uses_2pass)
 +        return 0;
 +
 +    av_free(s->b_base);
 +    av_free(s->block_base);
 +    if (s->uses_2pass) {
 +        int sbs = s->sb_cols * s->sb_rows;
 +
 +        s->b_base = av_malloc_array(s->cols * s->rows, sizeof(VP9Block));
 +        s->block_base = av_mallocz((64 * 64 + 128) * sbs * 3);
 +        if (!s->b_base || !s->block_base)
 +            return AVERROR(ENOMEM);
 +        s->uvblock_base[0] = s->block_base + sbs * 64 * 64;
 +        s->uvblock_base[1] = s->uvblock_base[0] + sbs * 32 * 32;
 +        s->eob_base = (uint8_t *) (s->uvblock_base[1] + sbs * 32 * 32);
 +        s->uveob_base[0] = s->eob_base + 256 * sbs;
 +        s->uveob_base[1] = s->uveob_base[0] + 64 * sbs;
 +    } else {
 +        s->b_base = av_malloc(sizeof(VP9Block));
 +        s->block_base = av_mallocz((64 * 64 + 128) * 3);
 +        if (!s->b_base || !s->block_base)
 +            return AVERROR(ENOMEM);
 +        s->uvblock_base[0] = s->block_base + 64 * 64;
 +        s->uvblock_base[1] = s->uvblock_base[0] + 32 * 32;
 +        s->eob_base = (uint8_t *) (s->uvblock_base[1] + 32 * 32);
 +        s->uveob_base[0] = s->eob_base + 256;
 +        s->uveob_base[1] = s->uveob_base[0] + 64;
 +    }
 +    s->block_alloc_using_2pass = s->uses_2pass;
 +
      return 0;
  }