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"
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
#define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
24
typedef vpx_codec_stream_info_t  vp9_stream_info_t;
John Koleszar's avatar
John Koleszar committed
25
26

/* Structures for handling memory allocations */
John Koleszar's avatar
John Koleszar committed
27
typedef enum {
28
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
208
                                  vpx_codec_stream_info_t *si) {
  unsigned int sz;
John Koleszar's avatar
John Koleszar committed
209

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

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

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


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

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

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

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

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

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


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

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

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

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

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

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

    ctx->defer_alloc = 0;
  }

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

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

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

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

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

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

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

John Koleszar's avatar
John Koleszar committed
324
    if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
325
      flags.post_proc_flag =
326
#if CONFIG_POSTPROC_VISUALIZER
327
328
329
330
331
332
333
334
335
          ((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)
          |
336
#endif
337
338
          ctx->postproc_cfg.post_proc_flag;

John Koleszar's avatar
John Koleszar committed
339
340
      flags.deblocking_level      = ctx->postproc_cfg.deblocking_level;
      flags.noise_level           = ctx->postproc_cfg.noise_level;
341
#if CONFIG_POSTPROC_VISUALIZER
John Koleszar's avatar
John Koleszar committed
342
343
344
345
      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;
346
#endif
John Koleszar's avatar
John Koleszar committed
347
    }
John Koleszar's avatar
John Koleszar committed
348

349
    if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
350
      VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
351
352
      res = update_error_state(ctx, &pbi->common.error);
    }
John Koleszar's avatar
John Koleszar committed
353

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

John Koleszar's avatar
John Koleszar committed
361
  return res;
John Koleszar's avatar
John Koleszar committed
362
363
}

John Koleszar's avatar
John Koleszar committed
364
365
366
367
368
369
370
371
372
373
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;

374
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
375
376
377
    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
378
379
380

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

      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
385
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
386
387
388
389
390
391
392
393
394
395
396

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

      *count = frames;
    }
  }
}

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

408
409
  if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM;

John Koleszar's avatar
John Koleszar committed
410
  parse_superframe_index(data, data_sz, sizes, &frames_this_pts);
411
412

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

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

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
    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;
}

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

John Koleszar's avatar
John Koleszar committed
475
  return img;
John Koleszar's avatar
John Koleszar committed
476
477
}

478
479
480
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
481
482
483
484
485
486
  vpx_codec_err_t     res;
  const mem_req_t  *seg_iter = *iter;

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

    *iter = (vpx_codec_iter_t)seg_iter;

493
    if (seg_iter->id != VP9_SEG_MAX) {
John Koleszar's avatar
John Koleszar committed
494
495
496
497
498
499
500
501
502
      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;
503
    } else {
John Koleszar's avatar
John Koleszar committed
504
      res = VPX_CODEC_LIST_END;
505
    }
John Koleszar's avatar
John Koleszar committed
506
507
508
  } while (!mmap->sz && res != VPX_CODEC_LIST_END);

  return res;
John Koleszar's avatar
John Koleszar committed
509
510
}

511
static vpx_codec_err_t vp9_xma_set_mmap(vpx_codec_ctx_t         *ctx,
John Koleszar's avatar
John Koleszar committed
512
513
514
515
516
                                        const vpx_codec_mmap_t  *mmap) {
  vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
  int i, done;

  if (!ctx->priv) {
517
    if (mmap->id == VP9_SEG_ALG_PRIV) {
John Koleszar's avatar
John Koleszar committed
518
      if (!ctx->priv) {
519
        vp9_init_ctx(ctx, mmap);
John Koleszar's avatar
John Koleszar committed
520
521
        res = VPX_CODEC_OK;
      }
John Koleszar's avatar
John Koleszar committed
522
    }
John Koleszar's avatar
John Koleszar committed
523
  }
John Koleszar's avatar
John Koleszar committed
524

John Koleszar's avatar
John Koleszar committed
525
  done = 1;
John Koleszar's avatar
John Koleszar committed
526

John Koleszar's avatar
John Koleszar committed
527
528
529
530
531
532
  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
533
534
        }

