vp9_dx_iface.c 19.3 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9 10 11 12
 */

#include <stdlib.h>
#include <string.h>
13

14
#include "./vpx_version.h"
15 16 17 18 19

#include "vpx/internal/vpx_codec_internal.h"
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"

20
#include "vp9/common/vp9_frame_buffers.h"
21

22
#include "vp9/decoder/vp9_decoder.h"
23
#include "vp9/decoder/vp9_read_bit_buffer.h"
24

John Koleszar's avatar
John Koleszar committed
25
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
26

27
#define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
28 29

typedef vpx_codec_stream_info_t vp9_stream_info_t;
John Koleszar's avatar
John Koleszar committed
30

John Koleszar's avatar
John Koleszar committed
31 32 33
struct vpx_codec_alg_priv {
  vpx_codec_priv_t        base;
  vpx_codec_dec_cfg_t     cfg;
34
  vp9_stream_info_t       si;
35
  struct VP9Decoder *pbi;
John Koleszar's avatar
John Koleszar committed
36 37
  int                     postproc_cfg_set;
  vp8_postproc_cfg_t      postproc_cfg;
38 39
  vpx_decrypt_cb          decrypt_cb;
  void                   *decrypt_state;
John Koleszar's avatar
John Koleszar committed
40 41
  vpx_image_t             img;
  int                     img_avail;
42
  int                     invert_tile_order;
43 44 45 46 47

  // External frame buffer info to save for VP9 common.
  void *ext_priv;  // Private data associated with the external frame buffers.
  vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
  vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
John Koleszar's avatar
John Koleszar committed
48 49
};

50 51
static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
                            vpx_codec_priv_enc_mr_cfg_t *data) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
52 53 54
  // This function only allocates space for the vpx_codec_alg_priv_t
  // structure. More memory may be required at the time the stream
  // information becomes known.
John Koleszar's avatar
John Koleszar committed
55
  if (!ctx->priv) {
56 57
    vpx_codec_alg_priv_t *alg_priv = vpx_memalign(32, sizeof(*alg_priv));
    if (alg_priv == NULL)
58 59
      return VPX_CODEC_MEM_ERROR;

60 61 62
    vp9_zero(*alg_priv);

    ctx->priv = (vpx_codec_priv_t *)alg_priv;
63 64
    ctx->priv->sz = sizeof(*ctx->priv);
    ctx->priv->iface = ctx->iface;
65
    ctx->priv->alg_priv = alg_priv;
66 67 68 69 70 71 72
    ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
    ctx->priv->init_flags = ctx->init_flags;

    if (ctx->config.dec) {
      // Update the reference to the config structure to an internal copy.
      ctx->priv->alg_priv->cfg = *ctx->config.dec;
      ctx->config.dec = &ctx->priv->alg_priv->cfg;
John Koleszar's avatar
John Koleszar committed
73
    }
John Koleszar's avatar
John Koleszar committed
74
  }
John Koleszar's avatar
John Koleszar committed
75

76
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
77 78
}

79 80 81 82 83
static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
  if (ctx->pbi) {
    vp9_decoder_remove(ctx->pbi);
    ctx->pbi = NULL;
  }
John Koleszar's avatar
John Koleszar committed
84

85 86
  vpx_free(ctx);

John Koleszar's avatar
John Koleszar committed
87
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
88 89
}

