vp9_dx_iface.c 21.1 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
19
20
#include "vp9/decoder/vp9_onyxd.h"
#include "vp9/decoder/vp9_onyxd_int.h"
#include "vp9/decoder/vp9_read_bit_buffer.h"
John Koleszar's avatar
John Koleszar committed
21
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
22

23
24
#define VP9_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
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
29
  VP9_SEG_ALG_PRIV     = 256,
  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) {
John Koleszar's avatar
John Koleszar committed
103
  vpx_codec_err_t        res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
104

John Koleszar's avatar
John Koleszar committed
105
106
107
108
109
110
  /* 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
111

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

117
    res = vpx_mmap_alloc(&mmap);
John Koleszar's avatar
John Koleszar committed
118

John Koleszar's avatar
John Koleszar committed
119
    if (!res) {
120
      vp9_init_ctx(ctx, &mmap);
John Koleszar's avatar
John Koleszar committed
121

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

John Koleszar's avatar
John Koleszar committed
127
  return res;
John Koleszar's avatar
John Koleszar committed
128
129
}

130
static vpx_codec_err_t vp9_destroy(vpx_codec_alg_priv_t *ctx) {
John Koleszar's avatar
John Koleszar committed
131
  int i;
John Koleszar's avatar
John Koleszar committed
132

133
  vp9_remove_decompressor(ctx->pbi);
John Koleszar's avatar
John Koleszar committed
134

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

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

143
static vpx_codec_err_t vp9_peek_si(const uint8_t         *data,
John Koleszar's avatar
John Koleszar committed
144
                                   unsigned int           data_sz,
John Koleszar's avatar
John Koleszar committed
145
                                   vpx_codec_stream_info_t *si) {
James Zern's avatar
James Zern committed
146
  if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM;
147
148
149
150
  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
151

152
153
154
155
  {
    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);
James Zern's avatar
James Zern committed
156
    if (frame_marker != 0x2) return VPX_CODEC_UNSUP_BITSTREAM;
157
158
159
#if CONFIG_NON420
    if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
#else
James Zern's avatar
James Zern committed
160
    if (version != 0) return VPX_CODEC_UNSUP_BITSTREAM;
161
162
163
164
165
#endif

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

167
    si->is_kf = !vp9_rb_read_bit(&rb);
James Zern's avatar
James Zern committed
168
    if (si->is_kf) {
169
170
      const int sRGB = 7;
      int colorspace;
John Koleszar's avatar
John Koleszar committed
171

172
173
      rb.bit_offset += 1;  // show frame
      rb.bit_offset += 1;  // error resilient
John Koleszar's avatar
John Koleszar committed
174

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
      if (vp9_rb_read_literal(&rb, 8) != SYNC_CODE_0 ||
          vp9_rb_read_literal(&rb, 8) != SYNC_CODE_1 ||
          vp9_rb_read_literal(&rb, 8) != SYNC_CODE_2) {
        return VPX_CODEC_UNSUP_BITSTREAM;
      }

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

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

203
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
204
205
}

206
static vpx_codec_err_t vp9_get_si(vpx_codec_alg_priv_t    *ctx,
John Koleszar's avatar
John Koleszar committed
207
                                  vpx_codec_stream_info_t *si) {
John Koleszar's avatar
John Koleszar committed
208

John Koleszar's avatar
John Koleszar committed
209
  unsigned int sz;
John Koleszar's avatar
John Koleszar committed
210

211
212
  if (si->sz >= sizeof(vp9_stream_info_t))
    sz = sizeof(vp9_stream_info_t);
John Koleszar's avatar
John Koleszar committed
213
214
  else
    sz = sizeof(vpx_codec_stream_info_t);
John Koleszar's avatar
John Koleszar committed
215

John Koleszar's avatar
John Koleszar committed
216
217
  memcpy(si, &ctx->si, sz);
  si->sz = sz;
John Koleszar's avatar
John Koleszar committed
218

John Koleszar's avatar
John Koleszar committed
219
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
220
221
222
223
224
}


static vpx_codec_err_t
update_error_state(vpx_codec_alg_priv_t                 *ctx,
John Koleszar's avatar
John Koleszar committed
225
226
                   const struct vpx_internal_error_info *error) {
  vpx_codec_err_t res;
John Koleszar's avatar
John Koleszar committed
227

John Koleszar's avatar
John Koleszar committed
228
229
230
231
  if ((res = error->error_code))
    ctx->base.err_detail = error->has_detail
                           ? error->detail
                           : NULL;
John Koleszar's avatar
John Koleszar committed
232

John Koleszar's avatar
John Koleszar committed
233
  return res;
John Koleszar's avatar
John Koleszar committed
234
235
}

236
237
238
239
240
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
241
  vpx_codec_err_t res = VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
242

John Koleszar's avatar
John Koleszar committed
243
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
244

John Koleszar's avatar
John Koleszar committed
245
246
247
248
249
  /* 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)
250
    res = ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si);
John Koleszar's avatar
John Koleszar committed
251
252


John Koleszar's avatar
John Koleszar committed
253
254
255
  /* Perform deferred allocations, if required */
  if (!res && ctx->defer_alloc) {
    int i;
John Koleszar's avatar
John Koleszar committed
256

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

John Koleszar's avatar
John Koleszar committed
260
261
      cfg.w = ctx->si.w;
      cfg.h = ctx->si.h;
262
263
264
265
      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
266

John Koleszar's avatar
John Koleszar committed
267
      if (!ctx->mmaps[i].sz)
268
        ctx->mmaps[i].sz = vp9_mem_req_segs[i].calc_sz(&cfg,
John Koleszar's avatar
John Koleszar committed
269
                                                       ctx->base.init_flags);
John Koleszar's avatar
John Koleszar committed
270

271
      res = vpx_mmap_alloc(&ctx->mmaps[i]);
John Koleszar's avatar
John Koleszar committed
272
273
    }

John Koleszar's avatar
John Koleszar committed
274
    if (!res)
275
      vp9_finalize_mmaps(ctx);
John Koleszar's avatar
John Koleszar committed
276
277
278
279
280
281

    ctx->defer_alloc = 0;
  }

  /* Initialize the decoder instance on the first frame*/
  if (!res && !ctx->decoder_init) {
282
    res = vpx_validate_mmaps(&ctx->si, ctx->mmaps,
283
                             vp9_mem_req_segs, NELEMENTS(vp9_mem_req_segs),
284
                             ctx->base.init_flags);
John Koleszar's avatar
John Koleszar committed
285
286

    if (!res) {
287
288
      VP9D_CONFIG oxcf;
      VP9D_PTR optr;
John Koleszar's avatar
John Koleszar committed
289

290
      vp9_initialize_dec();
John Koleszar's avatar
John Koleszar committed
291

292
293
294
      oxcf.width = ctx->si.w;
      oxcf.height = ctx->si.h;
      oxcf.version = 9;
John Koleszar's avatar
John Koleszar committed
295
296
      oxcf.postprocess = 0;
      oxcf.max_threads = ctx->cfg.threads;
297
      oxcf.inv_tile_order = ctx->invert_tile_order;
298
      optr = vp9_create_decompressor(&oxcf);
John Koleszar's avatar
John Koleszar committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

      /* 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
315
316
    }

John Koleszar's avatar
John Koleszar committed
317
318
319
320
321
322
    ctx->decoder_init = 1;
  }

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

John Koleszar's avatar
John Koleszar committed
325
326
    if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
      flags.post_proc_flag = ctx->postproc_cfg.post_proc_flag
327
328
#if CONFIG_POSTPROC_VISUALIZER

329
330
331
332
                             | ((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)
333
#endif
John Koleszar's avatar
John Koleszar committed
334
335
336
;
      flags.deblocking_level      = ctx->postproc_cfg.deblocking_level;
      flags.noise_level           = ctx->postproc_cfg.noise_level;
337
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
338
339
340
341
      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;
342
#endif
John Koleszar's avatar
John Koleszar committed
343
    }
John Koleszar's avatar
John Koleszar committed
344

345
    if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
346
      VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
347
348
      res = update_error_state(ctx, &pbi->common.error);
    }
John Koleszar's avatar
John Koleszar committed
349

350
351
    if (!res && 0 == vp9_get_raw_frame(ctx->pbi, &sd, &time_stamp,
                                       &time_end_stamp, &flags)) {
John Koleszar's avatar
John Koleszar committed
352
353
      yuvconfig2image(&ctx->img, &sd, user_priv);
      ctx->img_avail = 1;
John Koleszar's avatar
John Koleszar committed
354
    }
John Koleszar's avatar
John Koleszar committed
355
  }
John Koleszar's avatar
John Koleszar committed
356

John Koleszar's avatar
John Koleszar committed
357
  return res;
John Koleszar's avatar
John Koleszar committed
358
359
}

John Koleszar's avatar
John Koleszar committed
360
361
362
363
364
365
366
367
368
369
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;

370
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
371
372
373
    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
374
375
376

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

      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
381
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
382
383
384
385
386
387
388
389
390
391
392

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

      *count = frames;
    }
  }
}

393
394
395
396
397
398
399
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;
400
  vpx_codec_err_t res = 0;
John Koleszar's avatar
John Koleszar committed
401
402
403
  uint32_t sizes[8];
  int frames_this_pts, frame_count = 0;

404
405
  if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM;

John Koleszar's avatar
John Koleszar committed
406
  parse_superframe_index(data, data_sz, sizes, &frames_this_pts);
407
408

  do {
John Koleszar's avatar
John Koleszar committed
409
    // Skip over the superframe index, if present
410
    if (data_sz && (*data_start & 0xe0) == 0xc0) {
John Koleszar's avatar
John Koleszar committed
411
      const uint8_t marker = *data_start;
Johann's avatar
Johann committed
412
413
414
      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
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438

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

439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
    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;
}

456
static vpx_image_t *vp9_get_frame(vpx_codec_alg_priv_t  *ctx,
John Koleszar's avatar
John Koleszar committed
457
458
459
460
461
462
463
464
465
466
                                  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
467
    }
John Koleszar's avatar
John Koleszar committed
468
  }
469
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
470

John Koleszar's avatar
John Koleszar committed
471
  return img;
John Koleszar's avatar
John Koleszar committed
472
473
}

474
475
476
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) {
John Koleszar's avatar
John Koleszar committed
477
478
479
480
481
482
  vpx_codec_err_t     res;
  const mem_req_t  *seg_iter = *iter;

  /* Get address of next segment request */
  do {
    if (!seg_iter)
483
484
      seg_iter = vp9_mem_req_segs;
    else if (seg_iter->id != VP9_SEG_MAX)
John Koleszar's avatar
John Koleszar committed
485
486
487
488
      seg_iter++;

    *iter = (vpx_codec_iter_t)seg_iter;

489
    if (seg_iter->id != VP9_SEG_MAX) {
John Koleszar's avatar
John Koleszar committed
490
491
492
493
494
495
496
497
498
499
500
501
502
503
      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
504
505
}

506
static vpx_codec_err_t vp9_xma_set_mmap(vpx_codec_ctx_t         *ctx,
John Koleszar's avatar
John Koleszar committed
507
508
509
510
511
                                        const vpx_codec_mmap_t  *mmap) {
  vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
  int i, done;

  if (!ctx->priv) {
512
    if (mmap->id == VP9_SEG_ALG_PRIV) {
John Koleszar's avatar
John Koleszar committed
513
      if (!ctx->priv) {
514
        vp9_init_ctx(ctx, mmap);
John Koleszar's avatar
John Koleszar committed
515
516
        res = VPX_CODEC_OK;
      }
John Koleszar's avatar
John Koleszar committed
517
    }
John Koleszar's avatar
John Koleszar committed
518
  }
John Koleszar's avatar
John Koleszar committed
519

John Koleszar's avatar
John Koleszar committed
520
  done = 1;
John Koleszar's avatar
John Koleszar committed
521

John Koleszar's avatar
John Koleszar committed
522
523
524
525
526
527
  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
528
529
        }

John Koleszar's avatar
John Koleszar committed
530
      done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
John Koleszar's avatar
John Koleszar committed
531
    }
John Koleszar's avatar
John Koleszar committed
532
533
534
  }

  if (done && !res) {
535
    vp9_finalize_mmaps(ctx->priv->alg_priv);
John Koleszar's avatar
John Koleszar committed
536
    res = ctx->iface->init(ctx, NULL);
John Koleszar's avatar
John Koleszar committed
537
  }
John Koleszar's avatar
John Koleszar committed
538

John Koleszar's avatar
John Koleszar committed
539
  return res;
John Koleszar's avatar
John Koleszar committed
540
541
}

