vp9_dx_iface.c 19.3 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
41
  vpx_image_t             img;
  int                     img_avail;
42
  int                     invert_tile_order;
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
51
static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
                            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.
John Koleszar's avatar
John Koleszar committed
55
  if (!ctx->priv) {
56
57
    vpx_codec_alg_priv_t *alg_priv = vpx_memalign(32, sizeof(*alg_priv));
    if (alg_priv == NULL)
58
59
      return VPX_CODEC_MEM_ERROR;

60
61
62
    vp9_zero(*alg_priv);

    ctx->priv = (vpx_codec_priv_t *)alg_priv;
63
64
    ctx->priv->sz = sizeof(*ctx->priv);
    ctx->priv->iface = ctx->iface;
65
    ctx->priv->alg_priv = alg_priv;
66
67
68
69
70
71
72
    ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
    ctx->priv->init_flags = ctx->init_flags;

    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
73
    }
John Koleszar's avatar
John Koleszar committed
74
  }
John Koleszar's avatar
John Koleszar committed
75

76
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
77
78
}

79
80
81
82
83
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
84

85
86
  vpx_free(ctx);

John Koleszar's avatar
John Koleszar committed
87
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
88
89
}

90
91
92
93
94
95
96
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];

97
98
99
100
101
  if (data_sz <= 8)
    return VPX_CODEC_UNSUP_BITSTREAM;

  if (data + data_sz <= data)
    return VPX_CODEC_INVALID_PARAM;
102
103
104

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

106
107
108
109
110
111
  if (decrypt_cb) {
    data_sz = MIN(sizeof(clear_buffer), data_sz);
    decrypt_cb(decrypt_state, data, clear_buffer, data_sz);
    data = clear_buffer;
  }

112
113
114
  {
    struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
    const int frame_marker = vp9_rb_read_literal(&rb, 2);
115
116
117
    const int version = vp9_rb_read_bit(&rb);
    (void) vp9_rb_read_bit(&rb);  // unused version bit

118
119
    if (frame_marker != VP9_FRAME_MARKER)
      return VPX_CODEC_UNSUP_BITSTREAM;
120
121
122
123
124
    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
125

126
    si->is_kf = !vp9_rb_read_bit(&rb);
James Zern's avatar
James Zern committed
127
    if (si->is_kf) {
128
129
      const int sRGB = 7;
      int colorspace;
John Koleszar's avatar
John Koleszar committed
130

131
132
      rb.bit_offset += 1;  // show frame
      rb.bit_offset += 1;  // error resilient
John Koleszar's avatar
John Koleszar committed
133

134
135
136
      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) {
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
        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
159
    }
John Koleszar's avatar
John Koleszar committed
160
161
  }

162
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
163
164
}

165
166
167
168
169
170
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);
}

171
172
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
173
174
175
  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
176
  memcpy(si, &ctx->si, sz);
177
  si->sz = (unsigned int)sz;
John Koleszar's avatar
John Koleszar committed
178

John Koleszar's avatar
John Koleszar committed
179
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
180
181
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
182
183
184
185
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
186

Dmitry Kovalev's avatar
Dmitry Kovalev committed
187
  return error->error_code;
John Koleszar's avatar
John Koleszar committed
188
189
}

190
191
192
static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
  VP9_COMMON *const cm = &ctx->pbi->common;

193
  cm->new_fb_idx = -1;
194
195
196
197
198
199
200
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

  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
227
  ctx->pbi = vp9_decoder_create();
228
229
230
  if (ctx->pbi == NULL)
    return;

Dmitry Kovalev's avatar
Dmitry Kovalev committed
231
232
233
  ctx->pbi->max_threads = ctx->cfg.threads;
  ctx->pbi->inv_tile_order = ctx->invert_tile_order;

234
235
236
237
238
239
240
241
242
  // 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