90 91 92 93 94 95 96
static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
                                                unsigned int data_sz,
                                                vpx_codec_stream_info_t *si,
                                                vpx_decrypt_cb decrypt_cb,
                                                void *decrypt_state) {
  uint8_t clear_buffer[9];

97 98 99 100 101
  if (data_sz <= 8)
    return VPX_CODEC_UNSUP_BITSTREAM;

  if (data + data_sz <= data)
    return VPX_CODEC_INVALID_PARAM;
102 103 104

  si->is_kf = 0;
  si->w = si->h = 0;
John Koleszar's avatar
John Koleszar committed
105

106 107 108 109 110 111
  if (decrypt_cb) {
    data_sz = MIN(sizeof(clear_buffer), data_sz);
    decrypt_cb(decrypt_state, data, clear_buffer, data_sz);
    data = clear_buffer;
  }

112 113 114
  {
    struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
    const int frame_marker = vp9_rb_read_literal(&rb, 2);
115 116 117
    const int version = vp9_rb_read_bit(&rb);
    (void) vp9_rb_read_bit(&rb);  // unused version bit

118 119
    if (frame_marker != VP9_FRAME_MARKER)
      return VPX_CODEC_UNSUP_BITSTREAM;
120 121 122 123 124
    if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;

    if (vp9_rb_read_bit(&rb)) {  // show an existing frame
      return VPX_CODEC_OK;
    }
James Zern's avatar
James Zern committed
125

126
    si->is_kf = !vp9_rb_read_bit(&rb);
James Zern's avatar
James Zern committed
127
    if (si->is_kf) {
128 129
      const int sRGB = 7;
      int colorspace;
John Koleszar's avatar
John Koleszar committed
130

131 132
      rb.bit_offset += 1;  // show frame
      rb.bit_offset += 1;  // error resilient
John Koleszar's avatar
John Koleszar committed
133

134 135 136
      if (vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_0 ||
          vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_1 ||
          vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_2) {
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
        return VPX_CODEC_UNSUP_BITSTREAM;
      }

      colorspace = vp9_rb_read_literal(&rb, 3);
      if (colorspace != sRGB) {
        rb.bit_offset += 1;  // [16,235] (including xvycc) vs [0,255] range
        if (version == 1) {
          rb.bit_offset += 2;  // subsampling x/y
          rb.bit_offset += 1;  // has extra plane
        }
      } else {
        if (version == 1) {
          rb.bit_offset += 1;  // has extra plane
        } else {
          // RGB is only available in version 1
          return VPX_CODEC_UNSUP_BITSTREAM;
        }
      }

      // TODO(jzern): these are available on non-keyframes in intra only mode.
      si->w = vp9_rb_read_literal(&rb, 16) + 1;
      si->h = vp9_rb_read_literal(&rb, 16) + 1;
James Zern's avatar
James Zern committed
159
    }
John Koleszar's avatar
John Koleszar committed
160 161
  }

162
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
163 164
}

165 166 167 168 169 170
static vpx_codec_err_t decoder_peek_si(const uint8_t *data,
                                       unsigned int data_sz,
                                       vpx_codec_stream_info_t *si) {
  return decoder_peek_si_internal(data, data_sz, si, NULL, NULL);
}

171 172
static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx,
                                      vpx_codec_stream_info_t *si) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
173 174 175
  const size_t sz = (si->sz >= sizeof(vp9_stream_info_t))
                       ? sizeof(vp9_stream_info_t)
                       : sizeof(vpx_codec_stream_info_t);
John Koleszar's avatar
John Koleszar committed
176
  memcpy(si, &ctx->si, sz);
177
  si->sz = (unsigned int)sz;
John Koleszar's avatar
John Koleszar committed
178

John Koleszar's avatar
John Koleszar committed
179
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
180 181
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
182 183 184 185
static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
                           const struct vpx_internal_error_info *error) {
  if (error->error_code)
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;
John Koleszar's avatar
John Koleszar committed
186

Dmitry Kovalev's avatar
Dmitry Kovalev committed
187
  return error->error_code;
John Koleszar's avatar
John Koleszar committed
188 189
}

190 191 192
static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
  VP9_COMMON *const cm = &ctx->pbi->common;

193
  cm->new_fb_idx = -1;
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226

  if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
    cm->get_fb_cb = ctx->get_ext_fb_cb;
    cm->release_fb_cb = ctx->release_ext_fb_cb;
    cm->cb_priv = ctx->ext_priv;
  } else {
    cm->get_fb_cb = vp9_get_frame_buffer;
    cm->release_fb_cb = vp9_release_frame_buffer;

    if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
      vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                         "Failed to initialize internal frame buffers");

    cm->cb_priv = &cm->int_frame_buffers;
  }
}

static void set_default_ppflags(vp8_postproc_cfg_t *cfg) {
  cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
  cfg->deblocking_level = 4;
  cfg->noise_level = 0;
}

