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

#include <stdlib.h>
#include <string.h>
13

14
#include "./vpx_version.h"
15
16
17
18
19

#include "vpx/internal/vpx_codec_internal.h"
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"

20
#include "vp9/common/vp9_frame_buffers.h"
21

22
#include "vp9/decoder/vp9_decoder.h"
23
#include "vp9/decoder/vp9_read_bit_buffer.h"
24

John Koleszar's avatar
John Koleszar committed
25
#include "vp9/vp9_iface_common.h"
John Koleszar's avatar
John Koleszar committed
26

27
#define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
28
29

typedef vpx_codec_stream_info_t vp9_stream_info_t;
John Koleszar's avatar
John Koleszar committed
30

John Koleszar's avatar
John Koleszar committed
31
32
33
struct vpx_codec_alg_priv {
  vpx_codec_priv_t        base;
  vpx_codec_dec_cfg_t     cfg;
34
  vp9_stream_info_t       si;
35
  struct VP9Decoder *pbi;
John Koleszar's avatar
John Koleszar committed
36
37
  int                     postproc_cfg_set;
  vp8_postproc_cfg_t      postproc_cfg;
38
39
  vpx_decrypt_cb          decrypt_cb;
  void                   *decrypt_state;
John Koleszar's avatar
John Koleszar committed
40
  vpx_image_t             img;
41
  int                     invert_tile_order;
42
  int                     frame_parallel_decode;  // frame-based threading.
43
44
45
46
47

  // External frame buffer info to save for VP9 common.
  void *ext_priv;  // Private data associated with the external frame buffers.
  vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
  vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
John Koleszar's avatar
John Koleszar committed
48
49
};

50
static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
51
                                    vpx_codec_priv_enc_mr_cfg_t *data) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
52
53
54
  // 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.
55
56
  (void)data;

John Koleszar's avatar
John Koleszar committed
57
  if (!ctx->priv) {
58
59
    vpx_codec_alg_priv_t *alg_priv = vpx_memalign(32, sizeof(*alg_priv));
    if (alg_priv == NULL)
60
61
      return VPX_CODEC_MEM_ERROR;

62
63
64
    vp9_zero(*alg_priv);

    ctx->priv = (vpx_codec_priv_t *)alg_priv;
65
66
    ctx->priv->sz = sizeof(*ctx->priv);
    ctx->priv->iface = ctx->iface;
67
    ctx->priv->alg_priv = alg_priv;
68
69
    ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
    ctx->priv->init_flags = ctx->init_flags;
70
71
72
73
74
    ctx->priv->alg_priv->frame_parallel_decode =
        (ctx->init_flags & VPX_CODEC_USE_FRAME_THREADING);

    // Disable frame parallel decoding for now.
    ctx->priv->alg_priv->frame_parallel_decode = 0;
75
76
77
78
79

    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
80
    }
John Koleszar's avatar
John Koleszar committed
81
  }
John Koleszar's avatar
John Koleszar committed
82

83
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
84
85
}

86
87
88
89
90
static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
  if (ctx->pbi) {
    vp9_decoder_remove(ctx->pbi);
    ctx->pbi = NULL;
  }
John Koleszar's avatar
John Koleszar committed
91

92
93
  vpx_free(ctx);

John Koleszar's avatar
John Koleszar committed
94
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
95
96
}

97
98
99
100
101
102
103
static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
                                                unsigned int data_sz,
                                                vpx_codec_stream_info_t *si,
                                                vpx_decrypt_cb decrypt_cb,
                                                void *decrypt_state) {
  uint8_t clear_buffer[9];

104
105
106
107
108
  if (data_sz <= 8)
    return VPX_CODEC_UNSUP_BITSTREAM;

  if (data + data_sz <= data)
    return VPX_CODEC_INVALID_PARAM;
109
110
111

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

113
114
115
116
117
118
  if (decrypt_cb) {
    data_sz = MIN(sizeof(clear_buffer), data_sz);
    decrypt_cb(decrypt_state, data, clear_buffer, data_sz);
    data = clear_buffer;
  }

119
120
121
  {
    struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
    const int frame_marker = vp9_rb_read_literal(&rb, 2);
122
123
124
    const int version = vp9_rb_read_bit(&rb);
    (void) vp9_rb_read_bit(&rb);  // unused version bit

125
126
    if (frame_marker != VP9_FRAME_MARKER)
      return VPX_CODEC_UNSUP_BITSTREAM;
127
128
129
130
131
    if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;

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

133
    si->is_kf = !vp9_rb_read_bit(&rb);
James Zern's avatar
James Zern committed
134
    if (si->is_kf) {
135
136
      const int sRGB = 7;
      int colorspace;
John Koleszar's avatar
John Koleszar committed
137

138
139
      rb.bit_offset += 1;  // show frame
      rb.bit_offset += 1;  // error resilient
John Koleszar's avatar
John Koleszar committed
140

141
142
143
      if (vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_0 ||
          vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_1 ||
          vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_2) {
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
        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
166
    }
John Koleszar's avatar
John Koleszar committed
167
168
  }

169
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
170
171
}

172
173
174
175
176
177
static vpx_codec_err_t decoder_peek_si(const uint8_t *data,
                                       unsigned int data_sz,
                                       vpx_codec_stream_info_t *si) {
  return decoder_peek_si_internal(data, data_sz, si, NULL, NULL);
}

178
179
static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx,
                                      vpx_codec_stream_info_t *si) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
