vp9_dx_iface.c 20 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"
John Koleszar's avatar
John Koleszar committed
17
#include "vpx_version.h"
18
#include "decoder/vp9_onyxd.h"
19
#include "decoder/vp9_onyxd_int.h"
John Koleszar's avatar
John Koleszar committed
20
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
21
22
23
24
25

#define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
typedef vpx_codec_stream_info_t  vp8_stream_info_t;

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

static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t);

John Koleszar's avatar
John Koleszar committed
34
35
36
static const mem_req_t vp8_mem_req_segs[] = {
  {VP8_SEG_ALG_PRIV,    0, 8, VPX_CODEC_MEM_ZERO, vp8_priv_sz},
  {VP8_SEG_MAX, 0, 0, 0, NULL}
John Koleszar's avatar
John Koleszar committed
37
38
};

John Koleszar's avatar
John Koleszar committed
39
40
41
42
43
44
45
struct vpx_codec_alg_priv {
  vpx_codec_priv_t        base;
  vpx_codec_mmap_t        mmaps[NELEMENTS(vp8_mem_req_segs) - 1];
  vpx_codec_dec_cfg_t     cfg;
  vp8_stream_info_t       si;
  int                     defer_alloc;
  int                     decoder_init;
46
  VP9D_PTR                pbi;
John Koleszar's avatar
John Koleszar committed
47
48
  int                     postproc_cfg_set;
  vp8_postproc_cfg_t      postproc_cfg;
49
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
50
51
52
53
54
  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;
55
#endif
John Koleszar's avatar
John Koleszar committed
56
57
58
  vpx_image_t             img;
  int                     img_setup;
  int                     img_avail;
59
  int                     invert_tile_order;
John Koleszar's avatar
John Koleszar committed
60
61
};

62
63
static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si,
                                 vpx_codec_flags_t flags) {
John Koleszar's avatar
John Koleszar committed
64
65
66
67
68
69
70
  /* 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
71
72
}

John Koleszar's avatar
John Koleszar committed
73
74
static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) {
  int i;
John Koleszar's avatar
John Koleszar committed
75

John Koleszar's avatar
John Koleszar committed
76
77
78
79
  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
80

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

John Koleszar's avatar
John Koleszar committed
84
85
86
  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
87

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

John Koleszar's avatar
John Koleszar committed
95
96
static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx) {
  /* nothing to clean up */
John Koleszar's avatar
John Koleszar committed
97
98
}

John Koleszar's avatar
John Koleszar committed
99
100
static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx,
                                vpx_codec_priv_enc_mr_cfg_t *data) {
John Koleszar's avatar
John Koleszar committed
101
  vpx_codec_err_t        res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
102

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

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

115
    res = vpx_mmap_alloc(&mmap);
John Koleszar's avatar
John Koleszar committed
116

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

John Koleszar's avatar
John Koleszar committed
120
121
      ctx->priv->alg_priv->defer_alloc = 1;
      /*post processing level initialized to do nothing */
John Koleszar's avatar
John Koleszar committed
122
    }
John Koleszar's avatar
John Koleszar committed
123
  }
John Koleszar's avatar
John Koleszar committed
124

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

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

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

John Koleszar's avatar
John Koleszar committed
133
134
135
136
  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
137

John Koleszar's avatar
John Koleszar committed
138
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
139
140
141
142
}

static vpx_codec_err_t vp8_peek_si(const uint8_t         *data,
                                   unsigned int           data_sz,
John Koleszar's avatar
John Koleszar committed
143
144
145
                                   vpx_codec_stream_info_t *si) {
  vpx_codec_err_t res = VPX_CODEC_OK;

James Zern's avatar
James Zern committed
146
  if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM;
John Koleszar's avatar
John Koleszar committed
147

James Zern's avatar
James Zern committed
148
149
150
151
152
153
154
155
156
157
  if (data + data_sz <= data) {
    res = VPX_CODEC_INVALID_PARAM;
  } else {
    const int frame_marker = (data[0] >> 6) & 0x3;
    const int version = (data[0] >> 4) & 0x3;
    if (frame_marker != 0x2) return VPX_CODEC_UNSUP_BITSTREAM;
    if (version != 0) return VPX_CODEC_UNSUP_BITSTREAM;

    si->is_kf = !((data[0] >> 2) & 0x1);
    if (si->is_kf) {
158
      const uint8_t *c = data + 1;
John Koleszar's avatar
John Koleszar committed
159

160
      if (c[0] != SYNC_CODE_0 || c[1] != SYNC_CODE_1 || c[2] != SYNC_CODE_2)
James Zern's avatar
James Zern committed
161
        return VPX_CODEC_UNSUP_BITSTREAM;
John Koleszar's avatar
John Koleszar committed
162

James Zern's avatar
James Zern committed
163
164
165
166
      c += 3;
      si->w = (((c[0] & 0xf) << 12) | (c[1] << 4) | ((c[2] >> 4) & 0xf)) + 1;
      si->h = (((c[2] & 0xf) << 12) | (c[3] << 4) | ((c[4] >> 4) & 0xf)) + 1;
    }
John Koleszar's avatar
John Koleszar committed
167
168
169
  }

  return res;
John Koleszar's avatar
John Koleszar committed
170
171
172
}