static void set_ppflags(const vpx_codec_alg_priv_t *ctx,
                        vp9_ppflags_t *flags) {
  flags->post_proc_flag =
      ctx->postproc_cfg.post_proc_flag;

  flags->deblocking_level = ctx->postproc_cfg.deblocking_level;
  flags->noise_level = ctx->postproc_cfg.noise_level;
}

static void init_decoder(vpx_codec_alg_priv_t *ctx) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
227
  ctx->pbi = vp9_decoder_create();
228 229 230
  if (ctx->pbi == NULL)
    return;

Dmitry Kovalev's avatar
Dmitry Kovalev committed
231 232 233
  ctx->pbi->max_threads = ctx->cfg.threads;
  ctx->pbi->inv_tile_order = ctx->invert_tile_order;

234 235 236 237 238 239 240 241 242
  // If postprocessing was enabled by the application and a
  // configuration has not been provided, default it.
  if (!ctx->postproc_cfg_set &&
      (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC))
    set_default_ppflags(&ctx->postproc_cfg);

  init_buffer_callbacks(ctx);
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
243 244 245
static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
                                  const uint8_t **data, unsigned int data_sz,
                                  void *user_priv, int64_t deadline) {
246 247 248
  YV12_BUFFER_CONFIG sd = { 0 };
  vp9_ppflags_t flags = {0};
  VP9_COMMON *cm = NULL;
John Koleszar's avatar
John Koleszar committed
249

250 251
  (void)deadline;

John Koleszar's avatar
John Koleszar committed
252
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
253

254 255 256
  // Determine the stream parameters. Note that we rely on peek_si to
  // validate that we have a buffer that does not wrap around the top
  // of the heap.
257 258
  if (!ctx->si.h) {
    const vpx_codec_err_t res =
259 260
        decoder_peek_si_internal(*data, data_sz, &ctx->si, ctx->decrypt_cb,
                                 ctx->decrypt_state);
261 262 263
    if (res != VPX_CODEC_OK)
      return res;
  }
264

265
  // Initialize the decoder instance on the first frame
266
  if (ctx->pbi == NULL) {
267 268 269
    init_decoder(ctx);
    if (ctx->pbi == NULL)
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
270 271
  }

272 273 274 275 276
  // Set these even if already initialized.  The caller may have changed the
  // decrypt config between frames.
  ctx->pbi->decrypt_cb = ctx->decrypt_cb;
  ctx->pbi->decrypt_state = ctx->decrypt_state;

277
  cm = &ctx->pbi->common;
John Koleszar's avatar
John Koleszar committed
278

279
  if (vp9_receive_compressed_data(ctx->pbi, data_sz, data))
280
    return update_error_state(ctx, &cm->error);
John Koleszar's avatar
John Koleszar committed
281

282 283
  if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
    set_ppflags(ctx, &flags);
John Koleszar's avatar
John Koleszar committed
284

285
  if (vp9_get_raw_frame(ctx->pbi, &sd, &flags))
286
    return update_error_state(ctx, &cm->error);
287

288 289 290
  yuvconfig2image(&ctx->img, &sd, user_priv);
  ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
  ctx->img_avail = 1;
John Koleszar's avatar
John Koleszar committed
291

292
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
293 294
}

