vp9_dx_iface.c 22.5 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
37
38
39
typedef struct {
  unsigned int   id;
  unsigned long  sz;
  unsigned int   align;
  unsigned int   flags;
  unsigned long(*calc_sz)(const vpx_codec_dec_cfg_t *, vpx_codec_flags_t);
John Koleszar's avatar
John Koleszar committed
40
41
} mem_req_t;

John Koleszar's avatar
John Koleszar committed
42
43
44
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
45
46
};

John Koleszar's avatar
John Koleszar committed
47
48
49
50
51
52
53
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;
54
  VP9D_PTR                pbi;
John Koleszar's avatar
John Koleszar committed
55
56
  int                     postproc_cfg_set;
  vp8_postproc_cfg_t      postproc_cfg;
57
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
58
59
60
61
62
  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;
63
#endif
John Koleszar's avatar
John Koleszar committed
64
65
66
  vpx_image_t             img;
  int                     img_setup;
  int                     img_avail;
67
  int                     invert_tile_order;
John Koleszar's avatar
John Koleszar committed
68
69
};

70
71
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
72
73
74
75
76
77
78
  /* 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
79
80
81
}


John Koleszar's avatar
John Koleszar committed
82
83
static void vp8_mmap_dtor(vpx_codec_mmap_t *mmap) {
  free(mmap->priv);
John Koleszar's avatar
John Koleszar committed
84
85
}

John Koleszar's avatar
John Koleszar committed
86
87
88
static vpx_codec_err_t vp8_mmap_alloc(vpx_codec_mmap_t *mmap) {
  vpx_codec_err_t  res;
  unsigned int   align;
John Koleszar's avatar
John Koleszar committed
89

John Koleszar's avatar
John Koleszar committed
90
  align = mmap->align ? mmap->align - 1 : 0;
John Koleszar's avatar
John Koleszar committed
91

John Koleszar's avatar
John Koleszar committed
92
93
94
95
  if (mmap->flags & VPX_CODEC_MEM_ZERO)
    mmap->priv = calloc(1, mmap->sz + align);
  else
    mmap->priv = malloc(mmap->sz + align);
John Koleszar's avatar
John Koleszar committed
96

John Koleszar's avatar
John Koleszar committed
97
98
99
100
  res = (mmap->priv) ? VPX_CODEC_OK : VPX_CODEC_MEM_ERROR;
  mmap->base = (void *)((((uintptr_t)mmap->priv) + align) & ~(uintptr_t)align);
  mmap->dtor = vp8_mmap_dtor;
  return res;
John Koleszar's avatar
John Koleszar committed
101
102
103
}

static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si,
104
105
                                          const vpx_codec_mmap_t *mmaps,
                                          vpx_codec_flags_t init_flags) {
John Koleszar's avatar
John Koleszar committed
106
107
108
109
110
111
112
113
114
  int i;
  vpx_codec_err_t res = VPX_CODEC_OK;

  for (i = 0; i < NELEMENTS(vp8_mem_req_segs) - 1; i++) {
    /* Ensure the segment has been allocated */
    if (!mmaps[i].base) {
      res = VPX_CODEC_MEM_ERROR;
      break;
    }
John Koleszar's avatar
John Koleszar committed
115

John Koleszar's avatar
John Koleszar committed
116
117
118
    /* Verify variable size segment is big enough for the current si. */
    if (vp8_mem_req_segs[i].calc_sz) {
      vpx_codec_dec_cfg_t cfg;
John Koleszar's avatar
John Koleszar committed
119

John Koleszar's avatar
John Koleszar committed
120
121
      cfg.w = si->w;
      cfg.h = si->h;
John Koleszar's avatar
John Koleszar committed
122

John Koleszar's avatar
John Koleszar committed
123
124
125
126
      if (mmaps[i].sz < vp8_mem_req_segs[i].calc_sz(&cfg, init_flags)) {
        res = VPX_CODEC_MEM_ERROR;
        break;
      }
John Koleszar's avatar
John Koleszar committed
127
    }
John Koleszar's avatar
John Koleszar committed
128
  }
John Koleszar's avatar
John Koleszar committed
129

John Koleszar's avatar
John Koleszar committed
130
  return res;
John Koleszar's avatar
John Koleszar committed
131
132
}

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

John Koleszar's avatar
John Koleszar committed
136
137
138
139
  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
140

