vp9_dx_iface.c 20.9 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 13
 */


#include <stdlib.h>
#include <string.h>
14 15 16
#include "vpx/vpx_decoder.h"
#include "vpx/vp8dx.h"
#include "vpx/internal/vpx_codec_internal.h"
17
#include "./vpx_version.h"
18 19 20
#include "vp9/decoder/vp9_onyxd.h"
#include "vp9/decoder/vp9_onyxd_int.h"
#include "vp9/decoder/vp9_read_bit_buffer.h"
21
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
22

23
#define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
24
typedef vpx_codec_stream_info_t  vp9_stream_info_t;
John Koleszar's avatar
John Koleszar committed
25 26

/* Structures for handling memory allocations */
John Koleszar's avatar
John Koleszar committed
27
typedef enum {
28
  VP9_SEG_ALG_PRIV = 256,
29
  VP9_SEG_MAX
John Koleszar's avatar
John Koleszar committed
30
} mem_seg_id_t;
31
#define NELEMENTS(x) ((int)(sizeof(x)/sizeof(x[0])))
John Koleszar's avatar
John Koleszar committed
32

33 34
static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si,
                             vpx_codec_flags_t flags);
John Koleszar's avatar
John Koleszar committed
35

36 37 38
static const mem_req_t vp9_mem_req_segs[] = {
  {VP9_SEG_ALG_PRIV, 0, 8, VPX_CODEC_MEM_ZERO, priv_sz},
  {VP9_SEG_MAX, 0, 0, 0, NULL}
John Koleszar's avatar
John Koleszar committed
39 40
};

John Koleszar's avatar
John Koleszar committed
41 42
struct vpx_codec_alg_priv {
  vpx_codec_priv_t        base;
43
  vpx_codec_mmap_t        mmaps[NELEMENTS(vp9_mem_req_segs) - 1];
John Koleszar's avatar
John Koleszar committed
44
  vpx_codec_dec_cfg_t     cfg;
45
  vp9_stream_info_t       si;
John Koleszar's avatar
John Koleszar committed
46 47
  int                     defer_alloc;
  int                     decoder_init;
48
  VP9D_PTR                pbi;
John Koleszar's avatar
John Koleszar committed
49 50
  int                     postproc_cfg_set;
  vp8_postproc_cfg_t      postproc_cfg;
51
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
52 53 54 55 56
  unsigned int            dbg_postproc_flag;
  int                     dbg_color_ref_frame_flag;
  int                     dbg_color_mb_modes_flag;
  int                     dbg_color_b_modes_flag;
  int                     dbg_display_mv_flag;
57
#endif
John Koleszar's avatar
John Koleszar committed
58 59 60
  vpx_image_t             img;
  int                     img_setup;
  int                     img_avail;
61
  int                     invert_tile_order;
John Koleszar's avatar
John Koleszar committed
62 63
};

64 65
static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si,
                             vpx_codec_flags_t flags) {
John Koleszar's avatar
John Koleszar committed
66 67 68 69 70 71 72
  /* Although this declaration is constant, we can't use it in the requested
   * segments list because we want to define the requested segments list
   * before defining the private type (so that the number of memory maps is
   * known)
   */
  (void)si;
  return sizeof(vpx_codec_alg_priv_t);
John Koleszar's avatar
John Koleszar committed
73 74
}

75
static void vp9_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) {
John Koleszar's avatar
John Koleszar committed
76
  int i;
John Koleszar's avatar
John Koleszar committed
77

John Koleszar's avatar
John Koleszar committed
78 79 80 81
  ctx->priv = mmap->base;
  ctx->priv->sz = sizeof(*ctx->priv);
  ctx->priv->iface = ctx->iface;
  ctx->priv->alg_priv = mmap->base;
John Koleszar's avatar
John Koleszar committed
82

John Koleszar's avatar
John Koleszar committed
83
  for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++)
84
    ctx->priv->alg_priv->mmaps[i].id = vp9_mem_req_segs[i].id;
John Koleszar's avatar
John Koleszar committed
85

John Koleszar's avatar
John Koleszar committed
86 87 88
  ctx->priv->alg_priv->mmaps[0] = *mmap;
  ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
  ctx->priv->init_flags = ctx->init_flags;
John Koleszar's avatar
John Koleszar committed
89