180
181
182
  const size_t sz = (si->sz >= sizeof(vp9_stream_info_t))
                       ? sizeof(vp9_stream_info_t)
                       : sizeof(vpx_codec_stream_info_t);
John Koleszar's avatar
John Koleszar committed
183
  memcpy(si, &ctx->si, sz);
184
  si->sz = (unsigned int)sz;
John Koleszar's avatar
John Koleszar committed
185

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

Dmitry Kovalev's avatar
Dmitry Kovalev committed
189
190
191
192
static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
                           const struct vpx_internal_error_info *error) {
  if (error->error_code)
    ctx->base.err_detail = error->has_detail ? error->detail : NULL;
John Koleszar's avatar
John Koleszar committed
193

Dmitry Kovalev's avatar
Dmitry Kovalev committed
194
  return error->error_code;
John Koleszar's avatar
John Koleszar committed
195
196
}

197
198
199
static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
  VP9_COMMON *const cm = &ctx->pbi->common;

200
  cm->new_fb_idx = -1;
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

  if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
    cm->get_fb_cb = ctx->get_ext_fb_cb;
    cm->release_fb_cb = ctx->release_ext_fb_cb;
    cm->cb_priv = ctx->ext_priv;
  } else {
    cm->get_fb_cb = vp9_get_frame_buffer;
    cm->release_fb_cb = vp9_release_frame_buffer;

    if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
      vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                         "Failed to initialize internal frame buffers");

    cm->cb_priv = &cm->int_frame_buffers;
  }
}

static void set_default_ppflags(vp8_postproc_cfg_t *cfg) {
  cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
  cfg->deblocking_level = 4;
  cfg->noise_level = 0;
}

static void set_ppflags(const vpx_codec_alg_priv_t *ctx,
                        vp9_ppflags_t *flags) {
  flags->post_proc_flag =
      ctx->postproc_cfg.post_proc_flag;

  flags->deblocking_level = ctx->postproc_cfg.deblocking_level;
  flags->noise_level = ctx->postproc_cfg.noise_level;
}

static void init_decoder(vpx_codec_alg_priv_t *ctx) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
234
  ctx->pbi = vp9_decoder_create();
235
236
237
  if (ctx->pbi == NULL)
    return;

Dmitry Kovalev's avatar
Dmitry Kovalev committed
238
239
  ctx->pbi->max_threads = ctx->cfg.threads;
  ctx->pbi->inv_tile_order = ctx->invert_tile_order;
240
  ctx->pbi->frame_parallel_decode = ctx->frame_parallel_decode;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
241

242
243
244
245
246
247
248
249
250
  // 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))
    set_default_ppflags(&ctx->postproc_cfg);

  init_buffer_callbacks(ctx);
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
251
252
253
static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
                                  const uint8_t **data, unsigned int data_sz,
                                  void *user_priv, int64_t deadline) {
254
  vp9_ppflags_t flags = {0};
255
  VP9_COMMON *cm = NULL;
John Koleszar's avatar
John Koleszar committed
256

257
258
  (void)deadline;

259
260
261
  // 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.
262
263
  if (!ctx->si.h) {
    const vpx_codec_err_t res =
264
265
        decoder_peek_si_internal(*data, data_sz, &ctx->si, ctx->decrypt_cb,
                                 ctx->decrypt_state);
266
267
    if (res != VPX_CODEC_OK)
      return res;
268
269
270

    if (!ctx->si.is_kf)
      return VPX_CODEC_ERROR;
271
  }
272

273
  // Initialize the decoder instance on the first frame
274
  if (ctx->pbi == NULL) {
275
276
277
    init_decoder(ctx);
    if (ctx->pbi == NULL)
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
278
279
  }

280
281
282
283
284
  // Set these even if already initialized.  The caller may have changed the
  // decrypt config between frames.
  ctx->pbi->decrypt_cb = ctx->decrypt_cb;
  ctx->pbi->decrypt_state = ctx->decrypt_state;

285
  cm = &ctx->pbi->common;
John Koleszar's avatar
John Koleszar committed
286

287
  if (vp9_receive_compressed_data(ctx->pbi, data_sz, data))
288
    return update_error_state(ctx, &cm->error);
John Koleszar's avatar
John Koleszar committed
289

290
291
  if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
    set_ppflags(ctx, &flags);
John Koleszar's avatar
John Koleszar committed
292

293
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
294
295
}