John Koleszar's avatar
John Koleszar committed
141
142
  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
143

John Koleszar's avatar
John Koleszar committed
144
145
146
  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
147

John Koleszar's avatar
John Koleszar committed
148
149
150
151
152
  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
153
154
}

John Koleszar's avatar
John Koleszar committed
155
156
static void *mmap_lkup(vpx_codec_alg_priv_t *ctx, unsigned int id) {
  int i;
John Koleszar's avatar
John Koleszar committed
157

John Koleszar's avatar
John Koleszar committed
158
159
160
  for (i = 0; i < NELEMENTS(ctx->mmaps); i++)
    if (ctx->mmaps[i].id == id)
      return ctx->mmaps[i].base;
John Koleszar's avatar
John Koleszar committed
161

John Koleszar's avatar
John Koleszar committed
162
  return NULL;
John Koleszar's avatar
John Koleszar committed
163
}
John Koleszar's avatar
John Koleszar committed
164
165
static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx) {
  /* nothing to clean up */
John Koleszar's avatar
John Koleszar committed
166
167
}

John Koleszar's avatar
John Koleszar committed
168
169
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
170
  vpx_codec_err_t        res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
171

John Koleszar's avatar
John Koleszar committed
172
173
174
175
176
177
  /* 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
178

John Koleszar's avatar
John Koleszar committed
179
180
181
182
    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
183

John Koleszar's avatar
John Koleszar committed
184
    res = vp8_mmap_alloc(&mmap);
John Koleszar's avatar
John Koleszar committed
185

John Koleszar's avatar
John Koleszar committed
186
187
    if (!res) {
      vp8_init_ctx(ctx, &mmap);
John Koleszar's avatar
John Koleszar committed
188

John Koleszar's avatar
John Koleszar committed
189
190
      ctx->priv->alg_priv->defer_alloc = 1;
      /*post processing level initialized to do nothing */
John Koleszar's avatar
John Koleszar committed
191
    }
John Koleszar's avatar
John Koleszar committed
192
  }
John Koleszar's avatar
John Koleszar committed
193

John Koleszar's avatar
John Koleszar committed
194
  return res;
John Koleszar's avatar
John Koleszar committed
195
196
}

John Koleszar's avatar
John Koleszar committed
197
198
static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) {
  int i;
John Koleszar's avatar
John Koleszar committed
199

200
  vp9_remove_decompressor(ctx->pbi);
John Koleszar's avatar
John Koleszar committed
201

John Koleszar's avatar
John Koleszar committed
202
203
204
205
  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
206

John Koleszar's avatar
John Koleszar committed
207
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
208
209
210
211
}

static vpx_codec_err_t vp8_peek_si(const uint8_t         *data,
                                   unsigned int           data_sz,
John Koleszar's avatar
John Koleszar committed
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
                                   vpx_codec_stream_info_t *si) {
  vpx_codec_err_t res = VPX_CODEC_OK;

  if (data + data_sz <= data)
    res = VPX_CODEC_INVALID_PARAM;
  else {
    /* Parse uncompresssed part of key frame header.
     * 3 bytes:- including version, frame type and an offset
     * 3 bytes:- sync code (0x9d, 0x01, 0x2a)
     * 4 bytes:- including image width and height in the lowest 14 bits
     *           of each 2-byte value.
     */
    si->is_kf = 0;

    if (data_sz >= 10 && !(data[0] & 0x01)) { /* I-Frame */
      const uint8_t *c = data + 3;
      si->is_kf = 1;

      /* vet via sync code */
      if (c[0] != 0x9d || c[1] != 0x01 || c[2] != 0x2a)
        res = VPX_CODEC_UNSUP_BITSTREAM;

Jingning Han's avatar
Jingning Han committed
234
235
      si->w = (c[3] | (c[4] << 8));
      si->h = (c[5] | (c[6] << 8));
John Koleszar's avatar
John Koleszar committed
236

John Koleszar's avatar
John Koleszar committed
237
238
239
240
241
242
243
244
      /*printf("w=%d, h=%d\n", si->w, si->h);*/
      if (!(si->h | si->w))
        res = VPX_CODEC_UNSUP_BITSTREAM;
    } else
      res = VPX_CODEC_UNSUP_BITSTREAM;
  }

  return res;
John Koleszar's avatar
John Koleszar committed
245
246
247
248

}

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

John Koleszar's avatar
John Koleszar committed
251
  unsigned int sz;