John Koleszar's avatar
John Koleszar committed
90 91 92 93 94
  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
95 96
}

97
static void vp9_finalize_mmaps(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
98
  /* nothing to clean up */
John Koleszar's avatar
John Koleszar committed
99 100
}

101
static vpx_codec_err_t vp9_init(vpx_codec_ctx_t *ctx,
John Koleszar's avatar
John Koleszar committed
102
                                vpx_codec_priv_enc_mr_cfg_t *data) {
103
  vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
104

105 106 107
  // 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
108 109
  if (!ctx->priv) {
    vpx_codec_mmap_t mmap;
John Koleszar's avatar
John Koleszar committed
110

111
    mmap.id = vp9_mem_req_segs[0].id;
John Koleszar's avatar
John Koleszar committed
112
    mmap.sz = sizeof(vpx_codec_alg_priv_t);
113 114
    mmap.align = vp9_mem_req_segs[0].align;
    mmap.flags = vp9_mem_req_segs[0].flags;
John Koleszar's avatar
John Koleszar committed
115

116
    res = vpx_mmap_alloc(&mmap);
John Koleszar's avatar
John Koleszar committed
117
    if (!res) {
118
      vp9_init_ctx(ctx, &mmap);
John Koleszar's avatar
John Koleszar committed
119

John Koleszar's avatar
John Koleszar committed
120
      ctx->priv->alg_priv->defer_alloc = 1;
John Koleszar's avatar
John Koleszar committed
121
    }
John Koleszar's avatar
John Koleszar committed
122
  }
John Koleszar's avatar
John Koleszar committed
123

John Koleszar's avatar
John Koleszar committed
124
  return res;
John Koleszar's avatar
John Koleszar committed
125 126
}

127
static vpx_codec_err_t vp9_destroy(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
128
  int i;
John Koleszar's avatar
John Koleszar committed
129

130
  vp9_remove_decompressor(ctx->pbi);
John Koleszar's avatar
John Koleszar committed
131

John Koleszar's avatar
John Koleszar committed
132 133 134 135
  for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--) {
    if (ctx->mmaps[i].dtor)
      ctx->mmaps[i].dtor(&ctx->mmaps[i]);
  }
John Koleszar's avatar
John Koleszar committed
136

John Koleszar's avatar
John Koleszar committed
137
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
138 139
}

140
static vpx_codec_err_t vp9_peek_si(const uint8_t *data, unsigned int data_sz,
John Koleszar's avatar
John Koleszar committed
141
                                   vpx_codec_stream_info_t *si) {
142
  if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM;
143 144 145 146
  if (data + data_sz <= data) return VPX_CODEC_INVALID_PARAM;

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

148 149 150 151
  {
    struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
    const int frame_marker = vp9_rb_read_literal(&rb, 2);
    const int version = vp9_rb_read_bit(&rb) | (vp9_rb_read_bit(&rb) << 1);
152 153
    if (frame_marker != VP9_FRAME_MARKER)
      return VPX_CODEC_UNSUP_BITSTREAM;
154 155 156
#if CONFIG_NON420
    if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
#else
157
    if (version != 0) return VPX_CODEC_UNSUP_BITSTREAM;
158 159 160 161 162
#endif

    if (vp9_rb_read_bit(&rb)) {  // show an existing frame
      return VPX_CODEC_OK;
    }
163

164
    si->is_kf = !vp9_rb_read_bit(&rb);
165
    if (si->is_kf) {
166 167
      const int sRGB = 7;
      int colorspace;
John Koleszar's avatar
John Koleszar committed
168

169 170
      rb.bit_offset += 1;  // show frame
      rb.bit_offset += 1;  // error resilient
John Koleszar's avatar
John Koleszar committed
171

172 173 174
      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) {
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
        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;
197
    }
John Koleszar's avatar
John Koleszar committed
198 199
  }

200
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
201 202
}

203
static vpx_codec_err_t vp9_get_si(vpx_codec_alg_priv_t    *ctx,
John Koleszar's avatar
John Koleszar committed
204
                                  vpx_codec_stream_info_t *si) {
205 206 207
  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
208 209
  memcpy(si, &ctx->si, sz);
  si->sz = sz;
John Koleszar's avatar
John Koleszar committed
210

John Koleszar's avatar
John Koleszar committed
211
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
212 213 214
}