295 296 297 298 299 300 301 302 303 304 305
static INLINE uint8_t read_marker(vpx_decrypt_cb decrypt_cb,
                                  void *decrypt_state,
                                  const uint8_t *data) {
  if (decrypt_cb) {
    uint8_t marker;
    decrypt_cb(decrypt_state, data, &marker, 1);
    return marker;
  }
  return *data;
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
306
static void parse_superframe_index(const uint8_t *data, size_t data_sz,
307 308 309
                                   uint32_t sizes[8], int *count,
                                   vpx_decrypt_cb decrypt_cb,
                                   void *decrypt_state) {
John Koleszar's avatar
John Koleszar committed
310 311 312
  uint8_t marker;

  assert(data_sz);
313
  marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1);
John Koleszar's avatar
John Koleszar committed
314 315
  *count = 0;

316
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
317 318 319
    const uint32_t frames = (marker & 0x7) + 1;
    const uint32_t mag = ((marker >> 3) & 0x3) + 1;
    const size_t index_sz = 2 + mag * frames;
John Koleszar's avatar
John Koleszar committed
320

321 322 323 324
    uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
                                  data + data_sz - index_sz);

    if (data_sz >= index_sz && marker2 == marker) {
John Koleszar's avatar
John Koleszar committed
325
      // found a valid superframe index
Johann's avatar
Johann committed
326
      uint32_t i, j;
327
      const uint8_t *x = &data[data_sz - index_sz + 1];
John Koleszar's avatar
John Koleszar committed
328

329 330 331 332 333 334 335 336
      // frames has a maximum of 8 and mag has a maximum of 4.
      uint8_t clear_buffer[32];
      assert(sizeof(clear_buffer) >= frames * mag);
      if (decrypt_cb) {
        decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
        x = clear_buffer;
      }

John Koleszar's avatar
John Koleszar committed
337
      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
338
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
339 340 341 342 343 344 345 346 347 348 349

        for (j = 0; j < mag; j++)
          this_sz |= (*x++) << (j * 8);
        sizes[i] = this_sz;
      }

      *count = frames;
    }
  }
}

350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
static vpx_codec_err_t decode_one_iter(vpx_codec_alg_priv_t *ctx,
                                       const uint8_t **data_start_ptr,
                                       const uint8_t *data_end,
                                       uint32_t frame_size, void *user_priv,
                                       long deadline) {
  const vpx_codec_err_t res = decode_one(ctx, data_start_ptr, frame_size,
                                         user_priv, deadline);
  if (res != VPX_CODEC_OK)
    return res;

  // Account for suboptimal termination by the encoder.
  while (*data_start_ptr < data_end) {
    const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state,
                                       *data_start_ptr);
    if (marker)
      break;
    (*data_start_ptr)++;
  }

  return VPX_CODEC_OK;
}

372 373 374
static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
                                      const uint8_t *data, unsigned int data_sz,
                                      void *user_priv, long deadline) {
375
  const uint8_t *data_start = data;
376 377 378 379
  const uint8_t *const data_end = data + data_sz;
  vpx_codec_err_t res;
  uint32_t frame_sizes[8];
  int frame_count;
John Koleszar's avatar
John Koleszar committed
380

381 382
  if (data == NULL || data_sz == 0)
    return VPX_CODEC_INVALID_PARAM;
383

384
  parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
385
                         ctx->decrypt_cb, ctx->decrypt_state);
386

387 388
  if (frame_count > 0) {
    int i;
John Koleszar's avatar
John Koleszar committed
389

390 391
    for (i = 0; i < frame_count; ++i) {
      const uint32_t frame_size = frame_sizes[i];
392 393
      if (data_start < data ||
          frame_size > (uint32_t)(data_end - data_start)) {
John Koleszar's avatar
John Koleszar committed
394 395 396 397
        ctx->base.err_detail = "Invalid frame size in index";
        return VPX_CODEC_CORRUPT_FRAME;
      }

398 399 400 401
      res = decode_one_iter(ctx, &data_start, data_end, frame_size,
                            user_priv, deadline);
      if (res != VPX_CODEC_OK)
        return res;
John Koleszar's avatar
John Koleszar committed
402
    }
403
  } else {
404
    while (data_start < data_end) {
405 406
      res = decode_one_iter(ctx, &data_start, data_end,
                            (uint32_t)(data_end - data_start),
407 408 409
                            user_priv, deadline);
      if (res != VPX_CODEC_OK)
        return res;
410
    }
411
  }
412

413
  return VPX_CODEC_OK;
414 415
}

416 417
static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
                                      vpx_codec_iter_t *iter) {
John Koleszar's avatar
John Koleszar committed
418 419 420
  vpx_image_t *img = NULL;

  if (ctx->img_avail) {
421 422
    // iter acts as a flip flop, so an image is only returned on the first
    // call to get_frame.
John Koleszar's avatar
John Koleszar committed
423 424 425
    if (!(*iter)) {
      img = &ctx->img;
      *iter = img;
John Koleszar's avatar
John Koleszar committed
426
    }
John Koleszar's avatar
John Koleszar committed
427
  }
428
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
429

John Koleszar's avatar
John Koleszar committed
430
  return img;
John Koleszar's avatar
John Koleszar committed
431 432
}