243
244
245
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) {
246
247
248
  YV12_BUFFER_CONFIG sd = { 0 };
  vp9_ppflags_t flags = {0};
  VP9_COMMON *cm = NULL;
John Koleszar's avatar
John Koleszar committed
249

250
251
  (void)deadline;

John Koleszar's avatar
John Koleszar committed
252
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
253

254
255
256
  // 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.
257
258
  if (!ctx->si.h) {
    const vpx_codec_err_t res =
259
260
        decoder_peek_si_internal(*data, data_sz, &ctx->si, ctx->decrypt_cb,
                                 ctx->decrypt_state);
261
262
263
    if (res != VPX_CODEC_OK)
      return res;
  }
264

265
  // Initialize the decoder instance on the first frame
266
  if (ctx->pbi == NULL) {
267
268
269
    init_decoder(ctx);
    if (ctx->pbi == NULL)
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
270
271
  }

272
273
274
275
276
  // 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;

277
  cm = &ctx->pbi->common;
John Koleszar's avatar
John Koleszar committed
278

279
  if (vp9_receive_compressed_data(ctx->pbi, data_sz, data))
280
    return update_error_state(ctx, &cm->error);
John Koleszar's avatar
John Koleszar committed
281

282
283
  if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
    set_ppflags(ctx, &flags);
John Koleszar's avatar
John Koleszar committed
284

285
  if (vp9_get_raw_frame(ctx->pbi, &sd, &flags))
286
    return update_error_state(ctx, &cm->error);
287

288
289
290
  yuvconfig2image(&ctx->img, &sd, user_priv);
  ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
  ctx->img_avail = 1;
John Koleszar's avatar
John Koleszar committed
291

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

295
296
297
298
299
300
301
302
303
304
305
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
306
static void parse_superframe_index(const uint8_t *data, size_t data_sz,
307
308
309
                                   uint32_t sizes[8], int *count,
                                   vpx_decrypt_cb decrypt_cb,
                                   void *decrypt_state) {
John Koleszar's avatar
John Koleszar committed
310
311
312
  uint8_t marker;

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

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

321
322
323
324
    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
325
      // found a valid superframe index
Johann's avatar
Johann committed
326
      uint32_t i, j;
327
      const uint8_t *x = &data[data_sz - index_sz + 1];
John Koleszar's avatar
John Koleszar committed
328

329
330
331
332
333
334
335
336
      // 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
337
      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
338
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
339
340
341
342
343
344
345
346
347
348
349

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

      *count = frames;
    }
  }
}

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
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;
}

372
373
374
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) {
375
  const uint8_t *data_start = data;
376
377
378
379
  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
380

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

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

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

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

398
399
400
401
      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
402
    }
403
  } else {
404
    while (data_start < data_end) {
405
406
      res = decode_one_iter(ctx, &data_start, data_end,
                            (uint32_t)(data_end - data_start),
407
408
409
                            user_priv, deadline);
      if (res != VPX_CODEC_OK)
        return res;
410
    }
411
  }
412

413
  return VPX_CODEC_OK;
414
415
}

416
417
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
418
419
420
  vpx_image_t *img = NULL;

  if (ctx->img_avail) {
421
422
    // iter acts as a flip flop, so an image is only returned on the first
    // call to get_frame.
John Koleszar's avatar
John Koleszar committed
423
424
425
    if (!(*iter)) {
      img = &ctx->img;
      *iter = img;
John Koleszar's avatar
John Koleszar committed
426
    }
John Koleszar's avatar
John Koleszar committed
427
  }
428
  ctx->img_avail = 0;
John Koleszar's avatar
John Koleszar committed
429

John Koleszar's avatar
John Koleszar committed
430
  return img;
John Koleszar's avatar
John Koleszar committed
431
432
}

433
static vpx_codec_err_t decoder_set_fb_fn(
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
    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;
}

451
452
static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
                                          int ctr_id, va_list args) {
453
  vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
454

John Koleszar's avatar
John Koleszar committed
455
  if (data) {
456
    vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
John Koleszar's avatar
John Koleszar committed
457
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
458

John Koleszar's avatar
John Koleszar committed
459
    image2yuvconfig(&frame->img, &sd);
460
    return vp9_set_reference_dec(&ctx->pbi->common,
461
                                 (VP9_REFFRAME)frame->frame_type, &sd);
462
  } else {
John Koleszar's avatar
John Koleszar committed
463
    return VPX_CODEC_INVALID_PARAM;
464
  }
John Koleszar's avatar
John Koleszar committed
465
466
}

467
468
static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
469
  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
John Koleszar's avatar
John Koleszar committed
470

John Koleszar's avatar
John Koleszar committed
471
472
473
  if (data) {
    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
    YV12_BUFFER_CONFIG sd;
John Koleszar's avatar
John Koleszar committed
474

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

John Koleszar's avatar
John Koleszar committed
477
478
    return vp9_copy_reference_dec(ctx->pbi,
                                  (VP9_REFFRAME)frame->frame_type, &sd);
479
  } else {
John Koleszar's avatar
John Koleszar committed
480
    return VPX_CODEC_INVALID_PARAM;
481
  }