John Koleszar's avatar
John Koleszar committed
535
      done &= (ctx->priv->alg_priv->mmaps[i].base != NULL);
John Koleszar's avatar
John Koleszar committed
536
    }
John Koleszar's avatar
John Koleszar committed
537
538
539
  }

  if (done && !res) {
540
    vp9_finalize_mmaps(ctx->priv->alg_priv);
John Koleszar's avatar
John Koleszar committed
541
    res = ctx->iface->init(ctx, NULL);
John Koleszar's avatar
John Koleszar committed
542
  }
John Koleszar's avatar
John Koleszar committed
543

John Koleszar's avatar
John Koleszar committed
544
  return res;
John Koleszar's avatar
John Koleszar committed
545
546
}

547
548
549
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
550
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
551

John Koleszar's avatar
John Koleszar committed
552
553
554
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
555

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

558
559
    return vp9_set_reference_dec(ctx->pbi,
                                 (VP9_REFFRAME)frame->frame_type, &sd);
560
  } else {
John Koleszar's avatar
John Koleszar committed
561
    return VPX_CODEC_INVALID_PARAM;
562
  }
John Koleszar's avatar
John Koleszar committed
563
564
}

565
566
567
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
568
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
569

John Koleszar's avatar
John Koleszar committed
570
571
572
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
573

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

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

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

599
600
601
static vpx_codec_err_t set_postproc(vpx_codec_alg_priv_t *ctx,
                                    int ctr_id,
                                    va_list args) {
602
#if CONFIG_VP9_POSTPROC
John Koleszar's avatar
John Koleszar committed
603
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
604

John Koleszar's avatar
John Koleszar committed
605
606
607
608
  if (data) {
    ctx->postproc_cfg_set = 1;
    ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
    return VPX_CODEC_OK;
609
  } else {
John Koleszar's avatar
John Koleszar committed
610
    return VPX_CODEC_INVALID_PARAM;
611
  }
John Koleszar's avatar
John Koleszar committed
612
#else
John Koleszar's avatar
John Koleszar committed
613
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
614
615
616
#endif
}

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

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

John Koleszar's avatar
John Koleszar committed
625
626
627
628
629
630
  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);
  }
631

John Koleszar's avatar
John Koleszar committed
632
  return VPX_CODEC_OK;
633
#else
John Koleszar's avatar
John Koleszar committed
634
  return VPX_CODEC_INCAPABLE;
635
636
#endif
}
John Koleszar's avatar
John Koleszar committed
637

638
639
640
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
641
  int *update_info = va_arg(args, int *);
642
  VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
643

John Koleszar's avatar
John Koleszar committed
644
  if (update_info) {
645
    *update_info = pbi->refresh_frame_flags;
646

John Koleszar's avatar
John Koleszar committed
647
    return VPX_CODEC_OK;
648
  } else {
John Koleszar's avatar
John Koleszar committed
649
    return VPX_CODEC_INVALID_PARAM;
650
  }
651
652
653
}


654
655
656
static vpx_codec_err_t get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
                                           int ctrl_id,
                                           va_list args) {
John Koleszar's avatar
John Koleszar committed
657
  int *corrupted = va_arg(args, int *);
658

John Koleszar's avatar
John Koleszar committed
659
  if (corrupted) {
660
    VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
John Koleszar's avatar
John Koleszar committed
661
    *corrupted = pbi->common.frame_to_show->corrupted;
662

John Koleszar's avatar
John Koleszar committed
663
    return VPX_CODEC_OK;
664
  } else {
John Koleszar's avatar
John Koleszar committed
665
    return VPX_CODEC_INVALID_PARAM;
666
  }
667
668
}

669
670
671
672
673
674
675
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;
}

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


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