John Koleszar's avatar
John Koleszar committed
252

John Koleszar's avatar
John Koleszar committed
253
254
255
256
  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
257

John Koleszar's avatar
John Koleszar committed
258
259
  memcpy(si, &ctx->si, sz);
  si->sz = sz;
John Koleszar's avatar
John Koleszar committed
260

John Koleszar's avatar
John Koleszar committed
261
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
262
263
264
265
266
}


static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t                 *ctx,
John Koleszar's avatar
John Koleszar committed
267
268
                   const struct vpx_internal_error_info *error) {
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
269

John Koleszar's avatar
John Koleszar committed
270
271
272
273
  if ((res = error->error_code))
    ctx->base.err_detail = error->has_detail
                           ? error->detail
                           : NULL;
John Koleszar's avatar
John Koleszar committed
274

John Koleszar's avatar
John Koleszar committed
275
  return res;
John Koleszar's avatar
John Koleszar committed
276
277
}

278
279
280
281
282
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
283
  vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
284

John Koleszar's avatar
John Koleszar committed
285
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
286

John Koleszar's avatar
John Koleszar committed
287
288
289
290
291
  /* 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)
292
    res = ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si);
John Koleszar's avatar
John Koleszar committed
293
294


John Koleszar's avatar
John Koleszar committed
295
296
297
  /* Perform deferred allocations, if required */
  if (!res && ctx->defer_alloc) {
    int i;
John Koleszar's avatar
John Koleszar committed
298

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

John Koleszar's avatar
John Koleszar committed
302
303
304
305
306
307
      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
308

John Koleszar's avatar
John Koleszar committed
309
310
311
      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
312

John Koleszar's avatar
John Koleszar committed
313
      res = vp8_mmap_alloc(&ctx->mmaps[i]);
John Koleszar's avatar
John Koleszar committed
314
315
    }