John Koleszar's avatar
John Koleszar committed
482
483
}

484
485
static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
                                          int ctr_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
486
487
488
489
490
491
492
493
494
495
496
497
498
  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;
  }
}

499
500
static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx,
                                         int ctr_id, va_list args) {
501
#if CONFIG_VP9_POSTPROC
John Koleszar's avatar
John Koleszar committed
502
  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
John Koleszar's avatar
John Koleszar committed
503

John Koleszar's avatar
John Koleszar committed
504
505
506
507
  if (data) {
    ctx->postproc_cfg_set = 1;
    ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
    return VPX_CODEC_OK;
508
  } else {
John Koleszar's avatar
John Koleszar committed
509
    return VPX_CODEC_INVALID_PARAM;
510
  }
John Koleszar's avatar
John Koleszar committed
511
#else
John Koleszar's avatar
John Koleszar committed
512
  return VPX_CODEC_INCAPABLE;
John Koleszar's avatar
John Koleszar committed
513
514
515
#endif
}

516
517
static vpx_codec_err_t ctrl_set_dbg_options(vpx_codec_alg_priv_t *ctx,
                                            int ctrl_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
518
  return VPX_CODEC_INCAPABLE;
519
}
John Koleszar's avatar
John Koleszar committed
520

521
522
static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
                                                 int ctrl_id, va_list args) {
523
  int *const update_info = va_arg(args, int *);
524

John Koleszar's avatar
John Koleszar committed
525
  if (update_info) {
526
527
528
529
    if (ctx->pbi)
      *update_info = ctx->pbi->refresh_frame_flags;
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
530
    return VPX_CODEC_OK;
531
  } else {
John Koleszar's avatar
John Koleszar committed
532
    return VPX_CODEC_INVALID_PARAM;
533
  }
534
535
536
}


537
538
static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
                                                int ctrl_id, va_list args) {
John Koleszar's avatar
John Koleszar committed
539
  int *corrupted = va_arg(args, int *);
540

John Koleszar's avatar
John Koleszar committed
541
  if (corrupted) {
542
543
    if (ctx->pbi)
      *corrupted = ctx->pbi->common.frame_to_show->corrupted;
Yaowu Xu's avatar
Yaowu Xu committed
544
545
    else
      return VPX_CODEC_ERROR;
John Koleszar's avatar
John Koleszar committed
546
    return VPX_CODEC_OK;
547
  } else {
John Koleszar's avatar
John Koleszar committed
548
    return VPX_CODEC_INVALID_PARAM;
549
  }
550
551
}

552
553
static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
                                             int ctrl_id, va_list args) {
554
555
556
  int *const display_size = va_arg(args, int *);

  if (display_size) {
557
558
559
560
    if (ctx->pbi) {
      const VP9_COMMON *const cm = &ctx->pbi->common;
      display_size[0] = cm->display_width;
      display_size[1] = cm->display_height;
561
562
563
564
565
566
567
568
569
    } else {
      return VPX_CODEC_ERROR;
    }
    return VPX_CODEC_OK;
  } else {
    return VPX_CODEC_INVALID_PARAM;
  }
}

570
571
static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
                                                  int ctr_id, va_list args) {
572
573
574
575
  ctx->invert_tile_order = va_arg(args, int);
  return VPX_CODEC_OK;
}

576
577
578
579
580
581
582
583
584
static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx,
                                          int ctrl_id,
                                          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;
}

585
586
587
588
589
590
591
592
593
594
595
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},
596
  {VPXD_SET_DECRYPTOR,            ctrl_set_decryptor},
597
598
599
600
601
602
603

  // 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
604
  { -1, NULL},
John Koleszar's avatar
John Koleszar committed
605
606
607
608
609
};

#ifndef VERSION_STRING
#define VERSION_STRING
#endif
610
611
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
  "WebM Project VP9 Decoder" VERSION_STRING,
John Koleszar's avatar
John Koleszar committed
612
  VPX_CODEC_INTERNAL_ABI_VERSION,
613
  VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
614
615
616
617
618
619
      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
620
  { // NOLINT
621
622
623
624
625
    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
626
  },
627
  { // NOLINT
John Koleszar's avatar
John Koleszar committed
628
629
630
631
632
633
634
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED,
    NOT_IMPLEMENTED
  }
John Koleszar's avatar
John Koleszar committed
635
};