296
297
298
299
300
301
302
303
304
305
306
static INLINE uint8_t read_marker(vpx_decrypt_cb decrypt_cb,
                                  void *decrypt_state,
                                  const uint8_t *data) {
  if (decrypt_cb) {
    uint8_t marker;
    decrypt_cb(decrypt_state, data, &marker, 1);
    return marker;
  }
  return *data;
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
307
static void parse_superframe_index(const uint8_t *data, size_t data_sz,
308
309
310
                                   uint32_t sizes[8], int *count,
                                   vpx_decrypt_cb decrypt_cb,
                                   void *decrypt_state) {
John Koleszar's avatar
John Koleszar committed
311
312
313
  uint8_t marker;

  assert(data_sz);
314
  marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1);
John Koleszar's avatar
John Koleszar committed
315
316
  *count = 0;

317
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
318
319
320
    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
321

322
323
324
325
    uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
                                  data + data_sz - index_sz);

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

330
331
332
333
334
335
336
337
      // frames has a maximum of 8 and mag has a maximum of 4.
      uint8_t clear_buffer[32];
      assert(sizeof(clear_buffer) >= frames * mag);
      if (decrypt_cb) {
        decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
        x = clear_buffer;
      }

John Koleszar's avatar
John Koleszar committed
338
      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
339
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
340
341
342
343
344
345
346
347
348
349
350

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

      *count = frames;
    }
  }
}

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
static vpx_codec_err_t decode_one_iter(vpx_codec_alg_priv_t *ctx,
                                       const uint8_t **data_start_ptr,
                                       const uint8_t *data_end,
                                       uint32_t frame_size, void *user_priv,
                                       long deadline) {
  const vpx_codec_err_t res = decode_one(ctx, data_start_ptr, frame_size,
                                         user_priv, deadline);
  if (res != VPX_CODEC_OK)
    return res;

  // Account for suboptimal termination by the encoder.
  while (*data_start_ptr < data_end) {
    const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state,
                                       *data_start_ptr);
    if (marker)
      break;
    (*data_start_ptr)++;
  }

  return VPX_CODEC_OK;
}

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

382
383
  if (data == NULL || data_sz == 0)
    return VPX_CODEC_INVALID_PARAM;
384

385
  parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
386
                         ctx->decrypt_cb, ctx->decrypt_state);
387

388
389
  if (frame_count > 0) {
    int i;
John Koleszar's avatar
John Koleszar committed
390

391
392
    for (i = 0; i < frame_count; ++i) {
      const uint32_t frame_size = frame_sizes[i];
393
394
      if (data_start < data ||
          frame_size > (uint32_t)(data_end - data_start)) {
John Koleszar's avatar
John Koleszar committed
395
396
397
398
        ctx->base.err_detail = "Invalid frame size in index";
        return VPX_CODEC_CORRUPT_FRAME;
      }

399
400
401
402
      res = decode_one_iter(ctx, &data_start, data_end, frame_size,
                            user_priv, deadline);
      if (res != VPX_CODEC_OK)
        return res;
John Koleszar's avatar
John Koleszar committed
403
    }
404
  } else {
405
    while (data_start < data_end) {
406
407
      res = decode_one_iter(ctx, &data_start, data_end,
                            (uint32_t)(data_end - data_start),
408
409
410
                            user_priv, deadline);
      if (res != VPX_CODEC_OK)
        return res;
411
    }
412
  }
413

414
  return VPX_CODEC_OK;
415
416
}