542
543
544
static vpx_codec_err_t set_reference(vpx_codec_alg_priv_t *ctx,
                                     int ctr_id,
                                     va_list args) {
John Koleszar's avatar
John Koleszar committed
545

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

John Koleszar's avatar
John Koleszar committed
548
549
550
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
551

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

554
555
    return vp9_set_reference_dec(ctx->pbi,
                                 (VP9_REFFRAME)frame->frame_type, &sd);
John Koleszar's avatar
John Koleszar committed
556
557
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
558
559
560

}

561
562
563
static vpx_codec_err_t copy_reference(vpx_codec_alg_priv_t *ctx,
                                      int ctr_id,
                                      va_list args) {
John Koleszar's avatar
John Koleszar committed
564

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

John Koleszar's avatar
John Koleszar committed
567
568
569
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
570

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

John Koleszar's avatar
John Koleszar committed
573
574
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
John Koleszar's avatar
John Koleszar committed
575
576
  } else
    return VPX_CODEC_INVALID_PARAM;
John Koleszar's avatar
John Koleszar committed
577
578
579

}

John Koleszar's avatar
John Koleszar committed
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
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;
  }
}

596
597
598
static vpx_codec_err_t set_postproc(vpx_codec_alg_priv_t *ctx,
                                    int ctr_id,
                                    va_list args) {
John Koleszar's avatar
John Koleszar committed
599
#if CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
600
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
601

John Koleszar's avatar
John Koleszar committed
602
603
604
605
606
607
  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
608
609

#else
John Koleszar's avatar
John Koleszar committed
610
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
611
612
613
#endif
}