215 216 217 218
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
219

220
  return error->error_code;
John Koleszar's avatar
John Koleszar committed
221 222
}

223 224 225
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) {
John Koleszar's avatar
John Koleszar committed
226
  vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
227

John Koleszar's avatar
John Koleszar committed
228
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
229

John Koleszar's avatar
John Koleszar committed
230 231 232 233 234
  /* 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.
   */
  if (!ctx->si.h)
235
    res = ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si);
John Koleszar's avatar
John Koleszar committed
236 237


John Koleszar's avatar
John Koleszar committed
238 239 240
  /* Perform deferred allocations, if required */
  if (!res && ctx->defer_alloc) {
    int i;
John Koleszar's avatar
John Koleszar committed
241

John Koleszar's avatar
John Koleszar committed
242 243
    for (i = 1; !res && i < NELEMENTS(ctx->mmaps); i++) {
      vpx_codec_dec_cfg_t cfg;
John Koleszar's avatar
John Koleszar committed
244

John Koleszar's avatar
John Koleszar committed
245 246
      cfg.w = ctx->si.w;
      cfg.h = ctx->si.h;
247 248 249 250
      ctx->mmaps[i].id = vp9_mem_req_segs[i].id;
      ctx->mmaps[i].sz = vp9_mem_req_segs[i].sz;
      ctx->mmaps[i].align = vp9_mem_req_segs[i].align;
      ctx->mmaps[i].flags = vp9_mem_req_segs[i].flags;
John Koleszar's avatar
John Koleszar committed
251

John Koleszar's avatar
John Koleszar committed
252
      if (!ctx->mmaps[i].sz)
253
        ctx->mmaps[i].sz = vp9_mem_req_segs[i].calc_sz(&cfg,
John Koleszar's avatar
John Koleszar committed
254
                                                       ctx->base.init_flags);
John Koleszar's avatar
John Koleszar committed
255

256
      res = vpx_mmap_alloc(&ctx->mmaps[i]);
John Koleszar's avatar
John Koleszar committed
257 258
    }

John Koleszar's avatar
John Koleszar committed
259
    if (!res)
260
      vp9_finalize_mmaps(ctx);
John Koleszar's avatar
John Koleszar committed
261 262 263 264 265 266

    ctx->defer_alloc = 0;
  }

  /* Initialize the decoder instance on the first frame*/
  if (!res && !ctx->decoder_init) {
267
    res = vpx_validate_mmaps(&ctx->si, ctx->mmaps,
268
                             vp9_mem_req_segs, NELEMENTS(vp9_mem_req_segs),
269
                             ctx->base.init_flags);
John Koleszar's avatar
John Koleszar committed
270 271

    if (!res) {
272 273
      VP9D_CONFIG oxcf;
      VP9D_PTR optr;
John Koleszar's avatar
John Koleszar committed
274

275
      vp9_initialize_dec();
John Koleszar's avatar
John Koleszar committed
276

277 278 279
      oxcf.width = ctx->si.w;
      oxcf.height = ctx->si.h;
      oxcf.version = 9;
John Koleszar's avatar
John Koleszar committed
280 281
      oxcf.postprocess = 0;
      oxcf.max_threads = ctx->cfg.threads;
282
      oxcf.inv_tile_order = ctx->invert_tile_order;
283
      optr = vp9_create_decompressor(&oxcf);
John Koleszar's avatar
John Koleszar committed
284

285 286 287 288 289
      // 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)) {
        ctx->postproc_cfg.post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
John Koleszar's avatar
John Koleszar committed
290 291 292 293
        ctx->postproc_cfg.deblocking_level = 4;
        ctx->postproc_cfg.noise_level = 0;
      }

294
      if (!optr)
John Koleszar's avatar
John Koleszar committed
295
        res = VPX_CODEC_ERROR;
296
      else
John Koleszar's avatar
John Koleszar committed
297
        ctx->pbi = optr;
John Koleszar's avatar
John Koleszar committed
298 299
    }