417
418
static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
                                      vpx_codec_iter_t *iter) {
John Koleszar's avatar
John Koleszar committed
419
420
  vpx_image_t *img = NULL;

421
422
423
424
425
426
427
428
429
430
  // iter acts as a flip flop, so an image is only returned on the first
  // call to get_frame.
  if (*iter == NULL && ctx->pbi != NULL) {
    YV12_BUFFER_CONFIG sd;
    vp9_ppflags_t flags = {0, 0, 0};

    if (vp9_get_raw_frame(ctx->pbi, &sd, &flags) == 0) {
      VP9_COMMON *cm = &ctx->pbi->common;
      yuvconfig2image(&ctx->img, &sd, NULL);
      ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
John Koleszar's avatar
John Koleszar committed
431
432
      img = &ctx->img;
      *iter = img;
John Koleszar's avatar
John Koleszar committed
433
    }
John Koleszar's avatar
John Koleszar committed
434
  }
John Koleszar's avatar
John Koleszar committed
435

John Koleszar's avatar
John Koleszar committed
436
  return img;
John Koleszar's avatar
John Koleszar committed
437
438
}

439
static vpx_codec_err_t decoder_set_fb_fn(
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
    vpx_codec_alg_priv_t *ctx,
    vpx_get_frame_buffer_cb_fn_t cb_get,
    vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
  if (cb_get == NULL || cb_release == NULL) {
    return VPX_CODEC_INVALID_PARAM;
  } else if (ctx->pbi == NULL) {
    // If the decoder has already been initialized, do not accept changes to
    // the frame buffer functions.
    ctx->get_ext_fb_cb = cb_get;
    ctx->release_ext_fb_cb = cb_release;
    ctx->ext_priv = cb_priv;
    return VPX_CODEC_OK;
  }

  return VPX_CODEC_ERROR;
}

457
static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
458
                                          va_list args) {
459
  vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
460

John Koleszar's avatar
John Koleszar committed
461
  if (data) {
462
    vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
John Koleszar's avatar
John Koleszar committed
463
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
464

John Koleszar's avatar
John Koleszar committed
465
    image2yuvconfig(&frame->img, &sd);
466
    return vp9_set_reference_dec(&ctx->pbi->common,
467
                                 (VP9_REFFRAME)frame->frame_type, &sd);
468
  } else {
John Koleszar's avatar
John Koleszar committed
469
    return VPX_CODEC_INVALID_PARAM;
470
  }
John Koleszar's avatar
John Koleszar committed
471
472
}

473
static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
474
                                           va_list args) {
John Koleszar's avatar
John Koleszar committed
475
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
476

John Koleszar's avatar
John Koleszar committed
477
478
479
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
480

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

John Koleszar's avatar
John Koleszar committed
483
484
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
485
  } else {
John Koleszar's avatar
John Koleszar committed
486
    return VPX_CODEC_INVALID_PARAM;
487
  }
John Koleszar's avatar
John Koleszar committed
488
489
}

490
static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
491
                                          va_list args) {
John Koleszar's avatar
John Koleszar committed
492
493
494
495
496
497
498
499
500
501
502
503
504
  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;
  }
}

505
static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx,
506
                                         va_list args) {
507
#if CONFIG_VP9_POSTPROC
John Koleszar's avatar
John Koleszar committed
508
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
509

John Koleszar's avatar
John Koleszar committed
510
511
512
513
  if (data) {
    ctx->postproc_cfg_set = 1;
    ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
    return VPX_CODEC_OK;
514
  } else {
John Koleszar's avatar
John Koleszar committed
515
    return VPX_CODEC_INVALID_PARAM;
516
  }
John Koleszar's avatar
John Koleszar committed
517
#else
518
519
  (void)ctx;
  (void)args;
John Koleszar's avatar
John Koleszar committed
520
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
521
522
523
#endif
}

524
static vpx_codec_err_t ctrl_set_dbg_options(vpx_codec_alg_priv_t *ctx,
525
526
527
                                            va_list args) {
  (void)ctx;
  (void)args;
John Koleszar's avatar
John Koleszar committed
528
  return VPX_CODEC_INCAPABLE;
529
}
John Koleszar's avatar
John Koleszar committed
530

531
static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
532
                                                 va_list args) {
533
  int *const update_info = va_arg(args, int *);
534

John Koleszar's avatar
John Koleszar committed
535
  if (update_info) {
536
537
538
539
    if (ctx->pbi)
      *update_info = ctx->pbi->refresh_frame_flags;
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
540
    return VPX_CODEC_OK;
541
  } else {
John Koleszar's avatar
John Koleszar committed
542
    return VPX_CODEC_INVALID_PARAM;
543
  }
544
545
546
}


547
static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
548
                                                va_list args) {
John Koleszar's avatar
John Koleszar committed
549
  int *corrupted = va_arg(args, int *);
550

John Koleszar's avatar
John Koleszar committed
551
  if (corrupted) {
552
553
    if (ctx->pbi)
      *corrupted = ctx->pbi->common.frame_to_show->corrupted;
Yaowu Xu's avatar
Yaowu Xu committed
554
555
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
556
    return VPX_CODEC_OK;
557
  } else {
John Koleszar's avatar
John Koleszar committed
558
    return VPX_CODEC_INVALID_PARAM;
559
  }
560
561
}

