Merge commit '96c373c7704aeb1cc1d2c275fbb5d71777665589'
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Thu, 28 Jan 2016 16:54:26 +0000 (16:54 +0000)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Thu, 28 Jan 2016 16:57:04 +0000 (16:57 +0000)
* commit '96c373c7704aeb1cc1d2c275fbb5d71777665589':
  lavc: Move context_model to codec private options

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
1  2 
libavcodec/avcodec.h
libavcodec/ffv1.h
libavcodec/ffv1enc.c
libavcodec/huffyuvenc.c
libavcodec/options_table.h

Simple merge
@@@ -111,9 -101,9 +111,10 @@@ typedef struct FFV1Context 
      int16_t *sample_buffer;
  
      int ec;
 +    int intra;
      int slice_damaged;
      int key_frame_ok;
+     int context_model;
  
      int bits_per_raw_sample;
      int packed_at_lsb;
@@@ -369,11 -257,11 +369,11 @@@ static av_always_inline int encode_line
      return 0;
  }
  
 -static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h,
 -                         int stride, int plane_index)
 +static int encode_plane(FFV1Context *s, uint8_t *src, int w, int h,
 +                         int stride, int plane_index, int pixel_stride)
  {
 -    int x, y, i;
 +    int x, y, i, ret;
-     const int ring_size = s->avctx->context_model ? 3 : 2;
+     const int ring_size = s->context_model ? 3 : 2;
      int16_t *sample[3];
      s->run_index = 0;
  
@@@ -413,10 -297,12 +413,10 @@@ static int encode_rgb_frame(FFV1Contex
                               int w, int h, const int stride[3])
  {
      int x, y, p, i;
-     const int ring_size = s->avctx->context_model ? 3 : 2;
+     const int ring_size = s->context_model ? 3 : 2;
 -    int16_t *sample[MAX_PLANES][3];
 -    int lbd  = s->avctx->bits_per_raw_sample <= 8;
 -    int bits = s->avctx->bits_per_raw_sample > 0
 -               ? s->avctx->bits_per_raw_sample
 -               : 8;
 +    int16_t *sample[4][3];
 +    int lbd    = s->bits_per_raw_sample <= 8;
 +    int bits   = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
      int offset = 1 << bits;
  
      s->run_index = 0;
@@@ -814,27 -664,29 +814,33 @@@ FF_ENABLE_DEPRECATION_WARNING
          break;
      default:
          av_log(avctx, AV_LOG_ERROR, "format not supported\n");
 -        return AVERROR_INVALIDDATA;
 +        return AVERROR(ENOSYS);
      }
 +    av_assert0(s->bits_per_raw_sample >= 8);
 +
      if (s->transparency) {
 -        av_log(
 -            avctx, AV_LOG_WARNING,
 -            "Storing alpha plane, this will require a recent FFV1 decoder to playback!\n");
 +        av_log(avctx, AV_LOG_WARNING, "Storing alpha plane, this will require a recent FFV1 decoder to playback!\n");
      }
+ #if FF_API_PRIVATE_OPT
+ FF_DISABLE_DEPRECATION_WARNINGS
+     if (avctx->context_model)
+         s->context_model = avctx->context_model;
      if (avctx->context_model > 1U) {
 -        av_log(avctx, AV_LOG_ERROR,
 -               "Invalid context model %d, valid values are 0 and 1\n",
 -               avctx->context_model);
 +        av_log(avctx, AV_LOG_ERROR, "Invalid context model %d, valid values are 0 and 1\n", avctx->context_model);
          return AVERROR(EINVAL);
      }
+ FF_ENABLE_DEPRECATION_WARNINGS
+ #endif
  
 -    if (s->ac == AC_RANGE_CUSTOM_TAB)
 +    if (s->ac == AC_RANGE_CUSTOM_TAB) {
 +        for (i = 1; i < 256; i++)
 +            s->state_transition[i] = ver2_state[i];
 +    } else {
 +        RangeCoder c;
 +        ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
          for (i = 1; i < 256; i++)
 -            s->state_transition[i] = ffv1_ver2_state[i];
 +            s->state_transition[i] = c.one_state[i];
 +    }
  
      for (i = 0; i < 256; i++) {
          s->quant_table_count = 2;
@@@ -1028,112 -857,23 +1034,112 @@@ static void encode_slice_header(FFV1Con
      int j;
      memset(state, 128, sizeof(state));
  
 -    put_symbol(c, state, (fs->slice_x + 1) * f->num_h_slices / f->width, 0);
 -    put_symbol(c, state, (fs->slice_y + 1) * f->num_v_slices / f->height, 0);
 -    put_symbol(c, state, (fs->slice_width + 1) * f->num_h_slices / f->width - 1,
 -               0);
 -    put_symbol(c, state,
 -               (fs->slice_height + 1) * f->num_v_slices / f->height - 1,
 -               0);
 -    for (j = 0; j < f->plane_count; j++) {
 +    put_symbol(c, state, (fs->slice_x     +1)*f->num_h_slices / f->width   , 0);
 +    put_symbol(c, state, (fs->slice_y     +1)*f->num_v_slices / f->height  , 0);
 +    put_symbol(c, state, (fs->slice_width +1)*f->num_h_slices / f->width -1, 0);
 +    put_symbol(c, state, (fs->slice_height+1)*f->num_v_slices / f->height-1, 0);
 +    for (j=0; j<f->plane_count; j++) {
          put_symbol(c, state, f->plane[j].quant_table_index, 0);
-         av_assert0(f->plane[j].quant_table_index == f->avctx->context_model);
+         av_assert0(f->plane[j].quant_table_index == f->context_model);
      }
 -    if (!f->frame->interlaced_frame)
 +    if (!f->picture.f->interlaced_frame)
          put_symbol(c, state, 3, 0);
      else
 -        put_symbol(c, state, 1 + !f->frame->top_field_first, 0);
 -    put_symbol(c, state, f->frame->sample_aspect_ratio.num, 0);
 -    put_symbol(c, state, f->frame->sample_aspect_ratio.den, 0);
 +        put_symbol(c, state, 1 + !f->picture.f->top_field_first, 0);
 +    put_symbol(c, state, f->picture.f->sample_aspect_ratio.num, 0);
 +    put_symbol(c, state, f->picture.f->sample_aspect_ratio.den, 0);
 +    if (f->version > 3) {
 +        put_rac(c, state, fs->slice_coding_mode == 1);
 +        if (fs->slice_coding_mode == 1)
 +            ff_ffv1_clear_slice_state(f, fs);
 +        put_symbol(c, state, fs->slice_coding_mode, 0);
 +        if (fs->slice_coding_mode != 1) {
 +            put_symbol(c, state, fs->slice_rct_by_coef, 0);
 +            put_symbol(c, state, fs->slice_rct_ry_coef, 0);
 +        }
 +    }
 +}
 +
 +static void choose_rct_params(FFV1Context *fs, const uint8_t *src[3], const int stride[3], int w, int h)
 +{
 +#define NB_Y_COEFF 15
 +    static const int rct_y_coeff[15][2] = {
 +        {0, 0}, //      4G
 +        {1, 1}, //  R + 2G + B
 +        {2, 2}, // 2R      + 2B
 +        {0, 2}, //      2G + 2B
 +        {2, 0}, // 2R + 2G
 +        {4, 0}, // 4R
 +        {0, 4}, //           4B
 +
 +        {0, 3}, //      1G + 3B
 +        {3, 0}, // 3R + 1G
 +        {3, 1}, // 3R      +  B
 +        {1, 3}, //  R      + 3B
 +        {1, 2}, //  R +  G + 2B
 +        {2, 1}, // 2R +  G +  B
 +        {0, 1}, //      3G +  B
 +        {1, 0}, //  R + 3G
 +    };
 +
 +    int stat[NB_Y_COEFF] = {0};
 +    int x, y, i, p, best;
 +    int16_t *sample[3];
 +    int lbd = fs->bits_per_raw_sample <= 8;
 +
 +    for (y = 0; y < h; y++) {
 +        int lastr=0, lastg=0, lastb=0;
 +        for (p = 0; p < 3; p++)
 +            sample[p] = fs->sample_buffer + p*w;
 +
 +        for (x = 0; x < w; x++) {
 +            int b, g, r;
 +            int ab, ag, ar;
 +            if (lbd) {
 +                unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y));
 +                b =  v        & 0xFF;
 +                g = (v >>  8) & 0xFF;
 +                r = (v >> 16) & 0xFF;
 +            } else {
 +                b = *((const uint16_t*)(src[0] + x*2 + stride[0]*y));
 +                g = *((const uint16_t*)(src[1] + x*2 + stride[1]*y));
 +                r = *((const uint16_t*)(src[2] + x*2 + stride[2]*y));
 +            }
 +
 +            ar = r - lastr;
 +            ag = g - lastg;
 +            ab = b - lastb;
 +            if (x && y) {
 +                int bg = ag - sample[0][x];
 +                int bb = ab - sample[1][x];
 +                int br = ar - sample[2][x];
 +
 +                br -= bg;
 +                bb -= bg;
 +
 +                for (i = 0; i<NB_Y_COEFF; i++) {
 +                    stat[i] += FFABS(bg + ((br*rct_y_coeff[i][0] + bb*rct_y_coeff[i][1])>>2));
 +                }
 +
 +            }
 +            sample[0][x] = ag;
 +            sample[1][x] = ab;
 +            sample[2][x] = ar;
 +
 +            lastr = r;
 +            lastg = g;
 +            lastb = b;
 +        }
 +    }
 +
 +    best = 0;
 +    for (i=1; i<NB_Y_COEFF; i++) {
 +        if (stat[i] < stat[best])
 +            best = i;
 +    }
 +
 +    fs->slice_rct_by_coef = rct_y_coeff[best][1];
 +    fs->slice_rct_ry_coef = rct_y_coeff[best][0];
  }
  
  static int encode_slice(AVCodecContext *c, void *arg)
@@@ -1376,11 -1084,11 +1382,13 @@@ static const AVOption options[] = 
          { "rice", "Golomb rice", 0, AV_OPT_TYPE_CONST,
              { .i64 = AC_GOLOMB_RICE }, INT_MIN, INT_MAX, VE, "coder" },
          { "range_def", "Range with default table", 0, AV_OPT_TYPE_CONST,
 -            { .i64 = AC_RANGE_DEFAULT_TAB }, INT_MIN, INT_MAX, VE, "coder" },
 +            { .i64 = AC_RANGE_DEFAULT_TAB_FORCE }, INT_MIN, INT_MAX, VE, "coder" },
          { "range_tab", "Range with custom table", 0, AV_OPT_TYPE_CONST,
              { .i64 = AC_RANGE_CUSTOM_TAB }, INT_MIN, INT_MAX, VE, "coder" },
 +        { "ac", "Range with custom table (the ac option exists for compatibility and is deprecated)", 0, AV_OPT_TYPE_CONST,
 +            { .i64 = 1 }, INT_MIN, INT_MAX, VE, "coder" },