614
615
616
static vpx_codec_err_t set_dbg_options(vpx_codec_alg_priv_t *ctx,
                                       int ctrl_id,
                                       va_list args) {
617
#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC
John Koleszar's avatar
John Koleszar committed
618
  int data = va_arg(args, int);
619
620
621

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

John Koleszar's avatar
John Koleszar committed
622
623
624
625
626
627
  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);
  }
628

John Koleszar's avatar
John Koleszar committed
629
  return VPX_CODEC_OK;
630
#else
John Koleszar's avatar
John Koleszar committed
631
  return VPX_CODEC_INCAPABLE;
632
633
#endif
}
John Koleszar's avatar
John Koleszar committed
634

635
636
637
static vpx_codec_err_t get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
                                            int ctrl_id,
                                            va_list args) {
John Koleszar's avatar
John Koleszar committed
638
  int *update_info = va_arg(args, int *);
639
  VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
640

John Koleszar's avatar
John Koleszar committed
641
  if (update_info) {
642
    *update_info = pbi->refresh_frame_flags;
643

John Koleszar's avatar
John Koleszar committed
644
645
646
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
647
648
649
}


650
651
652
static vpx_codec_err_t get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
                                           int ctrl_id,
                                           va_list args) {
653

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

John Koleszar's avatar
John Koleszar committed
656
  if (corrupted) {
657
    VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
658
    *corrupted = pbi->common.frame_to_show->corrupted;
659

John Koleszar's avatar
John Koleszar committed
660
661
662
    return VPX_CODEC_OK;
  } else
    return VPX_CODEC_INVALID_PARAM;
663
664
665

}

666
667
668
669
670
671
672
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;
}

673
static vpx_codec_ctrl_fn_map_t ctf_maps[] = {
674
675
676
677
678
679
680
681
682
  {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},
John Koleszar's avatar
John Koleszar committed
683
  {VP9_GET_REFERENCE,             get_reference},
684
  {VP9_INVERT_TILE_DECODE_ORDER,  set_invert_tile_order},
John Koleszar's avatar
John Koleszar committed
685
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
686
687
688
689
690
691
};


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