John Koleszar's avatar
John Koleszar committed
316
317
318
319
320
321
322
323
324
325
326
    if (!res)
      vp8_finalize_mmaps(ctx);

    ctx->defer_alloc = 0;
  }

  /* Initialize the decoder instance on the first frame*/
  if (!res && !ctx->decoder_init) {
    res = vp8_validate_mmaps(&ctx->si, ctx->mmaps, ctx->base.init_flags);

    if (!res) {
327
328
      VP9D_CONFIG oxcf;
      VP9D_PTR optr;
John Koleszar's avatar
John Koleszar committed
329

330
      vp9_initialize_dec();
John Koleszar's avatar
John Koleszar committed
331
332
333
334
335
336

      oxcf.Width = ctx->si.w;
      oxcf.Height = ctx->si.h;
      oxcf.Version = 9;
      oxcf.postprocess = 0;
      oxcf.max_threads = ctx->cfg.threads;
337
      oxcf.inv_tile_order = ctx->invert_tile_order;
338
      optr = vp9_create_decompressor(&oxcf);
John Koleszar's avatar
John Koleszar committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

      /* 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
355
356
    }

John Koleszar's avatar
John Koleszar committed
357
358
359
360
361
362
    ctx->decoder_init = 1;
  }

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

John Koleszar's avatar
John Koleszar committed
365
366
    if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
      flags.post_proc_flag = ctx->postproc_cfg.post_proc_flag
367
368
#if CONFIG_POSTPROC_VISUALIZER

369
370
371
372
                             | ((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)
373
#endif
John Koleszar's avatar
John Koleszar committed
374
375
376
;
      flags.deblocking_level      = ctx->postproc_cfg.deblocking_level;
      flags.noise_level           = ctx->postproc_cfg.noise_level;
377
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
378
379
380
381
      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;
382
#endif
John Koleszar's avatar
John Koleszar committed
383
    }
John Koleszar's avatar
John Koleszar committed
384

385
    if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
386
      VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
387
388
      res = update_error_state(ctx, &pbi->common.error);
    }
John Koleszar's avatar
John Koleszar committed
389

390
391
    if (!res && 0 == vp9_get_raw_frame(ctx->pbi, &sd, &time_stamp,
                                       &time_end_stamp, &flags)) {
John Koleszar's avatar
John Koleszar committed
392
393
      yuvconfig2image(&ctx->img, &sd, user_priv);
      ctx->img_avail = 1;
John Koleszar's avatar
John Koleszar committed
394
    }
John Koleszar's avatar
John Koleszar committed
395
  }
John Koleszar's avatar
John Koleszar committed
396

John Koleszar's avatar
John Koleszar committed
397
  return res;
John Koleszar's avatar
John Koleszar committed
398
399
}

John Koleszar's avatar
John Koleszar committed
400
401
402
403
404
405
406
407
408
409
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;

410
  if ((marker & 0xe0) == 0xc0) {
John Koleszar's avatar
John Koleszar committed
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
    const int frames = (marker & 0x7) + 1;
    const int mag = ((marker >> 3) & 3) + 1;
    const int index_sz = 2 + mag  * frames;

    if (data_sz >= index_sz && data[data_sz - index_sz] == marker) {
      // found a valid superframe index
      int i, j;
      const uint8_t *x = data + data_sz - index_sz + 1;

      for (i = 0; i < frames; i++) {
        int this_sz = 0;

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

      *count = frames;
    }
  }
}

433
434
435
436
437
438
439
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;
440
  vpx_codec_err_t res = 0;
John Koleszar's avatar
John Koleszar committed
441
442
443
444
  uint32_t sizes[8];
  int frames_this_pts, frame_count = 0;

  parse_superframe_index(data, data_sz, sizes, &frames_this_pts);
445
446

  do {
John Koleszar's avatar
John Koleszar committed
447
    // Skip over the superframe index, if present
448
    if (data_sz && (*data_start & 0xe0) == 0xc0) {
John Koleszar's avatar
John Koleszar committed
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
      const uint8_t marker = *data_start;
      const int frames = (marker & 0x7) + 1;
      const int mag = ((marker >> 3) & 3) + 1;
      const int index_sz = 2 + mag  * frames;

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

477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
    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
494
static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t  *ctx,
John Koleszar's avatar
John Koleszar committed
495
496
497
498
499
500
501
502
503
504
                                  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
505
    }
John Koleszar's avatar
John Koleszar committed
506
  }
John Koleszar's avatar
John Koleszar committed
507

John Koleszar's avatar
John Koleszar committed
508
  return img;
John Koleszar's avatar
John Koleszar committed
509
510
511
512
513
514
}


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
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
                                 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
543
544
545
}

static vpx_codec_err_t vp8_xma_set_mmap(vpx_codec_ctx_t         *ctx,
John Koleszar's avatar
John Koleszar committed
546
547
548
549
550
551
552
553
554
555
                                        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
556
    }
John Koleszar's avatar
John Koleszar committed
557
  }
John Koleszar's avatar
John Koleszar committed
558

John Koleszar's avatar
John Koleszar committed
559
  done = 1;
John Koleszar's avatar
John Koleszar committed
560

John Koleszar's avatar
John Koleszar committed
561
562
563
564
565
566
  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
567
568
        }

John Koleszar's avatar
John Koleszar committed
569
      done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
John Koleszar's avatar
John Koleszar committed
570
    }
John Koleszar's avatar
John Koleszar committed
571
572
573
574
  }

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

John Koleszar's avatar
John Koleszar committed
578
  return res;
John Koleszar's avatar
John Koleszar committed
579
580
581
}

static vpx_codec_err_t image2yuvconfig(const vpx_image_t   *img,
John Koleszar's avatar
John Koleszar committed
582
583
584
585
586
                                       YV12_BUFFER_CONFIG  *yv12) {
  vpx_codec_err_t        res = VPX_CODEC_OK;
  yv12->y_buffer = img->planes[VPX_PLANE_Y];
  yv12->u_buffer = img->planes[VPX_PLANE_U];
  yv12->v_buffer = img->planes[VPX_PLANE_V];
John Koleszar's avatar
John Koleszar committed
587

John Koleszar's avatar
John Koleszar committed
588
589
  yv12->y_crop_width  = img->d_w;
  yv12->y_crop_height = img->d_h;
John Koleszar's avatar
John Koleszar committed
590
591
592
593
  yv12->y_width  = img->d_w;
  yv12->y_height = img->d_h;
  yv12->uv_width = yv12->y_width / 2;
  yv12->uv_height = yv12->y_height / 2;
John Koleszar's avatar
John Koleszar committed
594

John Koleszar's avatar
John Koleszar committed
595
596
  yv12->y_stride = img->stride[VPX_PLANE_Y];
  yv12->uv_stride = img->stride[VPX_PLANE_U];
John Koleszar's avatar
John Koleszar committed
597

John Koleszar's avatar
John Koleszar committed
598
  yv12->border  = (img->stride[VPX_PLANE_Y] - img->d_w) / 2;
599
600
  yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 ||
                   img->fmt == VPX_IMG_FMT_VPXYV12);
John Koleszar's avatar
John Koleszar committed
601

John Koleszar's avatar
John Koleszar committed
602
  return res;
John Koleszar's avatar
John Koleszar committed
603
604
605
}


606
static vpx_codec_err_t vp9_set_reference(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
607
608
                                         int ctr_id,
                                         va_list args) {
John Koleszar's avatar
John Koleszar committed
609

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

John Koleszar's avatar
John Koleszar committed
612
613
614
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
615

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

618
619
    return vp9_set_reference_dec(ctx->pbi,
                                 (VP9_REFFRAME)frame->frame_type, &sd);
John Koleszar's avatar
John Koleszar committed
620
621
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
622
623
624

}

John Koleszar's avatar
John Koleszar committed
625
626
627
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
628

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

John Koleszar's avatar
John Koleszar committed
631
632
633
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
634

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

John Koleszar's avatar
John Koleszar committed
637
638
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
John Koleszar's avatar
John Koleszar committed
639
640
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
641
642
643

}

John Koleszar's avatar
John Koleszar committed
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
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
660
661
static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx,
                                        int ctr_id,
John Koleszar's avatar
John Koleszar committed
662
                                        va_list args) {
John Koleszar's avatar
John Koleszar committed
663
#if CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
664
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
665

John Koleszar's avatar
John Koleszar committed
666
667
668
669
670
671
  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
672
673

#else
John Koleszar's avatar
John Koleszar committed
674
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
675
676
677
#endif
}

678
static vpx_codec_err_t vp8_set_dbg_options(vpx_codec_alg_priv_t *ctx,
John Koleszar's avatar
John Koleszar committed
679
680
                                           int ctrl_id,
                                           va_list args) {
681
#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
682
  int data = va_arg(args, int);
683
684
685

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

John Koleszar's avatar
John Koleszar committed
686
687
688
689
690
691
  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);
  }
692

John Koleszar's avatar
John Koleszar committed
693
  return VPX_CODEC_OK;
694
#else
John Koleszar's avatar
John Koleszar committed
695
  return VPX_CODEC_INCAPABLE;
696
697
#endif
}
John Koleszar's avatar
John Koleszar committed
698

699
700
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
701
702
                                                va_list args) {
  int *update_info = va_arg(args, int *);
703
  VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
704

John Koleszar's avatar
John Koleszar committed
705
  if (update_info) {
706
    *update_info = pbi->refresh_frame_flags;
707

John Koleszar's avatar
John Koleszar committed
708
709
710
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
711
712
713
}


714
715
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
716
                                               va_list args) {
717

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

John Koleszar's avatar
John Koleszar committed
720
  if (corrupted) {
721
    VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
722
    *corrupted = pbi->common.frame_to_show->corrupted;
723

John Koleszar's avatar
John Koleszar committed
724
725
726
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
727
728
729

}

730
731
732
733
734
735
736
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;
}

737
static vpx_codec_ctrl_fn_map_t ctf_maps[] = {
738
  {VP8_SET_REFERENCE,             vp9_set_reference},
John Koleszar's avatar
John Koleszar committed
739
  {VP8_COPY_REFERENCE,            vp9_copy_reference},
John Koleszar's avatar
John Koleszar committed
740
741
742
743
744
745
746
  {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
747
  {VP9_GET_REFERENCE,             get_reference},
748
  {VP9_INVERT_TILE_DECODE_ORDER,  set_invert_tile_order},
John Koleszar's avatar
John Koleszar committed
749
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
750
751
752
753
754
755
};


#ifndef VERSION_STRING
#define VERSION_STRING
#endif
756
757
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
  "WebM Project VP9 Decoder" VERSION_STRING,
John Koleszar's avatar
John Koleszar committed
758
759
760
761
762
  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; */
763
  ctf_maps,         /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
John Koleszar's avatar
John Koleszar committed
764
765
766
767
768
  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; */
769
    vp9_decode,       /* vpx_codec_decode_fn_t     decode; */
John Koleszar's avatar
John Koleszar committed
770
771
772
773
774
775
776
777
778
779
780
    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
781
};