John Koleszar's avatar
John Koleszar committed
300 301 302 303 304 305
    ctx->decoder_init = 1;
  }

  if (!res && ctx->pbi) {
    YV12_BUFFER_CONFIG sd;
    int64_t time_stamp = 0, time_end_stamp = 0;
306
    vp9_ppflags_t flags = {0};
John Koleszar's avatar
John Koleszar committed
307

John Koleszar's avatar
John Koleszar committed
308
    if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
309
      flags.post_proc_flag =
310
#if CONFIG_POSTPROC_VISUALIZER
311 312 313 314
          (ctx->dbg_color_ref_frame_flag ? VP9D_DEBUG_CLR_FRM_REF_BLKS : 0) |
          (ctx->dbg_color_mb_modes_flag ? VP9D_DEBUG_CLR_BLK_MODES : 0) |
          (ctx->dbg_color_b_modes_flag ? VP9D_DEBUG_CLR_BLK_MODES : 0) |
          (ctx->dbg_display_mv_flag ? VP9D_DEBUG_DRAW_MV : 0) |
315
#endif
316 317
          ctx->postproc_cfg.post_proc_flag;

318 319
      flags.deblocking_level = ctx->postproc_cfg.deblocking_level;
      flags.noise_level = ctx->postproc_cfg.noise_level;
320
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
321 322
      flags.display_ref_frame_flag = ctx->dbg_color_ref_frame_flag;
      flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag;
323 324
      flags.display_b_modes_flag = ctx->dbg_color_b_modes_flag;
      flags.display_mv_flag = ctx->dbg_display_mv_flag;
325
#endif
John Koleszar's avatar
John Koleszar committed
326
    }
John Koleszar's avatar
John Koleszar committed
327

328
    if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
329
      VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
330 331
      res = update_error_state(ctx, &pbi->common.error);
    }
John Koleszar's avatar
John Koleszar committed
332

333 334
    if (!res && 0 == vp9_get_raw_frame(ctx->pbi, &sd, &time_stamp,
                                       &time_end_stamp, &flags)) {
John Koleszar's avatar
John Koleszar committed
335 336
      yuvconfig2image(&ctx->img, &sd, user_priv);
      ctx->img_avail = 1;
John Koleszar's avatar
John Koleszar committed
337
    }
John Koleszar's avatar
John Koleszar committed
338
  }
John Koleszar's avatar
John Koleszar committed
339

John Koleszar's avatar
John Koleszar committed
340
  return res;
John Koleszar's avatar
John Koleszar committed
341 342
}

343 344
static void parse_superframe_index(const uint8_t *data, size_t data_sz,
                                   uint32_t sizes[8], int *count) {
John Koleszar's avatar
John Koleszar committed
345 346 347 348 349 350
  uint8_t marker;

  assert(data_sz);
  marker = data[data_sz - 1];
  *count = 0;

351
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
352 353 354
    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
355 356 357

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

      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
362
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
363 364 365 366 367 368 369 370 371 372 373

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

      *count = frames;
    }
  }
}

374 375 376 377 378 379 380
static vpx_codec_err_t vp9_decode(vpx_codec_alg_priv_t  *ctx,
                                  const uint8_t         *data,
                                  unsigned int           data_sz,
                                  void                  *user_priv,
                                  long                   deadline) {
  const uint8_t *data_start = data;
  const uint8_t *data_end = data + data_sz;
381
  vpx_codec_err_t res = 0;
John Koleszar's avatar
John Koleszar committed
382 383 384
  uint32_t sizes[8];
  int frames_this_pts, frame_count = 0;

385 386
  if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM;

John Koleszar's avatar
John Koleszar committed
387
  parse_superframe_index(data, data_sz, sizes, &frames_this_pts);
388 389

  do {
John Koleszar's avatar
John Koleszar committed
390
    // Skip over the superframe index, if present
391
    if (data_sz && (*data_start & 0xe0) == 0xc0) {
John Koleszar's avatar
John Koleszar committed
392
      const uint8_t marker = *data_start;
Johann's avatar
Johann committed
393 394 395
      const uint32_t frames = (marker & 0x7) + 1;
      const uint32_t mag = ((marker >> 3) & 0x3) + 1;
      const uint32_t index_sz = 2 + mag * frames;
John Koleszar's avatar
John Koleszar committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

      if (data_sz >= index_sz && data_start[index_sz - 1] == marker) {
        data_start += index_sz;
        data_sz -= index_sz;
        if (data_start < data_end)
          continue;
        else
          break;
      }
    }

    // Use the correct size for this frame, if an index is present.
    if (frames_this_pts) {
      uint32_t this_sz = sizes[frame_count];

      if (data_sz < this_sz) {
        ctx->base.err_detail = "Invalid frame size in index";
        return VPX_CODEC_CORRUPT_FRAME;
      }

      data_sz = this_sz;
      frame_count++;
    }

420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
    res = decode_one(ctx, &data_start, data_sz, user_priv, deadline);
    assert(data_start >= data);
    assert(data_start <= data_end);

    /* Early exit if there was a decode error */
    if (res)
      break;

    /* Account for suboptimal termination by the encoder. */
    while (data_start < data_end && *data_start == 0)
      data_start++;

    data_sz = data_end - data_start;
  } while (data_start < data_end);
  return res;
}