433
static vpx_codec_err_t decoder_set_fb_fn(
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
    vpx_codec_alg_priv_t *ctx,
    vpx_get_frame_buffer_cb_fn_t cb_get,
    vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
  if (cb_get == NULL || cb_release == NULL) {
    return VPX_CODEC_INVALID_PARAM;
  } else if (ctx->pbi == NULL) {
    // If the decoder has already been initialized, do not accept changes to
    // the frame buffer functions.
    ctx->get_ext_fb_cb = cb_get;
    ctx->release_ext_fb_cb = cb_release;
    ctx->ext_priv = cb_priv;
    return VPX_CODEC_OK;
  }

  return VPX_CODEC_ERROR;
}

451 452
static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
                                          int ctr_id, va_list args) {
453
  vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
454

John Koleszar's avatar
John Koleszar committed
455
  if (data) {
456
    vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
John Koleszar's avatar
John Koleszar committed
457
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
458

John Koleszar's avatar
John Koleszar committed
459
    image2yuvconfig(&frame->img, &sd);
460
    return vp9_set_reference_dec(&ctx->pbi->common,
461
                                 (VP9_REFFRAME)frame->frame_type, &sd);
462
  } else {
John Koleszar's avatar
John Koleszar committed
463
    return VPX_CODEC_INVALID_PARAM;
464
  }
John Koleszar's avatar
John Koleszar committed
465 466
}

467 468
static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
469
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
470

John Koleszar's avatar
John Koleszar committed
471 472 473
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
474

John Koleszar's avatar
John Koleszar committed
475
    image2yuvconfig(&frame->img, &sd);
John Koleszar's avatar
John Koleszar committed
476

John Koleszar's avatar
John Koleszar committed
477 478
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
479
  } else {
John Koleszar's avatar
John Koleszar committed
480
    return VPX_CODEC_INVALID_PARAM;
481
  }
John Koleszar's avatar
John Koleszar committed
482 483
}

484 485
static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
                                          int ctr_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
486 487 488 489 490 491 492 493 494 495 496 497 498
  vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);

  if (data) {
    YV12_BUFFER_CONFIG* fb;

    vp9_get_reference_dec(ctx->pbi, data->idx, &fb);
    yuvconfig2image(&data->img, fb, NULL);
    return VPX_CODEC_OK;
  } else {
    return VPX_CODEC_INVALID_PARAM;
  }
}

499 500
static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx,
                                         int ctr_id, va_list args) {
501
#if CONFIG_VP9_POSTPROC
John Koleszar's avatar
John Koleszar committed
502
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
503

John Koleszar's avatar
John Koleszar committed
504 505 506 507
  if (data) {
    ctx->postproc_cfg_set = 1;
    ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
    return VPX_CODEC_OK;
508
  } else {
John Koleszar's avatar
John Koleszar committed
509
    return VPX_CODEC_INVALID_PARAM;
510
  }
John Koleszar's avatar
John Koleszar committed
511
#else
John Koleszar's avatar
John Koleszar committed
512
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
513 514 515
#endif
}

516 517
static vpx_codec_err_t ctrl_set_dbg_options(vpx_codec_alg_priv_t *ctx,
                                            int ctrl_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
518
  return VPX_CODEC_INCAPABLE;
519
}
John Koleszar's avatar
John Koleszar committed
520

521 522
static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
                                                 int ctrl_id, va_list args) {
523
  int *const update_info = va_arg(args, int *);
524

John Koleszar's avatar
John Koleszar committed
525
  if (update_info) {
526 527 528 529
    if (ctx->pbi)
      *update_info = ctx->pbi->refresh_frame_flags;
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
530
    return VPX_CODEC_OK;
531
  } else {
John Koleszar's avatar
John Koleszar committed
532
    return VPX_CODEC_INVALID_PARAM;
533
  }
534 535 536
}


537 538
static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
                                                int ctrl_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
539
  int *corrupted = va_arg(args, int *);
540