static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t    *ctx,
John Koleszar's avatar
John Koleszar committed
173
                                  vpx_codec_stream_info_t *si) {
John Koleszar's avatar
John Koleszar committed
174

John Koleszar's avatar
John Koleszar committed
175
  unsigned int sz;
John Koleszar's avatar
John Koleszar committed
176

John Koleszar's avatar
John Koleszar committed
177
178
179
180
  if (si->sz >= sizeof(vp8_stream_info_t))
    sz = sizeof(vp8_stream_info_t);
  else
    sz = sizeof(vpx_codec_stream_info_t);
John Koleszar's avatar
John Koleszar committed
181

John Koleszar's avatar
John Koleszar committed
182
183
  memcpy(si, &ctx->si, sz);
  si->sz = sz;
John Koleszar's avatar
John Koleszar committed
184

John Koleszar's avatar
John Koleszar committed
185
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
186
187
188
189
190
}


static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t                 *ctx,
John Koleszar's avatar
John Koleszar committed
191
192
                   const struct vpx_internal_error_info *error) {
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
193

John Koleszar's avatar
John Koleszar committed
194
195
196
197
  if ((res = error->error_code))
    ctx->base.err_detail = error->has_detail
                           ? error->detail
                           : NULL;
John Koleszar's avatar
John Koleszar committed
198

John Koleszar's avatar
John Koleszar committed
199
  return res;
John Koleszar's avatar
John Koleszar committed
200
201
}