437
static vpx_image_t *vp9_get_frame(vpx_codec_alg_priv_t  *ctx,
John Koleszar's avatar
John Koleszar committed
438 439 440 441 442 443 444 445 446 447
                                  vpx_codec_iter_t      *iter) {
  vpx_image_t *img = NULL;

  if (ctx->img_avail) {
    /* iter acts as a flip flop, so an image is only returned on the first
     * call to get_frame.
     */
    if (!(*iter)) {
      img = &ctx->img;
      *iter = img;
John Koleszar's avatar
John Koleszar committed
448
    }
John Koleszar's avatar
John Koleszar committed
449
  }
450
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
451

John Koleszar's avatar
John Koleszar committed
452
  return img;
John Koleszar's avatar
John Koleszar committed
453 454
}

455 456 457 458 459
static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t *ctx,
                                        vpx_codec_mmap_t *mmap,
                                        vpx_codec_iter_t *iter) {
  vpx_codec_err_t res;
  const mem_req_t *seg_iter = *iter;
John Koleszar's avatar
John Koleszar committed
460 461 462 463

  /* Get address of next segment request */
  do {
    if (!seg_iter)
464 465
      seg_iter = vp9_mem_req_segs;
    else if (seg_iter->id != VP9_SEG_MAX)
John Koleszar's avatar
John Koleszar committed
466 467 468 469
      seg_iter++;

    *iter = (vpx_codec_iter_t)seg_iter;

470
    if (seg_iter->id != VP9_SEG_MAX) {
John Koleszar's avatar
John Koleszar committed
471 472 473 474 475 476 477 478 479
      mmap->id = seg_iter->id;
      mmap->sz = seg_iter->sz;
      mmap->align = seg_iter->align;
      mmap->flags = seg_iter->flags;

      if (!seg_iter->sz)
        mmap->sz = seg_iter->calc_sz(ctx->config.dec, ctx->init_flags);

      res = VPX_CODEC_OK;
480
    } else {
John Koleszar's avatar
John Koleszar committed
481
      res = VPX_CODEC_LIST_END;
482
    }
John Koleszar's avatar
John Koleszar committed
483 484 485
  } while (!mmap->sz && res != VPX_CODEC_LIST_END);

  return res;
John Koleszar's avatar
John Koleszar committed
486 487
}

488
static vpx_codec_err_t vp9_xma_set_mmap(vpx_codec_ctx_t *ctx,
John Koleszar's avatar
John Koleszar committed
489 490 491 492 493
                                        const vpx_codec_mmap_t  *mmap) {
  vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
  int i, done;

  if (!ctx->priv) {
494
    if (mmap->id == VP9_SEG_ALG_PRIV) {
John Koleszar's avatar
John Koleszar committed
495
      if (!ctx->priv) {
496
        vp9_init_ctx(ctx, mmap);
John Koleszar's avatar
John Koleszar committed
497 498
        res = VPX_CODEC_OK;
      }
John Koleszar's avatar
John Koleszar committed
499
    }
John Koleszar's avatar
John Koleszar committed
500
  }
John Koleszar's avatar
John Koleszar committed
501

John Koleszar's avatar
John Koleszar committed
502
  done = 1;
John Koleszar's avatar
John Koleszar committed
503

John Koleszar's avatar
John Koleszar committed
504 505 506 507 508 509
  if (!res && ctx->priv->alg_priv) {
    for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++) {
      if (ctx->priv->alg_priv->mmaps[i].id == mmap->id)
        if (!ctx->priv->alg_priv->mmaps[i].base) {
          ctx->priv->alg_priv->mmaps[i] = *mmap;
          res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
510 511
        }

John Koleszar's avatar
John Koleszar committed
512
      done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
John Koleszar's avatar
John Koleszar committed
513
    }
John Koleszar's avatar
John Koleszar committed
514 515 516
  }

  if (done && !res) {
517
    vp9_finalize_mmaps(ctx->priv->alg_priv);
John Koleszar's avatar
John Koleszar committed
518
    res = ctx->iface->init(ctx, NULL);
John Koleszar's avatar
John Koleszar committed
519
  }