John Koleszar's avatar
John Koleszar committed
541
  if (corrupted) {
542 543
    if (ctx->pbi)
      *corrupted = ctx->pbi->common.frame_to_show->corrupted;
Yaowu Xu's avatar
Yaowu Xu committed
544 545
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
546
    return VPX_CODEC_OK;
547
  } else {
John Koleszar's avatar
John Koleszar committed
548
    return VPX_CODEC_INVALID_PARAM;
549
  }
550 551
}

552 553
static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
                                             int ctrl_id, va_list args) {
554 555 556
  int *const display_size = va_arg(args, int *);

  if (display_size) {
557 558 559 560
    if (ctx->pbi) {
      const VP9_COMMON *const cm = &ctx->pbi->common;
      display_size[0] = cm->display_width;
      display_size[1] = cm->display_height;
561 562 563 564 565 566 567 568 569
    } else {
      return VPX_CODEC_ERROR;
    }
    return VPX_CODEC_OK;
  } else {
    return VPX_CODEC_INVALID_PARAM;
  }
}

570 571
static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
                                                  int ctr_id, va_list args) {
572 573 574 575
  ctx->invert_tile_order = va_arg(args, int);
  return VPX_CODEC_OK;
}

576 577 578 579 580 581 582 583 584
static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx,
                                          int ctrl_id,
                                          va_list args) {
  vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *);
  ctx->decrypt_cb = init ? init->decrypt_cb : NULL;
  ctx->decrypt_state = init ? init->decrypt_state : NULL;
  return VPX_CODEC_OK;
}

585 586 587 588 589 590 591 592 593 594 595
static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
  {VP8_COPY_REFERENCE,            ctrl_copy_reference},

  // Setters
  {VP8_SET_REFERENCE,             ctrl_set_reference},
  {VP8_SET_POSTPROC,              ctrl_set_postproc},
  {VP8_SET_DBG_COLOR_REF_FRAME,   ctrl_set_dbg_options},
  {VP8_SET_DBG_COLOR_MB_MODES,    ctrl_set_dbg_options},
  {VP8_SET_DBG_COLOR_B_MODES,     ctrl_set_dbg_options},
  {VP8_SET_DBG_DISPLAY_MV,        ctrl_set_dbg_options},
  {VP9_INVERT_TILE_DECODE_ORDER,  ctrl_set_invert_tile_order},
596
  {VPXD_SET_DECRYPTOR,            ctrl_set_decryptor},
597 598 599 600 601 602 603

  // Getters
  {VP8D_GET_LAST_REF_UPDATES,     ctrl_get_last_ref_updates},
  {VP8D_GET_FRAME_CORRUPTED,      ctrl_get_frame_corrupted},
  {VP9_GET_REFERENCE,             ctrl_get_reference},
  {VP9D_GET_DISPLAY_SIZE,         ctrl_get_display_size},

John Koleszar's avatar
John Koleszar committed
604
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
605 606 607 608 609
};

#ifndef VERSION_STRING
#define VERSION_STRING
#endif
610 611
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
  "WebM Project VP9 Decoder" VERSION_STRING,
John Koleszar's avatar
John Koleszar committed
612
  VPX_CODEC_INTERNAL_ABI_VERSION,
613
  VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
614 615 616 617 618 619
      VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER,  // vpx_codec_caps_t
  decoder_init,       // vpx_codec_init_fn_t
  decoder_destroy,    // vpx_codec_destroy_fn_t
  decoder_ctrl_maps,  // vpx_codec_ctrl_fn_map_t
  NOT_IMPLEMENTED,    // vpx_codec_get_mmap_fn_t
  NOT_IMPLEMENTED,    // vpx_codec_set_mmap_fn_t
620
  { // NOLINT
621 622 623 624 625
    decoder_peek_si,    // vpx_codec_peek_si_fn_t
    decoder_get_si,     // vpx_codec_get_si_fn_t
    decoder_decode,     // vpx_codec_decode_fn_t
    decoder_get_frame,  // vpx_codec_frame_get_fn_t
    decoder_set_fb_fn,  // vpx_codec_set_fb_fn_t
John Koleszar's avatar
John Koleszar committed
626
  },
627
  { // NOLINT
John Koleszar's avatar
John Koleszar committed
628 629 630 631 632 633 634
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED
  }
John Koleszar's avatar
John Koleszar committed
635
};