562
static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
563
                                             va_list args) {
564
565
566
  int *const display_size = va_arg(args, int *);

  if (display_size) {
567
568
569
570
    if (ctx->pbi) {
      const VP9_COMMON *const cm = &ctx->pbi->common;
      display_size[0] = cm->display_width;
      display_size[1] = cm->display_height;
571
572
573
574
575
576
577
578
579
    } else {
      return VPX_CODEC_ERROR;
    }
    return VPX_CODEC_OK;
  } else {
    return VPX_CODEC_INVALID_PARAM;
  }
}

580
static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
581
                                                  va_list args) {
582
583
584
585
  ctx->invert_tile_order = va_arg(args, int);
  return VPX_CODEC_OK;
}

586
587
588
589
590
591
592
593
static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx,
                                          va_list args) {
  vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *);
  ctx->decrypt_cb = init ? init->decrypt_cb : NULL;
  ctx->decrypt_state = init ? init->decrypt_state : NULL;
  return VPX_CODEC_OK;
}

594
595
596
597
598
599
600
601
602
603
604
static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
  {VP8_COPY_REFERENCE,            ctrl_copy_reference},

  // Setters
  {VP8_SET_REFERENCE,             ctrl_set_reference},
  {VP8_SET_POSTPROC,              ctrl_set_postproc},
  {VP8_SET_DBG_COLOR_REF_FRAME,   ctrl_set_dbg_options},
  {VP8_SET_DBG_COLOR_MB_MODES,    ctrl_set_dbg_options},
  {VP8_SET_DBG_COLOR_B_MODES,     ctrl_set_dbg_options},
  {VP8_SET_DBG_DISPLAY_MV,        ctrl_set_dbg_options},
  {VP9_INVERT_TILE_DECODE_ORDER,  ctrl_set_invert_tile_order},
605
  {VPXD_SET_DECRYPTOR,            ctrl_set_decryptor},
606
607
608
609
610
611
612

  // Getters
  {VP8D_GET_LAST_REF_UPDATES,     ctrl_get_last_ref_updates},
  {VP8D_GET_FRAME_CORRUPTED,      ctrl_get_frame_corrupted},
  {VP9_GET_REFERENCE,             ctrl_get_reference},
  {VP9D_GET_DISPLAY_SIZE,         ctrl_get_display_size},

John Koleszar's avatar
John Koleszar committed
613
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
614
615
616
617
618
};

#ifndef VERSION_STRING
#define VERSION_STRING
#endif
619
620
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
  "WebM Project VP9 Decoder" VERSION_STRING,
John Koleszar's avatar
John Koleszar committed
621
  VPX_CODEC_INTERNAL_ABI_VERSION,
622
  VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
623
624
625
626
627
628
      VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER,  // vpx_codec_caps_t
  decoder_init,       // vpx_codec_init_fn_t
  decoder_destroy,    // vpx_codec_destroy_fn_t
  decoder_ctrl_maps,  // vpx_codec_ctrl_fn_map_t
  NOT_IMPLEMENTED,    // vpx_codec_get_mmap_fn_t
  NOT_IMPLEMENTED,    // vpx_codec_set_mmap_fn_t
629
  { // NOLINT
630
631
632
633
634
    decoder_peek_si,    // vpx_codec_peek_si_fn_t
    decoder_get_si,     // vpx_codec_get_si_fn_t
    decoder_decode,     // vpx_codec_decode_fn_t
    decoder_get_frame,  // vpx_codec_frame_get_fn_t
    decoder_set_fb_fn,  // vpx_codec_set_fb_fn_t
John Koleszar's avatar
John Koleszar committed
635
  },
636
  { // NOLINT
637
638
639
640
641
642
643
    NOT_IMPLEMENTED,  // vpx_codec_enc_cfg_map_t
    NOT_IMPLEMENTED,  // vpx_codec_encode_fn_t
    NOT_IMPLEMENTED,  // vpx_codec_get_cx_data_fn_t
    NOT_IMPLEMENTED,  // vpx_codec_enc_config_set_fn_t
    NOT_IMPLEMENTED,  // vpx_codec_get_global_headers_fn_t
    NOT_IMPLEMENTED,  // vpx_codec_get_preview_frame_fn_t
    NOT_IMPLEMENTED   // vpx_codec_enc_mr_get_mem_loc_fn_t
John Koleszar's avatar
John Koleszar committed
644
  }
John Koleszar's avatar
John Koleszar committed
645
};