vp9_dx_iface.c 19.5 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9
10
11
12
 */

#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
43
44
45
46

  // 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
47
48
};

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

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

61
62
63
    vp9_zero(*alg_priv);

    ctx->priv = (vpx_codec_priv_t *)alg_priv;
64
65
    ctx->priv->sz = sizeof(*ctx->priv);
    ctx->priv->iface = ctx->iface;
66
    ctx->priv->alg_priv = alg_priv;
67
68
69
70
71
72
73
    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
74
    }
John Koleszar's avatar
John Koleszar committed
75
  }
John Koleszar's avatar
John Koleszar committed
76

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

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

86
87
  vpx_free(ctx);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

194
  cm->new_fb_idx = -1;
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
227

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

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

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

250
251
  (void)deadline;

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

    if (!ctx->si.is_kf)
      return VPX_CODEC_ERROR;
264
  }
265

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

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

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

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

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

286
  return VPX_CODEC_OK;
John Koleszar's avatar
John Koleszar committed
287
288
}

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

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

310
  if ((marker & 0xe0) == 0xc0) {
Johann's avatar
Johann committed
311
312
313
    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
314

315
316
317
318
    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
319
      // found a valid superframe index
Johann's avatar
Johann committed
320
      uint32_t i, j;
321
      const uint8_t *x = &data[data_sz - index_sz + 1];
John Koleszar's avatar
John Koleszar committed
322

323
324
325
326
327
328
329
330
      // 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
331
      for (i = 0; i < frames; i++) {
Johann's avatar
Johann committed
332
        uint32_t this_sz = 0;
John Koleszar's avatar
John Koleszar committed
333
334
335
336
337
338
339
340
341
342
343

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

      *count = frames;
    }
  }
}

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
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;
}

366
367
368
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) {
369
  const uint8_t *data_start = data;
370
371
372
373
  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
374

375
376
  if (data == NULL || data_sz == 0)
    return VPX_CODEC_INVALID_PARAM;
377

378
  parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
379
                         ctx->decrypt_cb, ctx->decrypt_state);
380

381
382
  if (frame_count > 0) {
    int i;
John Koleszar's avatar
John Koleszar committed
383

384
385
    for (i = 0; i < frame_count; ++i) {
      const uint32_t frame_size = frame_sizes[i];
386
387
      if (data_start < data ||
          frame_size > (uint32_t)(data_end - data_start)) {
John Koleszar's avatar
John Koleszar committed
388
389
390
391
        ctx->base.err_detail = "Invalid frame size in index";
        return VPX_CODEC_CORRUPT_FRAME;
      }

392
393
394
395
      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
396
    }
397
  } else {
398
    while (data_start < data_end) {
399
400
      res = decode_one_iter(ctx, &data_start, data_end,
                            (uint32_t)(data_end - data_start),
401
402
403
                            user_priv, deadline);
      if (res != VPX_CODEC_OK)
        return res;
404
    }
405
  }
406

407
  return VPX_CODEC_OK;
408
409
}

410
411
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
412
413
  vpx_image_t *img = NULL;

414
415
416
417
418
419
420
421
422
423
  // 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
424
425
      img = &ctx->img;
      *iter = img;
John Koleszar's avatar
John Koleszar committed
426
    }
John Koleszar's avatar
John Koleszar committed
427
  }
John Koleszar's avatar
John Koleszar committed
428

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

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

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

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

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

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

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

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

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

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

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

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

517
static vpx_codec_err_t ctrl_set_dbg_options(vpx_codec_alg_priv_t *ctx,
518
519
520
                                            va_list args) {
  (void)ctx;
  (void)args;
John Koleszar's avatar
John Koleszar committed
521
  return VPX_CODEC_INCAPABLE;
522
}
John Koleszar's avatar
John Koleszar committed
523

524
static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
525
                                                 va_list args) {
526
  int *const update_info = va_arg(args, int *);
527

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


540
static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
541
                                                va_list args) {
John Koleszar's avatar
John Koleszar committed
542
  int *corrupted = va_arg(args, int *);
543

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

555
static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
556
                                             va_list args) {
557
558
559
  int *const display_size = va_arg(args, int *);

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

573
static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
574
                                                  va_list args) {
575
576
577
578
  ctx->invert_tile_order = va_arg(args, int);
  return VPX_CODEC_OK;
}

579
580
581
582
583
584
585
586
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;
}

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

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

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