1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * 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.
9 */
10
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "./vpx_config.h"
15 #include "./vpx_version.h"
16
17 #include "vpx/internal/vpx_codec_internal.h"
18 #include "vpx/vp8dx.h"
19 #include "vpx/vpx_decoder.h"
20 #include "vpx_dsp/bitreader_buffer.h"
21 #include "vpx_dsp/vpx_dsp_common.h"
22
23 #include "vp9/common/vp9_alloccommon.h"
24 #include "vp9/common/vp9_frame_buffers.h"
25
26 #include "vp9/decoder/vp9_decodeframe.h"
27
28 #include "vp9/vp9_dx_iface.h"
29 #include "vp9/vp9_iface_common.h"
30
31 #define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
32
decoder_init(vpx_codec_ctx_t * ctx,vpx_codec_priv_enc_mr_cfg_t * data)33 static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
34 vpx_codec_priv_enc_mr_cfg_t *data) {
35 // This function only allocates space for the vpx_codec_alg_priv_t
36 // structure. More memory may be required at the time the stream
37 // information becomes known.
38 (void)data;
39
40 if (!ctx->priv) {
41 vpx_codec_alg_priv_t *const priv =
42 (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv));
43 if (priv == NULL) return VPX_CODEC_MEM_ERROR;
44
45 ctx->priv = (vpx_codec_priv_t *)priv;
46 ctx->priv->init_flags = ctx->init_flags;
47 priv->si.sz = sizeof(priv->si);
48 priv->flushed = 0;
49 if (ctx->config.dec) {
50 priv->cfg = *ctx->config.dec;
51 ctx->config.dec = &priv->cfg;
52 }
53 }
54
55 return VPX_CODEC_OK;
56 }
57
decoder_destroy(vpx_codec_alg_priv_t * ctx)58 static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
59 if (ctx->pbi != NULL) {
60 vp9_decoder_remove(ctx->pbi);
61 }
62
63 if (ctx->buffer_pool) {
64 vp9_free_ref_frame_buffers(ctx->buffer_pool);
65 vp9_free_internal_frame_buffers(&ctx->buffer_pool->int_frame_buffers);
66 }
67
68 vpx_free(ctx->buffer_pool);
69 vpx_free(ctx);
70 return VPX_CODEC_OK;
71 }
72
parse_bitdepth_colorspace_sampling(BITSTREAM_PROFILE profile,struct vpx_read_bit_buffer * rb)73 static int parse_bitdepth_colorspace_sampling(BITSTREAM_PROFILE profile,
74 struct vpx_read_bit_buffer *rb) {
75 vpx_color_space_t color_space;
76 if (profile >= PROFILE_2) rb->bit_offset += 1; // Bit-depth 10 or 12.
77 color_space = (vpx_color_space_t)vpx_rb_read_literal(rb, 3);
78 if (color_space != VPX_CS_SRGB) {
79 rb->bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range.
80 if (profile == PROFILE_1 || profile == PROFILE_3) {
81 rb->bit_offset += 2; // subsampling x/y.
82 rb->bit_offset += 1; // unused.
83 }
84 } else {
85 if (profile == PROFILE_1 || profile == PROFILE_3) {
86 rb->bit_offset += 1; // unused
87 } else {
88 // RGB is only available in version 1.
89 return 0;
90 }
91 }
92 return 1;
93 }
94
decoder_peek_si_internal(const uint8_t * data,unsigned int data_sz,vpx_codec_stream_info_t * si,int * is_intra_only,vpx_decrypt_cb decrypt_cb,void * decrypt_state)95 static vpx_codec_err_t decoder_peek_si_internal(
96 const uint8_t *data, unsigned int data_sz, vpx_codec_stream_info_t *si,
97 int *is_intra_only, vpx_decrypt_cb decrypt_cb, void *decrypt_state) {
98 int intra_only_flag = 0;
99 uint8_t clear_buffer[11];
100
101 if (data + data_sz <= data) return VPX_CODEC_INVALID_PARAM;
102
103 si->is_kf = 0;
104 si->w = si->h = 0;
105
106 if (decrypt_cb) {
107 data_sz = VPXMIN(sizeof(clear_buffer), data_sz);
108 decrypt_cb(decrypt_state, data, clear_buffer, data_sz);
109 data = clear_buffer;
110 }
111
112 // A maximum of 6 bits are needed to read the frame marker, profile and
113 // show_existing_frame.
114 if (data_sz < 1) return VPX_CODEC_UNSUP_BITSTREAM;
115
116 {
117 int show_frame;
118 int error_resilient;
119 struct vpx_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
120 const int frame_marker = vpx_rb_read_literal(&rb, 2);
121 const BITSTREAM_PROFILE profile = vp9_read_profile(&rb);
122
123 if (frame_marker != VP9_FRAME_MARKER) return VPX_CODEC_UNSUP_BITSTREAM;
124
125 if (profile >= MAX_PROFILES) return VPX_CODEC_UNSUP_BITSTREAM;
126
127 if (vpx_rb_read_bit(&rb)) { // show an existing frame
128 // If profile is > 2 and show_existing_frame is true, then at least 1 more
129 // byte (6+3=9 bits) is needed.
130 if (profile > 2 && data_sz < 2) return VPX_CODEC_UNSUP_BITSTREAM;
131 vpx_rb_read_literal(&rb, 3); // Frame buffer to show.
132 return VPX_CODEC_OK;
133 }
134
135 // For the rest of the function, a maximum of 9 more bytes are needed
136 // (computed by taking the maximum possible bits needed in each case). Note
137 // that this has to be updated if we read any more bits in this function.
138 if (data_sz < 10) return VPX_CODEC_UNSUP_BITSTREAM;
139
140 si->is_kf = !vpx_rb_read_bit(&rb);
141 show_frame = vpx_rb_read_bit(&rb);
142 error_resilient = vpx_rb_read_bit(&rb);
143
144 if (si->is_kf) {
145 if (!vp9_read_sync_code(&rb)) return VPX_CODEC_UNSUP_BITSTREAM;
146
147 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
148 return VPX_CODEC_UNSUP_BITSTREAM;
149 vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
150 } else {
151 intra_only_flag = show_frame ? 0 : vpx_rb_read_bit(&rb);
152
153 rb.bit_offset += error_resilient ? 0 : 2; // reset_frame_context
154
155 if (intra_only_flag) {
156 if (!vp9_read_sync_code(&rb)) return VPX_CODEC_UNSUP_BITSTREAM;
157 if (profile > PROFILE_0) {
158 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
159 return VPX_CODEC_UNSUP_BITSTREAM;
160 // The colorspace info may cause vp9_read_frame_size() to need 11
161 // bytes.
162 if (data_sz < 11) return VPX_CODEC_UNSUP_BITSTREAM;
163 }
164 rb.bit_offset += REF_FRAMES; // refresh_frame_flags
165 vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
166 }
167 }
168 }
169 if (is_intra_only != NULL) *is_intra_only = intra_only_flag;
170 return VPX_CODEC_OK;
171 }
172
decoder_peek_si(const uint8_t * data,unsigned int data_sz,vpx_codec_stream_info_t * si)173 static vpx_codec_err_t decoder_peek_si(const uint8_t *data,
174 unsigned int data_sz,
175 vpx_codec_stream_info_t *si) {
176 return decoder_peek_si_internal(data, data_sz, si, NULL, NULL, NULL);
177 }
178
decoder_get_si(vpx_codec_alg_priv_t * ctx,vpx_codec_stream_info_t * si)179 static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx,
180 vpx_codec_stream_info_t *si) {
181 const size_t sz = (si->sz >= sizeof(vp9_stream_info_t))
182 ? sizeof(vp9_stream_info_t)
183 : sizeof(vpx_codec_stream_info_t);
184 memcpy(si, &ctx->si, sz);
185 si->sz = (unsigned int)sz;
186
187 return VPX_CODEC_OK;
188 }
189
set_error_detail(vpx_codec_alg_priv_t * ctx,const char * const error)190 static void set_error_detail(vpx_codec_alg_priv_t *ctx,
191 const char *const error) {
192 ctx->base.err_detail = error;
193 }
194
update_error_state(vpx_codec_alg_priv_t * ctx,const struct vpx_internal_error_info * error)195 static vpx_codec_err_t update_error_state(
196 vpx_codec_alg_priv_t *ctx, const struct vpx_internal_error_info *error) {
197 if (error->error_code)
198 set_error_detail(ctx, error->has_detail ? error->detail : NULL);
199
200 return error->error_code;
201 }
202
init_buffer_callbacks(vpx_codec_alg_priv_t * ctx)203 static vpx_codec_err_t init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
204 VP9_COMMON *const cm = &ctx->pbi->common;
205 BufferPool *const pool = cm->buffer_pool;
206
207 cm->new_fb_idx = INVALID_IDX;
208 cm->byte_alignment = ctx->byte_alignment;
209 cm->skip_loop_filter = ctx->skip_loop_filter;
210
211 if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
212 pool->get_fb_cb = ctx->get_ext_fb_cb;
213 pool->release_fb_cb = ctx->release_ext_fb_cb;
214 pool->cb_priv = ctx->ext_priv;
215 } else {
216 pool->get_fb_cb = vp9_get_frame_buffer;
217 pool->release_fb_cb = vp9_release_frame_buffer;
218
219 if (vp9_alloc_internal_frame_buffers(&pool->int_frame_buffers)) {
220 vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
221 "Failed to initialize internal frame buffers");
222 return VPX_CODEC_MEM_ERROR;
223 }
224
225 pool->cb_priv = &pool->int_frame_buffers;
226 }
227
228 return VPX_CODEC_OK;
229 }
230
set_default_ppflags(vp8_postproc_cfg_t * cfg)231 static void set_default_ppflags(vp8_postproc_cfg_t *cfg) {
232 cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
233 cfg->deblocking_level = 4;
234 cfg->noise_level = 0;
235 }
236
set_ppflags(const vpx_codec_alg_priv_t * ctx,vp9_ppflags_t * flags)237 static void set_ppflags(const vpx_codec_alg_priv_t *ctx, vp9_ppflags_t *flags) {
238 flags->post_proc_flag = ctx->postproc_cfg.post_proc_flag;
239
240 flags->deblocking_level = ctx->postproc_cfg.deblocking_level;
241 flags->noise_level = ctx->postproc_cfg.noise_level;
242 }
243
244 #undef ERROR
245 #define ERROR(str) \
246 do { \
247 ctx->base.err_detail = str; \
248 return VPX_CODEC_INVALID_PARAM; \
249 } while (0)
250
251 #define RANGE_CHECK(p, memb, lo, hi) \
252 do { \
253 if (!(((p)->memb == (lo) || (p)->memb > (lo)) && (p)->memb <= (hi))) \
254 ERROR(#memb " out of range [" #lo ".." #hi "]"); \
255 } while (0)
256
init_decoder(vpx_codec_alg_priv_t * ctx)257 static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) {
258 vpx_codec_err_t res;
259 ctx->last_show_frame = -1;
260 ctx->need_resync = 1;
261 ctx->flushed = 0;
262
263 ctx->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool));
264 if (ctx->buffer_pool == NULL) return VPX_CODEC_MEM_ERROR;
265
266 ctx->pbi = vp9_decoder_create(ctx->buffer_pool);
267 if (ctx->pbi == NULL) {
268 vpx_free(ctx->buffer_pool);
269 ctx->buffer_pool = NULL;
270 set_error_detail(ctx, "Failed to allocate decoder");
271 return VPX_CODEC_MEM_ERROR;
272 }
273 ctx->pbi->max_threads = ctx->cfg.threads;
274 ctx->pbi->inv_tile_order = ctx->invert_tile_order;
275
276 RANGE_CHECK(ctx, row_mt, 0, 1);
277 ctx->pbi->row_mt = ctx->row_mt;
278
279 RANGE_CHECK(ctx, lpf_opt, 0, 1);
280 ctx->pbi->lpf_mt_opt = ctx->lpf_opt;
281
282 // If postprocessing was enabled by the application and a
283 // configuration has not been provided, default it.
284 if (!ctx->postproc_cfg_set && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC))
285 set_default_ppflags(&ctx->postproc_cfg);
286
287 res = init_buffer_callbacks(ctx);
288 if (res != VPX_CODEC_OK) {
289 vpx_free(ctx->buffer_pool);
290 ctx->buffer_pool = NULL;
291 vp9_decoder_remove(ctx->pbi);
292 ctx->pbi = NULL;
293 }
294 return res;
295 }
296
check_resync(vpx_codec_alg_priv_t * const ctx,const VP9Decoder * const pbi)297 static INLINE void check_resync(vpx_codec_alg_priv_t *const ctx,
298 const VP9Decoder *const pbi) {
299 // Clear resync flag if the decoder got a key frame or intra only frame.
300 if (ctx->need_resync == 1 && pbi->need_resync == 0 &&
301 (pbi->common.intra_only || pbi->common.frame_type == KEY_FRAME))
302 ctx->need_resync = 0;
303 }
304
decode_one(vpx_codec_alg_priv_t * ctx,const uint8_t ** data,unsigned int data_sz,void * user_priv)305 static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
306 const uint8_t **data, unsigned int data_sz,
307 void *user_priv) {
308 // Determine the stream parameters. Note that we rely on peek_si to
309 // validate that we have a buffer that does not wrap around the top
310 // of the heap.
311 if (!ctx->si.h) {
312 int is_intra_only = 0;
313 const vpx_codec_err_t res =
314 decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only,
315 ctx->decrypt_cb, ctx->decrypt_state);
316 if (res != VPX_CODEC_OK) return res;
317
318 if (!ctx->si.is_kf && !is_intra_only) return VPX_CODEC_ERROR;
319 }
320
321 ctx->user_priv = user_priv;
322
323 // Set these even if already initialized. The caller may have changed the
324 // decrypt config between frames.
325 ctx->pbi->decrypt_cb = ctx->decrypt_cb;
326 ctx->pbi->decrypt_state = ctx->decrypt_state;
327
328 if (vp9_receive_compressed_data(ctx->pbi, data_sz, data)) {
329 ctx->pbi->cur_buf->buf.corrupted = 1;
330 ctx->pbi->need_resync = 1;
331 ctx->need_resync = 1;
332 return update_error_state(ctx, &ctx->pbi->common.error);
333 }
334
335 check_resync(ctx, ctx->pbi);
336
337 return VPX_CODEC_OK;
338 }
339
decoder_decode(vpx_codec_alg_priv_t * ctx,const uint8_t * data,unsigned int data_sz,void * user_priv)340 static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
341 const uint8_t *data, unsigned int data_sz,
342 void *user_priv) {
343 const uint8_t *data_start = data;
344 vpx_codec_err_t res;
345 uint32_t frame_sizes[8];
346 int frame_count;
347
348 if (data == NULL && data_sz == 0) {
349 ctx->flushed = 1;
350 return VPX_CODEC_OK;
351 }
352
353 // Reset flushed when receiving a valid frame.
354 ctx->flushed = 0;
355
356 // Initialize the decoder on the first frame.
357 if (ctx->pbi == NULL) {
358 res = init_decoder(ctx);
359 if (res != VPX_CODEC_OK) return res;
360 }
361
362 res = vp9_parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
363 ctx->decrypt_cb, ctx->decrypt_state);
364 if (res != VPX_CODEC_OK) return res;
365
366 if (ctx->svc_decoding && ctx->svc_spatial_layer < frame_count - 1)
367 frame_count = ctx->svc_spatial_layer + 1;
368
369 // Decode in serial mode.
370 if (frame_count > 0) {
371 const uint8_t *const data_end = data + data_sz;
372 int i;
373
374 for (i = 0; i < frame_count; ++i) {
375 const uint8_t *data_start_copy = data_start;
376 const uint32_t frame_size = frame_sizes[i];
377 if (data_start < data || frame_size > (uint32_t)(data_end - data_start)) {
378 set_error_detail(ctx, "Invalid frame size in index");
379 return VPX_CODEC_CORRUPT_FRAME;
380 }
381
382 res = decode_one(ctx, &data_start_copy, frame_size, user_priv);
383 if (res != VPX_CODEC_OK) return res;
384
385 data_start += frame_size;
386 }
387 } else {
388 const uint8_t *const data_end = data + data_sz;
389 while (data_start < data_end) {
390 const uint32_t frame_size = (uint32_t)(data_end - data_start);
391 res = decode_one(ctx, &data_start, frame_size, user_priv);
392 if (res != VPX_CODEC_OK) return res;
393
394 // Account for suboptimal termination by the encoder.
395 while (data_start < data_end) {
396 const uint8_t marker =
397 read_marker(ctx->decrypt_cb, ctx->decrypt_state, data_start);
398 if (marker) break;
399 ++data_start;
400 }
401 }
402 }
403
404 return res;
405 }
406
decoder_get_frame(vpx_codec_alg_priv_t * ctx,vpx_codec_iter_t * iter)407 static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
408 vpx_codec_iter_t *iter) {
409 vpx_image_t *img = NULL;
410
411 // Legacy parameter carried over from VP8. Has no effect for VP9 since we
412 // always return only 1 frame per decode call.
413 (void)iter;
414
415 if (ctx->pbi != NULL) {
416 YV12_BUFFER_CONFIG sd;
417 vp9_ppflags_t flags = { 0, 0, 0 };
418 if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) set_ppflags(ctx, &flags);
419 if (vp9_get_raw_frame(ctx->pbi, &sd, &flags) == 0) {
420 VP9_COMMON *const cm = &ctx->pbi->common;
421 RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
422 ctx->last_show_frame = ctx->pbi->common.new_fb_idx;
423 if (ctx->need_resync) return NULL;
424 yuvconfig2image(&ctx->img, &sd, ctx->user_priv);
425 ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
426 img = &ctx->img;
427 return img;
428 }
429 }
430 return NULL;
431 }
432
decoder_set_fb_fn(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)433 static vpx_codec_err_t decoder_set_fb_fn(
434 vpx_codec_alg_priv_t *ctx, vpx_get_frame_buffer_cb_fn_t cb_get,
435 vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
436 if (cb_get == NULL || cb_release == NULL) {
437 return VPX_CODEC_INVALID_PARAM;
438 } else if (ctx->pbi == NULL) {
439 // If the decoder has already been initialized, do not accept changes to
440 // the frame buffer functions.
441 ctx->get_ext_fb_cb = cb_get;
442 ctx->release_ext_fb_cb = cb_release;
443 ctx->ext_priv = cb_priv;
444 return VPX_CODEC_OK;
445 }
446
447 return VPX_CODEC_ERROR;
448 }
449
ctrl_set_reference(vpx_codec_alg_priv_t * ctx,va_list args)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 *);
453
454 if (data) {
455 vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
456 YV12_BUFFER_CONFIG sd;
457 image2yuvconfig(&frame->img, &sd);
458 return vp9_set_reference_dec(
459 &ctx->pbi->common, ref_frame_to_vp9_reframe(frame->frame_type), &sd);
460 } else {
461 return VPX_CODEC_INVALID_PARAM;
462 }
463 }
464
ctrl_copy_reference(vpx_codec_alg_priv_t * ctx,va_list args)465 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
466 va_list args) {
467 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
468
469 if (data) {
470 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
471 YV12_BUFFER_CONFIG sd;
472 image2yuvconfig(&frame->img, &sd);
473 return vp9_copy_reference_dec(ctx->pbi, (VP9_REFFRAME)frame->frame_type,
474 &sd);
475 } else {
476 return VPX_CODEC_INVALID_PARAM;
477 }
478 }
479
ctrl_get_reference(vpx_codec_alg_priv_t * ctx,va_list args)480 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
481 va_list args) {
482 vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
483
484 if (data) {
485 if (ctx->pbi) {
486 const int fb_idx = ctx->pbi->common.cur_show_frame_fb_idx;
487 YV12_BUFFER_CONFIG *fb = get_buf_frame(&ctx->pbi->common, fb_idx);
488 if (fb == NULL) return VPX_CODEC_ERROR;
489 yuvconfig2image(&data->img, fb, NULL);
490 return VPX_CODEC_OK;
491 } else {
492 return VPX_CODEC_ERROR;
493 }
494 } else {
495 return VPX_CODEC_INVALID_PARAM;
496 }
497 }
498
ctrl_set_postproc(vpx_codec_alg_priv_t * ctx,va_list args)499 static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx,
500 va_list args) {
501 #if CONFIG_VP9_POSTPROC
502 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
503
504 if (data) {
505 ctx->postproc_cfg_set = 1;
506 ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
507 return VPX_CODEC_OK;
508 } else {
509 return VPX_CODEC_INVALID_PARAM;
510 }
511 #else
512 (void)ctx;
513 (void)args;
514 return VPX_CODEC_INCAPABLE;
515 #endif
516 }
517
ctrl_get_quantizer(vpx_codec_alg_priv_t * ctx,va_list args)518 static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx,
519 va_list args) {
520 int *const arg = va_arg(args, int *);
521 if (arg == NULL || ctx->pbi == NULL) return VPX_CODEC_INVALID_PARAM;
522 *arg = ctx->pbi->common.base_qindex;
523 return VPX_CODEC_OK;
524 }
525
ctrl_get_last_ref_updates(vpx_codec_alg_priv_t * ctx,va_list args)526 static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
527 va_list args) {
528 int *const update_info = va_arg(args, int *);
529
530 if (update_info) {
531 if (ctx->pbi != NULL) {
532 *update_info = ctx->pbi->refresh_frame_flags;
533 return VPX_CODEC_OK;
534 } else {
535 return VPX_CODEC_ERROR;
536 }
537 }
538
539 return VPX_CODEC_INVALID_PARAM;
540 }
541
ctrl_get_frame_corrupted(vpx_codec_alg_priv_t * ctx,va_list args)542 static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
543 va_list args) {
544 int *corrupted = va_arg(args, int *);
545
546 if (corrupted) {
547 if (ctx->pbi != NULL) {
548 RefCntBuffer *const frame_bufs = ctx->pbi->common.buffer_pool->frame_bufs;
549 if (ctx->pbi->common.frame_to_show == NULL) return VPX_CODEC_ERROR;
550 if (ctx->last_show_frame >= 0)
551 *corrupted = frame_bufs[ctx->last_show_frame].buf.corrupted;
552 return VPX_CODEC_OK;
553 } else {
554 return VPX_CODEC_ERROR;
555 }
556 }
557
558 return VPX_CODEC_INVALID_PARAM;
559 }
560
ctrl_get_frame_size(vpx_codec_alg_priv_t * ctx,va_list args)561 static vpx_codec_err_t ctrl_get_frame_size(vpx_codec_alg_priv_t *ctx,
562 va_list args) {
563 int *const frame_size = va_arg(args, int *);
564
565 if (frame_size) {
566 if (ctx->pbi != NULL) {
567 const VP9_COMMON *const cm = &ctx->pbi->common;
568 frame_size[0] = cm->width;
569 frame_size[1] = cm->height;
570 return VPX_CODEC_OK;
571 } else {
572 return VPX_CODEC_ERROR;
573 }
574 }
575
576 return VPX_CODEC_INVALID_PARAM;
577 }
578
ctrl_get_render_size(vpx_codec_alg_priv_t * ctx,va_list args)579 static vpx_codec_err_t ctrl_get_render_size(vpx_codec_alg_priv_t *ctx,
580 va_list args) {
581 int *const render_size = va_arg(args, int *);
582
583 if (render_size) {
584 if (ctx->pbi != NULL) {
585 const VP9_COMMON *const cm = &ctx->pbi->common;
586 render_size[0] = cm->render_width;
587 render_size[1] = cm->render_height;
588 return VPX_CODEC_OK;
589 } else {
590 return VPX_CODEC_ERROR;
591 }
592 }
593
594 return VPX_CODEC_INVALID_PARAM;
595 }
596
ctrl_get_bit_depth(vpx_codec_alg_priv_t * ctx,va_list args)597 static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx,
598 va_list args) {
599 unsigned int *const bit_depth = va_arg(args, unsigned int *);
600
601 if (bit_depth) {
602 if (ctx->pbi != NULL) {
603 const VP9_COMMON *const cm = &ctx->pbi->common;
604 *bit_depth = cm->bit_depth;
605 return VPX_CODEC_OK;
606 } else {
607 return VPX_CODEC_ERROR;
608 }
609 }
610
611 return VPX_CODEC_INVALID_PARAM;
612 }
613
ctrl_set_invert_tile_order(vpx_codec_alg_priv_t * ctx,va_list args)614 static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
615 va_list args) {
616 ctx->invert_tile_order = va_arg(args, int);
617 return VPX_CODEC_OK;
618 }
619
ctrl_set_decryptor(vpx_codec_alg_priv_t * ctx,va_list args)620 static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx,
621 va_list args) {
622 vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *);
623 ctx->decrypt_cb = init ? init->decrypt_cb : NULL;
624 ctx->decrypt_state = init ? init->decrypt_state : NULL;
625 return VPX_CODEC_OK;
626 }
627
ctrl_set_byte_alignment(vpx_codec_alg_priv_t * ctx,va_list args)628 static vpx_codec_err_t ctrl_set_byte_alignment(vpx_codec_alg_priv_t *ctx,
629 va_list args) {
630 const int legacy_byte_alignment = 0;
631 const int min_byte_alignment = 32;
632 const int max_byte_alignment = 1024;
633 const int byte_alignment = va_arg(args, int);
634
635 if (byte_alignment != legacy_byte_alignment &&
636 (byte_alignment < min_byte_alignment ||
637 byte_alignment > max_byte_alignment ||
638 (byte_alignment & (byte_alignment - 1)) != 0))
639 return VPX_CODEC_INVALID_PARAM;
640
641 ctx->byte_alignment = byte_alignment;
642 if (ctx->pbi != NULL) {
643 ctx->pbi->common.byte_alignment = byte_alignment;
644 }
645 return VPX_CODEC_OK;
646 }
647
ctrl_set_skip_loop_filter(vpx_codec_alg_priv_t * ctx,va_list args)648 static vpx_codec_err_t ctrl_set_skip_loop_filter(vpx_codec_alg_priv_t *ctx,
649 va_list args) {
650 ctx->skip_loop_filter = va_arg(args, int);
651
652 if (ctx->pbi != NULL) {
653 ctx->pbi->common.skip_loop_filter = ctx->skip_loop_filter;
654 }
655
656 return VPX_CODEC_OK;
657 }
658
ctrl_set_spatial_layer_svc(vpx_codec_alg_priv_t * ctx,va_list args)659 static vpx_codec_err_t ctrl_set_spatial_layer_svc(vpx_codec_alg_priv_t *ctx,
660 va_list args) {
661 ctx->svc_decoding = 1;
662 ctx->svc_spatial_layer = va_arg(args, int);
663 if (ctx->svc_spatial_layer < 0)
664 return VPX_CODEC_INVALID_PARAM;
665 else
666 return VPX_CODEC_OK;
667 }
668
ctrl_set_row_mt(vpx_codec_alg_priv_t * ctx,va_list args)669 static vpx_codec_err_t ctrl_set_row_mt(vpx_codec_alg_priv_t *ctx,
670 va_list args) {
671 ctx->row_mt = va_arg(args, int);
672
673 return VPX_CODEC_OK;
674 }
675
ctrl_enable_lpf_opt(vpx_codec_alg_priv_t * ctx,va_list args)676 static vpx_codec_err_t ctrl_enable_lpf_opt(vpx_codec_alg_priv_t *ctx,
677 va_list args) {
678 ctx->lpf_opt = va_arg(args, int);
679
680 return VPX_CODEC_OK;
681 }
682
683 static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
684 { VP8_COPY_REFERENCE, ctrl_copy_reference },
685
686 // Setters
687 { VP8_SET_REFERENCE, ctrl_set_reference },
688 { VP8_SET_POSTPROC, ctrl_set_postproc },
689 { VP9_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order },
690 { VPXD_SET_DECRYPTOR, ctrl_set_decryptor },
691 { VP9_SET_BYTE_ALIGNMENT, ctrl_set_byte_alignment },
692 { VP9_SET_SKIP_LOOP_FILTER, ctrl_set_skip_loop_filter },
693 { VP9_DECODE_SVC_SPATIAL_LAYER, ctrl_set_spatial_layer_svc },
694 { VP9D_SET_ROW_MT, ctrl_set_row_mt },
695 { VP9D_SET_LOOP_FILTER_OPT, ctrl_enable_lpf_opt },
696
697 // Getters
698 { VPXD_GET_LAST_QUANTIZER, ctrl_get_quantizer },
699 { VP8D_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates },
700 { VP8D_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted },
701 { VP9_GET_REFERENCE, ctrl_get_reference },
702 { VP9D_GET_DISPLAY_SIZE, ctrl_get_render_size },
703 { VP9D_GET_BIT_DEPTH, ctrl_get_bit_depth },
704 { VP9D_GET_FRAME_SIZE, ctrl_get_frame_size },
705
706 { -1, NULL },
707 };
708
709 #ifndef VERSION_STRING
710 #define VERSION_STRING
711 #endif
712 CODEC_INTERFACE(vpx_codec_vp9_dx) = {
713 "WebM Project VP9 Decoder" VERSION_STRING,
714 VPX_CODEC_INTERNAL_ABI_VERSION,
715 #if CONFIG_VP9_HIGHBITDEPTH
716 VPX_CODEC_CAP_HIGHBITDEPTH |
717 #endif
718 VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
719 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER, // vpx_codec_caps_t
720 decoder_init, // vpx_codec_init_fn_t
721 decoder_destroy, // vpx_codec_destroy_fn_t
722 decoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t
723 {
724 // NOLINT
725 decoder_peek_si, // vpx_codec_peek_si_fn_t
726 decoder_get_si, // vpx_codec_get_si_fn_t
727 decoder_decode, // vpx_codec_decode_fn_t
728 decoder_get_frame, // vpx_codec_frame_get_fn_t
729 decoder_set_fb_fn, // vpx_codec_set_fb_fn_t
730 },
731 {
732 // NOLINT
733 0,
734 NULL, // vpx_codec_enc_cfg_map_t
735 NULL, // vpx_codec_encode_fn_t
736 NULL, // vpx_codec_get_cx_data_fn_t
737 NULL, // vpx_codec_enc_config_set_fn_t
738 NULL, // vpx_codec_get_global_headers_fn_t
739 NULL, // vpx_codec_get_preview_frame_fn_t
740 NULL // vpx_codec_enc_mr_get_mem_loc_fn_t
741 }
742 };
743