+     { "context", "Context model", OFFSET(context_model), AV_OPT_TYPE_INT,
+             { .i64 = 0 }, 0, 1, VE },
  
      { NULL }
  };
@@@ -237,15 -165,13 +239,21 @@@ FF_DISABLE_DEPRECATION_WARNING
      avctx->coded_frame->key_frame = 1;
  FF_ENABLE_DEPRECATION_WARNINGS
  #endif
+ #if FF_API_PRIVATE_OPT
+ FF_DISABLE_DEPRECATION_WARNINGS
+     if (avctx->context_model == 1)
+         s->context = avctx->context_model;
+ FF_ENABLE_DEPRECATION_WARNINGS
+ #endif
  
 +    s->bps = desc->comp[0].depth;
 +    s->yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && desc->nb_components >= 2;
 +    s->chroma = desc->nb_components > 2;
 +    s->alpha = !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA);
 +    av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt,
 +                                     &s->chroma_h_shift,
 +                                     &s->chroma_v_shift);
 +
      switch (avctx->pix_fmt) {
      case AV_PIX_FMT_YUV420P:
      case AV_PIX_FMT_YUV422P:
          break;
      default:
          av_log(avctx, AV_LOG_ERROR, "format not supported\n");
 -        return -1;
 +        return AVERROR(EINVAL);
      }
 +    s->n = 1<<s->bps;
 +    s->vlc_n = FFMIN(s->n, MAX_VLC_N);
 +
      avctx->bits_per_coded_sample = s->bitstream_bpp;
 -    s->decorrelate = s->bitstream_bpp >= 24;
 +    s->decorrelate = s->bitstream_bpp >= 24 && !s->yuv && !(desc->flags & AV_PIX_FMT_FLAG_PLANAR);
      s->predictor = avctx->prediction_method;
      s->interlaced = avctx->flags & AV_CODEC_FLAG_INTERLACED_ME ? 1 : 0;