202
203
204
205
206
static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t  *ctx,
                                  const uint8_t        **data,
                                  unsigned int           data_sz,
                                  void                  *user_priv,
                                  long                   deadline) {
John Koleszar's avatar
John Koleszar committed
207
  vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
208

John Koleszar's avatar
John Koleszar committed
209
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
210

John Koleszar's avatar
John Koleszar committed
211
212
213
214
215
  /* 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)
216
    res = ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si);
John Koleszar's avatar
John Koleszar committed
217
218


John Koleszar's avatar
John Koleszar committed
219
220
221
  /* Perform deferred allocations, if required */
  if (!res && ctx->defer_alloc) {
    int i;
John Koleszar's avatar
John Koleszar committed
222

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

John Koleszar's avatar
John Koleszar committed
226
227
228
229
230
231
      cfg.w = ctx->si.w;
      cfg.h = ctx->si.h;
      ctx->mmaps[i].id = vp8_mem_req_segs[i].id;
      ctx->mmaps[i].sz = vp8_mem_req_segs[i].sz;
      ctx->mmaps[i].align = vp8_mem_req_segs[i].align;
      ctx->mmaps[i].flags = vp8_mem_req_segs[i].flags;
John Koleszar's avatar
John Koleszar committed
232

John Koleszar's avatar
John Koleszar committed
233
234
235
      if (!ctx->mmaps[i].sz)
        ctx->mmaps[i].sz = vp8_mem_req_segs[i].calc_sz(&cfg,
                                                       ctx->base.init_flags);
John Koleszar's avatar
John Koleszar committed
236

237
      res = vpx_mmap_alloc(&ctx->mmaps[i]);
John Koleszar's avatar
John Koleszar committed
238
239
    }

John Koleszar's avatar
John Koleszar committed
240
241
242
243
244
245
246
247
    if (!res)
      vp8_finalize_mmaps(ctx);

    ctx->defer_alloc = 0;
  }

  /* Initialize the decoder instance on the first frame*/
  if (!res && !ctx->decoder_init) {
248
249
250
    res = vpx_validate_mmaps(&ctx->si, ctx->mmaps,
                             vp8_mem_req_segs, NELEMENTS(vp8_mem_req_segs),
                             ctx->base.init_flags);
John Koleszar's avatar
John Koleszar committed
251
252

    if (!res) {
253
254
      VP9D_CONFIG oxcf;
      VP9D_PTR optr;
John Koleszar's avatar
John Koleszar committed
255

256
      vp9_initialize_dec();
John Koleszar's avatar
John Koleszar committed
257

258
259
260
      oxcf.width = ctx->si.w;
      oxcf.height = ctx->si.h;
      oxcf.version = 9;
John Koleszar's avatar
John Koleszar committed
261
262
      oxcf.postprocess = 0;
      oxcf.max_threads = ctx->cfg.threads;
263
      oxcf.inv_tile_order = ctx->invert_tile_order;
264
      optr = vp9_create_decompressor(&oxcf);
John Koleszar's avatar
John Koleszar committed
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

      /* 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;
        ctx->postproc_cfg.deblocking_level = 4;
        ctx->postproc_cfg.noise_level = 0;
      }

      if (!optr)
        res = VPX_CODEC_ERROR;
      else
        ctx->pbi = optr;
John Koleszar's avatar
John Koleszar committed
281
282
    }

John Koleszar's avatar
John Koleszar committed
283
284
285
286
287
288
    ctx->decoder_init = 1;
  }

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

John Koleszar's avatar
John Koleszar committed
291
292
    if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
      flags.post_proc_flag = ctx->postproc_cfg.post_proc_flag
293
294
#if CONFIG_POSTPROC_VISUALIZER

295
296
297
298
                             | ((ctx->dbg_color_ref_frame_flag != 0) ? VP9D_DEBUG_CLR_FRM_REF_BLKS : 0)
                             | ((ctx->dbg_color_mb_modes_flag != 0) ? VP9D_DEBUG_CLR_BLK_MODES : 0)
                             | ((ctx->dbg_color_b_modes_flag != 0) ? VP9D_DEBUG_CLR_BLK_MODES : 0)
                             | ((ctx->dbg_display_mv_flag != 0) ? VP9D_DEBUG_DRAW_MV : 0)
299
#endif
John Koleszar's avatar
John Koleszar committed
300
301
302
;
      flags.deblocking_level      = ctx->postproc_cfg.deblocking_level;
      flags.noise_level           = ctx->postproc_cfg.noise_level;
303
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
304
305
306
307
      flags.display_ref_frame_flag = ctx->dbg_color_ref_frame_flag;
      flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag;
      flags.display_b_modes_flag  = ctx->dbg_color_b_modes_flag;
      flags.display_mv_flag       = ctx->dbg_display_mv_flag;
308
#endif
John Koleszar's avatar
John Koleszar committed
309
    }
John Koleszar's avatar
John Koleszar committed
310

311
    if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
312
      VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
313
314
      res = update_error_state(ctx, &pbi->common.error);
    }
John Koleszar's avatar
John Koleszar committed
315

316
317
    if (!res && 0 == vp9_get_raw_frame(ctx->pbi, &sd, &time_stamp,
                                       &time_end_stamp, &flags)) {
John Koleszar's avatar
John Koleszar committed
318
319
      yuvconfig2image(&ctx->img, &sd, user_priv);
      ctx->img_avail = 1;
John Koleszar's avatar
John Koleszar committed
320
    }
John Koleszar's avatar
John Koleszar committed
321
  }
John Koleszar's avatar
John Koleszar committed
322

John Koleszar's avatar
John Koleszar committed
323
  return res;
John Koleszar's avatar
John Koleszar committed
324
325
}

John Koleszar's avatar
John Koleszar committed
326
327
328
329
330
331
332
333
334
335
static void parse_superframe_index(const uint8_t *data,
                                   size_t         data_sz,
                                   uint32_t       sizes[8],
                                   int           *count) {
  uint8_t marker;

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

336
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
337
338
339
    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
340
341
342

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

      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
347
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
348
349
350
351
352
353
354
355
356
357
358

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

      *count = frames;
    }
  }
}

359
360
361
362
363
364
365
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;
366
  vpx_codec_err_t res = 0;
John Koleszar's avatar
John Koleszar committed
367
368
369
370
  uint32_t sizes[8];
  int frames_this_pts, frame_count = 0;

  parse_superframe_index(data, data_sz, sizes, &frames_this_pts);
371
372

  do {
John Koleszar's avatar
John Koleszar committed
373
    // Skip over the superframe index, if present
374
    if (data_sz && (*data_start & 0xe0) == 0xc0) {
John Koleszar's avatar
John Koleszar committed
375
      const uint8_t marker = *data_start;
Johann's avatar
Johann committed
376
377
378
      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
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402

      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++;
    }

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
    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;
}

John Koleszar's avatar
John Koleszar committed
420
static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t  *ctx,
John Koleszar's avatar
John Koleszar committed
421
422
423
424
425
426
427
428
429
430
                                  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
431
    }
John Koleszar's avatar
John Koleszar committed
432
  }
433
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
434

John Koleszar's avatar
John Koleszar committed
435
  return img;
John Koleszar's avatar
John Koleszar committed
436
437
438
439
440
441
}


static
vpx_codec_err_t vp8_xma_get_mmap(const vpx_codec_ctx_t      *ctx,
                                 vpx_codec_mmap_t           *mmap,
John Koleszar's avatar
John Koleszar committed
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
                                 vpx_codec_iter_t           *iter) {
  vpx_codec_err_t     res;
  const mem_req_t  *seg_iter = *iter;

  /* Get address of next segment request */
  do {
    if (!seg_iter)
      seg_iter = vp8_mem_req_segs;
    else if (seg_iter->id != VP8_SEG_MAX)
      seg_iter++;

    *iter = (vpx_codec_iter_t)seg_iter;

    if (seg_iter->id != VP8_SEG_MAX) {
      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;
    } else
      res = VPX_CODEC_LIST_END;
  } while (!mmap->sz && res != VPX_CODEC_LIST_END);

  return res;
John Koleszar's avatar
John Koleszar committed
470
471
472
}

static vpx_codec_err_t vp8_xma_set_mmap(vpx_codec_ctx_t         *ctx,
John Koleszar's avatar
John Koleszar committed
473
474
475
476
477
478
479
480
481
482
                                        const vpx_codec_mmap_t  *mmap) {
  vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
  int i, done;

  if (!ctx->priv) {
    if (mmap->id == VP8_SEG_ALG_PRIV) {
      if (!ctx->priv) {
        vp8_init_ctx(ctx, mmap);
        res = VPX_CODEC_OK;
      }
John Koleszar's avatar
John Koleszar committed
483
    }
John Koleszar's avatar
John Koleszar committed
484
  }
John Koleszar's avatar
John Koleszar committed
485

John Koleszar's avatar
John Koleszar committed
486
  done = 1;
John Koleszar's avatar
John Koleszar committed
487

John Koleszar's avatar
John Koleszar committed
488
489
490
491
492
493
  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
494
495
        }

John Koleszar's avatar
John Koleszar committed
496
      done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
John Koleszar's avatar
John Koleszar committed
497
    }