John Koleszar's avatar
John Koleszar committed
520

John Koleszar's avatar
John Koleszar committed
521
  return res;
John Koleszar's avatar
John Koleszar committed
522 523
}

524
static vpx_codec_err_t set_reference(vpx_codec_alg_priv_t *ctx, int ctr_id,
525
                                     va_list args) {
John Koleszar's avatar
John Koleszar committed
526
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
527

John Koleszar's avatar
John Koleszar committed
528 529 530
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
531

John Koleszar's avatar
John Koleszar committed
532
    image2yuvconfig(&frame->img, &sd);
533 534
    return vp9_set_reference_dec(ctx->pbi,
                                 (VP9_REFFRAME)frame->frame_type, &sd);
535
  } else {
John Koleszar's avatar
John Koleszar committed
536
    return VPX_CODEC_INVALID_PARAM;
537
  }
John Koleszar's avatar
John Koleszar committed
538 539
}

540
static vpx_codec_err_t copy_reference(vpx_codec_alg_priv_t *ctx, int ctr_id,
541
                                      va_list args) {
John Koleszar's avatar
John Koleszar committed
542
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
543

John Koleszar's avatar
John Koleszar committed
544 545 546
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
547

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

550 551
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
552
  } else {
John Koleszar's avatar
John Koleszar committed
553
    return VPX_CODEC_INVALID_PARAM;
554
  }
John Koleszar's avatar
John Koleszar committed
555 556
}

557
static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx, int ctr_id,
558 559 560 561 562 563 564 565 566 567 568 569 570 571
                                     va_list args) {
  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;
  }
}

572
static vpx_codec_err_t set_postproc(vpx_codec_alg_priv_t *ctx, int ctr_id,
573
                                    va_list args) {
574
#if CONFIG_VP9_POSTPROC
John Koleszar's avatar
John Koleszar committed
575
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
576

John Koleszar's avatar
John Koleszar committed
577 578 579 580
  if (data) {
    ctx->postproc_cfg_set = 1;
    ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
    return VPX_CODEC_OK;
581
  } else {
John Koleszar's avatar
John Koleszar committed
582
    return VPX_CODEC_INVALID_PARAM;
583
  }
John Koleszar's avatar
John Koleszar committed
584
#else
John Koleszar's avatar
John Koleszar committed
585
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
586 587 588
#endif
}

589
static vpx_codec_err_t set_dbg_options(vpx_codec_alg_priv_t *ctx, int ctrl_id,
590
                                       va_list args) {
591
#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
592
  int data = va_arg(args, int);
593 594 595

#define MAP(id, var) case id: var = data; break;

John Koleszar's avatar
John Koleszar committed
596 597 598 599 600 601
  switch (ctrl_id) {
      MAP(VP8_SET_DBG_COLOR_REF_FRAME,   ctx->dbg_color_ref_frame_flag);
      MAP(VP8_SET_DBG_COLOR_MB_MODES,    ctx->dbg_color_mb_modes_flag);
      MAP(VP8_SET_DBG_COLOR_B_MODES,     ctx->dbg_color_b_modes_flag);
      MAP(VP8_SET_DBG_DISPLAY_MV,        ctx->dbg_display_mv_flag);
  }
602

John Koleszar's avatar
John Koleszar committed
603
  return VPX_CODEC_OK;
604
#else
John Koleszar's avatar
John Koleszar committed
605
  return VPX_CODEC_INCAPABLE;
606 607
#endif
}
John Koleszar's avatar
John Koleszar committed
608

609
static vpx_codec_err_t get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
610
                                            int ctrl_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
611
  int *update_info = va_arg(args, int *);
612
  VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
613