-     if (avctx->context_model == 1) {
-         s->context = avctx->context_model;
+     if (s->context) {
          if (s->flags & (AV_CODEC_FLAG_PASS1 | AV_CODEC_FLAG_PASS2)) {
              av_log(avctx, AV_LOG_ERROR,
                     "context=1 is not compatible with "
                     "2 pass huffyuv encoding\n");
 -            return -1;
 +            return AVERROR(EINVAL);
          }
-     }else s->context= 0;
+     }
  
      if (avctx->codec->id == AV_CODEC_ID_HUFFYUV) {
          if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
              av_log(avctx, AV_LOG_ERROR,
                     "Error: YV12 is not supported by huffyuv; use "
                     "vcodec=ffvhuff or format=422p\n");
 -            return -1;
 +            return AVERROR(EINVAL);
          }
-         if (avctx->context_model) {
+ #if FF_API_PRIVATE_OPT
+         if (s->context) {
              av_log(avctx, AV_LOG_ERROR,
                     "Error: per-frame huffman tables are not supported "
                     "by huffyuv; use vcodec=ffvhuff\n");
 -            return -1;
 +            return AVERROR(EINVAL);
 +        }
 +        if (s->version > 2) {
 +            av_log(avctx, AV_LOG_ERROR,
 +                   "Error: ver>2 is not supported "
 +                   "by huffyuv; use vcodec=ffvhuff\n");
 +            return AVERROR(EINVAL);
          }
+ #endif
          if (s->interlaced != ( s->height > 288 ))
              av_log(avctx, AV_LOG_INFO,
                     "using huffyuv 2.2.0 or newer interlacing flag\n");
@@@ -1043,27 -695,9 +1052,39 @@@ static av_cold int encode_end(AVCodecCo
      return 0;
  }
  
- static const AVOption options[] = {
-     { "non_deterministic", "Allow multithreading for e.g. context=1 at the expense of determinism",
-       offsetof(HYuvContext, non_determ), AV_OPT_TYPE_BOOL, { .i64 = 1 },
-       0, 1, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ #define OFFSET(x) offsetof(HYuvContext, x)
+ #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
++#define COMMON_OPTIONS \
++    { "non_deterministic", "Allow multithreading for e.g. context=1 at the expense of determinism", \
++      OFFSET(non_determ), AV_OPT_TYPE_BOOL, { .i64 = 1 }, \
++      0, 1, VE }, \
++
++static const AVOption normal_options[] = {
++    COMMON_OPTIONS
++    { NULL },
++};
++
++static const AVOption ff_options[] = {
++    COMMON_OPTIONS
++    { "context", "Set per-frame huffman tables", OFFSET(context), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
 +    { NULL },
 +};
 +
 +static const AVClass normal_class = {
 +    .class_name = "huffyuv",
 +    .item_name  = av_default_item_name,
-     .option     = options,
++    .option     = normal_options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +static const AVClass ff_class = {
 +    .class_name = "ffvhuff",
 +    .item_name  = av_default_item_name,
-     .option     = options,
++    .option     = ff_options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  AVCodec ff_huffyuv_encoder = {
      .name           = "huffyuv",
      .long_name      = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"),
Simple merge