John Koleszar's avatar
John Koleszar committed
498
499
500
501
  }

  if (done && !res) {
    vp8_finalize_mmaps(ctx->priv->alg_priv);
John Koleszar's avatar
John Koleszar committed
502
    res = ctx->iface->init(ctx, NULL);
John Koleszar's avatar
John Koleszar committed
503
  }
John Koleszar's avatar
John Koleszar committed
504

John Koleszar's avatar
John Koleszar committed
505
  return res;
John Koleszar's avatar
John Koleszar committed
506
507
508
}


509
static vpx_codec_err_t vp9_set_reference(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
510
511
                                         int ctr_id,
                                         va_list args) {
John Koleszar's avatar
John Koleszar committed
512

John Koleszar's avatar
John Koleszar committed
513
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
514

John Koleszar's avatar
John Koleszar committed
515
516
517
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
518

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

521
522
    return vp9_set_reference_dec(ctx->pbi,
                                 (VP9_REFFRAME)frame->frame_type, &sd);
John Koleszar's avatar
John Koleszar committed
523
524
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
525
526
527

}

John Koleszar's avatar
John Koleszar committed
528
529
530
static vpx_codec_err_t vp9_copy_reference(vpx_codec_alg_priv_t *ctx,
                                          int ctr_id,
                                          va_list args) {
John Koleszar's avatar
John Koleszar committed
531

John Koleszar's avatar
John Koleszar committed
532
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
533

John Koleszar's avatar
John Koleszar committed
534
535
536
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
537

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

John Koleszar's avatar
John Koleszar committed
540
541
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
John Koleszar's avatar
John Koleszar committed
542
543
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
544
545
546

}

John Koleszar's avatar
John Koleszar committed
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
                                     int ctr_id,
                                     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;
  }
}

John Koleszar's avatar
John Koleszar committed
563
564
static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx,
                                        int ctr_id,