John Koleszar's avatar
John Koleszar committed
614
  if (update_info) {
615
    *update_info = pbi->refresh_frame_flags;
616

John Koleszar's avatar
John Koleszar committed
617
    return VPX_CODEC_OK;
618
  } else {
John Koleszar's avatar
John Koleszar committed
619
    return VPX_CODEC_INVALID_PARAM;
620
  }
621 622 623
}


624
static vpx_codec_err_t get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
625
                                           int ctrl_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
626
  int *corrupted = va_arg(args, int *);
627

John Koleszar's avatar
John Koleszar committed
628
  if (corrupted) {
629
    VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
630 631 632 633
    if (pbi)
      *corrupted = pbi->common.frame_to_show->corrupted;
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
634
    return VPX_CODEC_OK;
635
  } else {
John Koleszar's avatar
John Koleszar committed
636
    return VPX_CODEC_INVALID_PARAM;
637
  }
638 639
}

640
static vpx_codec_err_t get_display_size(vpx_codec_alg_priv_t *ctx,
641
                                        int ctrl_id, va_list args) {
642 643 644
  int *const display_size = va_arg(args, int *);

  if (display_size) {
645
    const VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi;
646 647 648 649 650 651 652 653 654 655 656 657
    if (pbi) {
      display_size[0] = pbi->common.display_width;
      display_size[1] = pbi->common.display_height;
    } else {
      return VPX_CODEC_ERROR;
    }
    return VPX_CODEC_OK;
  } else {
    return VPX_CODEC_INVALID_PARAM;
  }
}

658 659 660 661 662 663 664
static vpx_codec_err_t set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
                                             int ctr_id,
                                             va_list args) {
  ctx->invert_tile_order = va_arg(args, int);
  return VPX_CODEC_OK;
}

665
static vpx_codec_ctrl_fn_map_t ctf_maps[] = {
666 667 668 669 670 671 672 673 674
  {VP8_SET_REFERENCE,             set_reference},
  {VP8_COPY_REFERENCE,            copy_reference},
  {VP8_SET_POSTPROC,              set_postproc},
  {VP8_SET_DBG_COLOR_REF_FRAME,   set_dbg_options},
  {VP8_SET_DBG_COLOR_MB_MODES,    set_dbg_options},
  {VP8_SET_DBG_COLOR_B_MODES,     set_dbg_options},
  {VP8_SET_DBG_DISPLAY_MV,        set_dbg_options},
  {VP8D_GET_LAST_REF_UPDATES,     get_last_ref_updates},
  {VP8D_GET_FRAME_CORRUPTED,      get_frame_corrupted},
675
  {VP9_GET_REFERENCE,             get_reference},
676
  {VP9D_GET_DISPLAY_SIZE,         get_display_size},
677
  {VP9_INVERT_TILE_DECODE_ORDER,  set_invert_tile_order},
John Koleszar's avatar
John Koleszar committed
678
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
679 680 681 682 683 684
};


#ifndef VERSION_STRING
#define VERSION_STRING
#endif
685 686
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
  "WebM Project VP9 Decoder" VERSION_STRING,
John Koleszar's avatar
John Koleszar committed
687
  VPX_CODEC_INTERNAL_ABI_VERSION,
688
  VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC,
John Koleszar's avatar
John Koleszar committed
689
  /* vpx_codec_caps_t          caps; */
690 691
  vp9_init,         /* vpx_codec_init_fn_t       init; */
  vp9_destroy,      /* vpx_codec_destroy_fn_t    destroy; */
692
  ctf_maps,         /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
693 694
  vp9_xma_get_mmap, /* vpx_codec_get_mmap_fn_t   get_mmap; */
  vp9_xma_set_mmap, /* vpx_codec_set_mmap_fn_t   set_mmap; */
695
  { // NOLINT
696 697
    vp9_peek_si,      /* vpx_codec_peek_si_fn_t    peek_si; */
    vp9_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
698
    vp9_decode,       /* vpx_codec_decode_fn_t     decode; */
699
    vp9_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
John Koleszar's avatar
John Koleszar committed
700
  },
701
  { // NOLINT
John Koleszar's avatar
John Koleszar committed
702 703 704 705 706 707 708 709
    /* encoder functions */
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED
  }
John Koleszar's avatar
John Koleszar committed
710
};