John Koleszar's avatar
John Koleszar committed
565
                                        va_list args) {
John Koleszar's avatar
John Koleszar committed
566
#if CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
567
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
568

John Koleszar's avatar
John Koleszar committed
569
570
571
572
573
574
  if (data) {
    ctx->postproc_cfg_set = 1;
    ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
575
576

#else
John Koleszar's avatar
John Koleszar committed
577
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
578
579
580
#endif
}

581
static vpx_codec_err_t vp8_set_dbg_options(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
582
583
                                           int ctrl_id,
                                           va_list args) {
584
#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
585
  int data = va_arg(args, int);
586
587
588

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

John Koleszar's avatar
John Koleszar committed
589
590
591
592
593
594
  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);
  }
595

John Koleszar's avatar
John Koleszar committed
596
  return VPX_CODEC_OK;
597
#else
John Koleszar's avatar
John Koleszar committed
598
  return VPX_CODEC_INCAPABLE;
599
600
#endif
}
John Koleszar's avatar
John Koleszar committed
601

602
603
static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
                                                int ctrl_id,
John Koleszar's avatar
John Koleszar committed
604
605
                                                va_list args) {
  int *update_info = va_arg(args, int *);
606
  VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
607

John Koleszar's avatar
John Koleszar committed
608
  if (update_info) {
609
    *update_info = pbi->refresh_frame_flags;
610

John Koleszar's avatar
John Koleszar committed
611
612
613
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
614
615
616
}


617
618
static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
                                               int ctrl_id,
John Koleszar's avatar
John Koleszar committed
619
                                               va_list args) {
620

John Koleszar's avatar
John Koleszar committed
621
  int *corrupted = va_arg(args, int *);
622

John Koleszar's avatar
John Koleszar committed
623
  if (corrupted) {
624
    VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
625
    *corrupted = pbi->common.frame_to_show->corrupted;
626

John Koleszar's avatar
John Koleszar committed
627
628
629
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
630
631
632

}

633
634
635
636
637
638
639
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;
}

640
static vpx_codec_ctrl_fn_map_t ctf_maps[] = {
641
  {VP8_SET_REFERENCE,             vp9_set_reference},
John Koleszar's avatar
John Koleszar committed
642
  {VP8_COPY_REFERENCE,            vp9_copy_reference},
John Koleszar's avatar
John Koleszar committed
643
644
645
646
647
648
649
  {VP8_SET_POSTPROC,              vp8_set_postproc},
  {VP8_SET_DBG_COLOR_REF_FRAME,   vp8_set_dbg_options},
  {VP8_SET_DBG_COLOR_MB_MODES,    vp8_set_dbg_options},
  {VP8_SET_DBG_COLOR_B_MODES,     vp8_set_dbg_options},
  {VP8_SET_DBG_DISPLAY_MV,        vp8_set_dbg_options},
  {VP8D_GET_LAST_REF_UPDATES,     vp8_get_last_ref_updates},
  {VP8D_GET_FRAME_CORRUPTED,      vp8_get_frame_corrupted},
John Koleszar's avatar
John Koleszar committed
650
  {VP9_GET_REFERENCE,             get_reference},
651
  {VP9_INVERT_TILE_DECODE_ORDER,  set_invert_tile_order},
John Koleszar's avatar
John Koleszar committed
652
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
653
654
655
656
657
658
};


#ifndef VERSION_STRING
#define VERSION_STRING
#endif
659
660
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
  "WebM Project VP9 Decoder" VERSION_STRING,
John Koleszar's avatar
John Koleszar committed
661
662
663
664
665
  VPX_CODEC_INTERNAL_ABI_VERSION,
  VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC,
  /* vpx_codec_caps_t          caps; */
  vp8_init,         /* vpx_codec_init_fn_t       init; */
  vp8_destroy,      /* vpx_codec_destroy_fn_t    destroy; */
666
  ctf_maps,         /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
John Koleszar's avatar
John Koleszar committed
667
668
669
670
671
  vp8_xma_get_mmap, /* vpx_codec_get_mmap_fn_t   get_mmap; */
  vp8_xma_set_mmap, /* vpx_codec_set_mmap_fn_t   set_mmap; */
  {
    vp8_peek_si,      /* vpx_codec_peek_si_fn_t    peek_si; */
    vp8_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
672
    vp9_decode,       /* vpx_codec_decode_fn_t     decode; */
John Koleszar's avatar
John Koleszar committed
673
674
675
676
677
678
679
680
681
682
683
    vp8_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
  },
  {
    /* encoder functions */
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED
  }
John Koleszar's avatar
John Koleszar committed
684
};