hadamard: Add 4x4 test.
[aom.git] / av1 / av1_dx_iface.c
blob45e8cb991a8686a7acefbe53cc4c864eca4bc2e2
1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
12 #include <stdlib.h>
13 #include <string.h>
15 #include "config/aom_config.h"
16 #include "config/aom_version.h"
18 #include "aom/internal/aom_codec_internal.h"
19 #include "aom/internal/aom_image_internal.h"
20 #include "aom/aomdx.h"
21 #include "aom/aom_decoder.h"
22 #include "aom_dsp/bitreader_buffer.h"
23 #include "aom_dsp/aom_dsp_common.h"
24 #include "aom_ports/mem_ops.h"
25 #include "aom_util/aom_thread.h"
27 #include "av1/common/alloccommon.h"
28 #include "av1/common/frame_buffers.h"
29 #include "av1/common/enums.h"
30 #include "av1/common/obu_util.h"
32 #include "av1/decoder/decoder.h"
33 #include "av1/decoder/decodeframe.h"
34 #include "av1/decoder/grain_synthesis.h"
35 #include "av1/decoder/obu.h"
37 #include "av1/av1_iface_common.h"
39 struct aom_codec_alg_priv {
40 aom_codec_priv_t base;
41 aom_codec_dec_cfg_t cfg;
42 aom_codec_stream_info_t si;
43 aom_image_t img;
44 int img_avail;
45 int flushed;
46 int invert_tile_order;
47 RefCntBuffer *last_show_frame; // Last output frame buffer
48 int byte_alignment;
49 int skip_loop_filter;
50 int skip_film_grain;
51 int decode_tile_row;
52 int decode_tile_col;
53 unsigned int tile_mode;
54 unsigned int ext_tile_debug;
55 unsigned int row_mt;
56 EXTERNAL_REFERENCES ext_refs;
57 unsigned int is_annexb;
58 int operating_point;
59 int output_all_layers;
61 AVxWorker *frame_worker;
63 aom_image_t image_with_grain;
64 aom_codec_frame_buffer_t grain_image_frame_buffers[MAX_NUM_SPATIAL_LAYERS];
65 size_t num_grain_image_frame_buffers;
66 int need_resync; // wait for key/intra-only frame
67 // BufferPool that holds all reference frames. Shared by all the FrameWorkers.
68 BufferPool *buffer_pool;
70 // External frame buffer info to save for AV1 common.
71 void *ext_priv; // Private data associated with the external frame buffers.
72 aom_get_frame_buffer_cb_fn_t get_ext_fb_cb;
73 aom_release_frame_buffer_cb_fn_t release_ext_fb_cb;
75 #if CONFIG_INSPECTION
76 aom_inspect_cb inspect_cb;
77 void *inspect_ctx;
78 #endif
81 static aom_codec_err_t decoder_init(aom_codec_ctx_t *ctx) {
82 // This function only allocates space for the aom_codec_alg_priv_t
83 // structure. More memory may be required at the time the stream
84 // information becomes known.
85 if (!ctx->priv) {
86 aom_codec_alg_priv_t *const priv =
87 (aom_codec_alg_priv_t *)aom_calloc(1, sizeof(*priv));
88 if (priv == NULL) return AOM_CODEC_MEM_ERROR;
90 ctx->priv = (aom_codec_priv_t *)priv;
91 ctx->priv->init_flags = ctx->init_flags;
92 priv->flushed = 0;
94 // TODO(tdaede): this should not be exposed to the API
95 priv->cfg.allow_lowbitdepth = !FORCE_HIGHBITDEPTH_DECODING;
96 if (ctx->config.dec) {
97 priv->cfg = *ctx->config.dec;
98 ctx->config.dec = &priv->cfg;
100 priv->num_grain_image_frame_buffers = 0;
101 // Turn row_mt on by default.
102 priv->row_mt = 1;
104 // Turn on normal tile coding mode by default.
105 // 0 is for normal tile coding mode, and 1 is for large scale tile coding
106 // mode(refer to lightfield example).
107 priv->tile_mode = 0;
108 priv->decode_tile_row = -1;
109 priv->decode_tile_col = -1;
112 return AOM_CODEC_OK;
115 static aom_codec_err_t decoder_destroy(aom_codec_alg_priv_t *ctx) {
116 if (ctx->frame_worker != NULL) {
117 AVxWorker *const worker = ctx->frame_worker;
118 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
119 AV1Decoder *const pbi = frame_worker_data->pbi;
120 aom_get_worker_interface()->end(worker);
121 aom_free(pbi->common.tpl_mvs);
122 pbi->common.tpl_mvs = NULL;
123 av1_remove_common(&frame_worker_data->pbi->common);
124 av1_free_cdef_buffers(&pbi->common, &pbi->cdef_worker, &pbi->cdef_sync,
125 pbi->num_workers);
126 av1_free_cdef_sync(&pbi->cdef_sync);
127 #if !CONFIG_REALTIME_ONLY
128 av1_free_restoration_buffers(&pbi->common);
129 #endif
130 av1_decoder_remove(pbi);
131 aom_free(frame_worker_data);
132 #if CONFIG_MULTITHREAD
133 pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
134 #endif
137 if (ctx->buffer_pool) {
138 for (size_t i = 0; i < ctx->num_grain_image_frame_buffers; i++) {
139 ctx->buffer_pool->release_fb_cb(ctx->buffer_pool->cb_priv,
140 &ctx->grain_image_frame_buffers[i]);
142 av1_free_ref_frame_buffers(ctx->buffer_pool);
143 av1_free_internal_frame_buffers(&ctx->buffer_pool->int_frame_buffers);
146 aom_free(ctx->frame_worker);
147 aom_free(ctx->buffer_pool);
148 aom_img_free(&ctx->img);
149 aom_free(ctx);
150 return AOM_CODEC_OK;
153 static aom_codec_err_t parse_timing_info(struct aom_read_bit_buffer *rb) {
154 const uint32_t num_units_in_display_tick =
155 aom_rb_read_unsigned_literal(rb, 32);
156 const uint32_t time_scale = aom_rb_read_unsigned_literal(rb, 32);
157 if (num_units_in_display_tick == 0 || time_scale == 0)
158 return AOM_CODEC_UNSUP_BITSTREAM;
159 const uint8_t equal_picture_interval = aom_rb_read_bit(rb);
160 if (equal_picture_interval) {
161 const uint32_t num_ticks_per_picture_minus_1 = aom_rb_read_uvlc(rb);
162 if (num_ticks_per_picture_minus_1 == UINT32_MAX) {
163 // num_ticks_per_picture_minus_1 cannot be (1 << 32) - 1.
164 return AOM_CODEC_UNSUP_BITSTREAM;
167 return AOM_CODEC_OK;
170 static aom_codec_err_t parse_decoder_model_info(
171 struct aom_read_bit_buffer *rb, int *buffer_delay_length_minus_1) {
172 *buffer_delay_length_minus_1 = aom_rb_read_literal(rb, 5);
173 const uint32_t num_units_in_decoding_tick =
174 aom_rb_read_unsigned_literal(rb, 32);
175 const uint8_t buffer_removal_time_length_minus_1 = aom_rb_read_literal(rb, 5);
176 const uint8_t frame_presentation_time_length_minus_1 =
177 aom_rb_read_literal(rb, 5);
178 (void)num_units_in_decoding_tick;
179 (void)buffer_removal_time_length_minus_1;
180 (void)frame_presentation_time_length_minus_1;
181 return AOM_CODEC_OK;
184 static aom_codec_err_t parse_op_parameters_info(
185 struct aom_read_bit_buffer *rb, int buffer_delay_length_minus_1) {
186 const int n = buffer_delay_length_minus_1 + 1;
187 const uint32_t decoder_buffer_delay = aom_rb_read_unsigned_literal(rb, n);
188 const uint32_t encoder_buffer_delay = aom_rb_read_unsigned_literal(rb, n);
189 const uint8_t low_delay_mode_flag = aom_rb_read_bit(rb);
190 (void)decoder_buffer_delay;
191 (void)encoder_buffer_delay;
192 (void)low_delay_mode_flag;
193 return AOM_CODEC_OK;
196 // Parses the operating points (including operating_point_idc, seq_level_idx,
197 // and seq_tier) and then sets si->number_spatial_layers and
198 // si->number_temporal_layers based on operating_point_idc[0].
199 static aom_codec_err_t parse_operating_points(struct aom_read_bit_buffer *rb,
200 int is_reduced_header,
201 aom_codec_stream_info_t *si) {
202 int operating_point_idc0 = 0;
203 if (is_reduced_header) {
204 aom_rb_read_literal(rb, LEVEL_BITS); // level
205 } else {
206 uint8_t decoder_model_info_present_flag = 0;
207 int buffer_delay_length_minus_1 = 0;
208 aom_codec_err_t status;
209 const uint8_t timing_info_present_flag = aom_rb_read_bit(rb);
210 if (timing_info_present_flag) {
211 if ((status = parse_timing_info(rb)) != AOM_CODEC_OK) return status;
212 decoder_model_info_present_flag = aom_rb_read_bit(rb);
213 if (decoder_model_info_present_flag) {
214 if ((status = parse_decoder_model_info(
215 rb, &buffer_delay_length_minus_1)) != AOM_CODEC_OK)
216 return status;
219 const uint8_t initial_display_delay_present_flag = aom_rb_read_bit(rb);
220 const uint8_t operating_points_cnt_minus_1 =
221 aom_rb_read_literal(rb, OP_POINTS_CNT_MINUS_1_BITS);
222 for (int i = 0; i < operating_points_cnt_minus_1 + 1; i++) {
223 int operating_point_idc;
224 operating_point_idc = aom_rb_read_literal(rb, OP_POINTS_IDC_BITS);
225 if (i == 0) operating_point_idc0 = operating_point_idc;
226 int seq_level_idx = aom_rb_read_literal(rb, LEVEL_BITS); // level
227 if (seq_level_idx > 7) aom_rb_read_bit(rb); // tier
228 if (decoder_model_info_present_flag) {
229 const uint8_t decoder_model_present_for_this_op = aom_rb_read_bit(rb);
230 if (decoder_model_present_for_this_op) {
231 if ((status = parse_op_parameters_info(
232 rb, buffer_delay_length_minus_1)) != AOM_CODEC_OK)
233 return status;
236 if (initial_display_delay_present_flag) {
237 const uint8_t initial_display_delay_present_for_this_op =
238 aom_rb_read_bit(rb);
239 if (initial_display_delay_present_for_this_op)
240 aom_rb_read_literal(rb, 4); // initial_display_delay_minus_1
245 if (aom_get_num_layers_from_operating_point_idc(
246 operating_point_idc0, &si->number_spatial_layers,
247 &si->number_temporal_layers) != AOM_CODEC_OK) {
248 return AOM_CODEC_ERROR;
251 return AOM_CODEC_OK;
254 static aom_codec_err_t decoder_peek_si_internal(const uint8_t *data,
255 size_t data_sz,
256 aom_codec_stream_info_t *si,
257 int *is_intra_only) {
258 int intra_only_flag = 0;
259 int got_sequence_header = 0;
260 int found_keyframe = 0;
262 if (data + data_sz <= data || data_sz < 1) return AOM_CODEC_INVALID_PARAM;
264 si->w = 0;
265 si->h = 0;
266 si->is_kf = 0; // is_kf indicates whether the current packet contains a RAP
268 ObuHeader obu_header;
269 memset(&obu_header, 0, sizeof(obu_header));
270 size_t payload_size = 0;
271 size_t bytes_read = 0;
272 uint8_t reduced_still_picture_hdr = 0;
273 aom_codec_err_t status = aom_read_obu_header_and_size(
274 data, data_sz, si->is_annexb, &obu_header, &payload_size, &bytes_read);
275 if (status != AOM_CODEC_OK) return status;
277 // If the first OBU is a temporal delimiter, skip over it and look at the next
278 // OBU in the bitstream
279 if (obu_header.type == OBU_TEMPORAL_DELIMITER) {
280 // Skip any associated payload (there shouldn't be one, but just in case)
281 if (data_sz < bytes_read + payload_size) return AOM_CODEC_CORRUPT_FRAME;
282 data += bytes_read + payload_size;
283 data_sz -= bytes_read + payload_size;
285 status = aom_read_obu_header_and_size(
286 data, data_sz, si->is_annexb, &obu_header, &payload_size, &bytes_read);
287 if (status != AOM_CODEC_OK) return status;
289 while (1) {
290 data += bytes_read;
291 data_sz -= bytes_read;
292 if (data_sz < payload_size) return AOM_CODEC_CORRUPT_FRAME;
293 // Check that the selected OBU is a sequence header
294 if (obu_header.type == OBU_SEQUENCE_HEADER) {
295 // Sanity check on sequence header size
296 if (data_sz < 2) return AOM_CODEC_CORRUPT_FRAME;
297 // Read a few values from the sequence header payload
298 struct aom_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
300 av1_read_profile(&rb); // profile
301 const uint8_t still_picture = aom_rb_read_bit(&rb);
302 reduced_still_picture_hdr = aom_rb_read_bit(&rb);
304 if (!still_picture && reduced_still_picture_hdr) {
305 return AOM_CODEC_UNSUP_BITSTREAM;
308 if (parse_operating_points(&rb, reduced_still_picture_hdr, si) !=
309 AOM_CODEC_OK) {
310 return AOM_CODEC_ERROR;
313 int num_bits_width = aom_rb_read_literal(&rb, 4) + 1;
314 int num_bits_height = aom_rb_read_literal(&rb, 4) + 1;
315 int max_frame_width = aom_rb_read_literal(&rb, num_bits_width) + 1;
316 int max_frame_height = aom_rb_read_literal(&rb, num_bits_height) + 1;
317 si->w = max_frame_width;
318 si->h = max_frame_height;
319 got_sequence_header = 1;
320 } else if (obu_header.type == OBU_FRAME_HEADER ||
321 obu_header.type == OBU_FRAME) {
322 if (got_sequence_header && reduced_still_picture_hdr) {
323 found_keyframe = 1;
324 break;
325 } else {
326 // make sure we have enough bits to get the frame type out
327 if (data_sz < 1) return AOM_CODEC_CORRUPT_FRAME;
328 struct aom_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
329 const int show_existing_frame = aom_rb_read_bit(&rb);
330 if (!show_existing_frame) {
331 const FRAME_TYPE frame_type = (FRAME_TYPE)aom_rb_read_literal(&rb, 2);
332 if (frame_type == KEY_FRAME) {
333 found_keyframe = 1;
334 break; // Stop here as no further OBUs will change the outcome.
335 } else if (frame_type == INTRA_ONLY_FRAME) {
336 intra_only_flag = 1;
341 // skip past any unread OBU header data
342 data += payload_size;
343 data_sz -= payload_size;
344 if (data_sz == 0) break; // exit if we're out of OBUs
345 status = aom_read_obu_header_and_size(
346 data, data_sz, si->is_annexb, &obu_header, &payload_size, &bytes_read);
347 if (status != AOM_CODEC_OK) return status;
349 if (got_sequence_header && found_keyframe) si->is_kf = 1;
350 if (is_intra_only != NULL) *is_intra_only = intra_only_flag;
351 return AOM_CODEC_OK;
354 static aom_codec_err_t decoder_peek_si(const uint8_t *data, size_t data_sz,
355 aom_codec_stream_info_t *si) {
356 return decoder_peek_si_internal(data, data_sz, si, NULL);
359 static aom_codec_err_t decoder_get_si(aom_codec_alg_priv_t *ctx,
360 aom_codec_stream_info_t *si) {
361 memcpy(si, &ctx->si, sizeof(*si));
363 return AOM_CODEC_OK;
366 static void set_error_detail(aom_codec_alg_priv_t *ctx,
367 const char *const error) {
368 ctx->base.err_detail = error;
371 static aom_codec_err_t update_error_state(
372 aom_codec_alg_priv_t *ctx, const struct aom_internal_error_info *error) {
373 if (error->error_code)
374 set_error_detail(ctx, error->has_detail ? error->detail : NULL);
376 return error->error_code;
379 static void init_buffer_callbacks(aom_codec_alg_priv_t *ctx) {
380 AVxWorker *const worker = ctx->frame_worker;
381 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
382 AV1Decoder *const pbi = frame_worker_data->pbi;
383 AV1_COMMON *const cm = &pbi->common;
384 BufferPool *const pool = cm->buffer_pool;
386 cm->cur_frame = NULL;
387 cm->features.byte_alignment = ctx->byte_alignment;
388 pbi->skip_loop_filter = ctx->skip_loop_filter;
389 pbi->skip_film_grain = ctx->skip_film_grain;
391 if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
392 pool->get_fb_cb = ctx->get_ext_fb_cb;
393 pool->release_fb_cb = ctx->release_ext_fb_cb;
394 pool->cb_priv = ctx->ext_priv;
395 } else {
396 pool->get_fb_cb = av1_get_frame_buffer;
397 pool->release_fb_cb = av1_release_frame_buffer;
399 if (av1_alloc_internal_frame_buffers(&pool->int_frame_buffers))
400 aom_internal_error(&pbi->error, AOM_CODEC_MEM_ERROR,
401 "Failed to initialize internal frame buffers");
403 pool->cb_priv = &pool->int_frame_buffers;
407 static int frame_worker_hook(void *arg1, void *arg2) {
408 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)arg1;
409 const uint8_t *data = frame_worker_data->data;
410 (void)arg2;
412 int result = av1_receive_compressed_data(frame_worker_data->pbi,
413 frame_worker_data->data_size, &data);
414 frame_worker_data->data_end = data;
416 if (result != 0) {
417 // Check decode result in serial decode.
418 frame_worker_data->pbi->need_resync = 1;
420 return !result;
423 static aom_codec_err_t init_decoder(aom_codec_alg_priv_t *ctx) {
424 const AVxWorkerInterface *const winterface = aom_get_worker_interface();
426 ctx->last_show_frame = NULL;
427 ctx->need_resync = 1;
428 ctx->flushed = 0;
430 ctx->buffer_pool = (BufferPool *)aom_calloc(1, sizeof(BufferPool));
431 if (ctx->buffer_pool == NULL) return AOM_CODEC_MEM_ERROR;
433 #if CONFIG_MULTITHREAD
434 if (pthread_mutex_init(&ctx->buffer_pool->pool_mutex, NULL)) {
435 set_error_detail(ctx, "Failed to allocate buffer pool mutex");
436 return AOM_CODEC_MEM_ERROR;
438 #endif
440 ctx->frame_worker = (AVxWorker *)aom_malloc(sizeof(*ctx->frame_worker));
441 if (ctx->frame_worker == NULL) {
442 set_error_detail(ctx, "Failed to allocate frame_worker");
443 return AOM_CODEC_MEM_ERROR;
446 AVxWorker *const worker = ctx->frame_worker;
447 FrameWorkerData *frame_worker_data = NULL;
448 winterface->init(worker);
449 worker->thread_name = "aom frameworker";
450 worker->data1 = aom_memalign(32, sizeof(FrameWorkerData));
451 if (worker->data1 == NULL) {
452 set_error_detail(ctx, "Failed to allocate frame_worker_data");
453 return AOM_CODEC_MEM_ERROR;
455 frame_worker_data = (FrameWorkerData *)worker->data1;
456 frame_worker_data->pbi = av1_decoder_create(ctx->buffer_pool);
457 if (frame_worker_data->pbi == NULL) {
458 set_error_detail(ctx, "Failed to allocate frame_worker_data");
459 return AOM_CODEC_MEM_ERROR;
461 frame_worker_data->frame_context_ready = 0;
462 frame_worker_data->received_frame = 0;
463 frame_worker_data->pbi->allow_lowbitdepth = ctx->cfg.allow_lowbitdepth;
465 // If decoding in serial mode, FrameWorker thread could create tile worker
466 // thread or loopfilter thread.
467 frame_worker_data->pbi->max_threads = ctx->cfg.threads;
468 frame_worker_data->pbi->inv_tile_order = ctx->invert_tile_order;
469 frame_worker_data->pbi->common.tiles.large_scale = ctx->tile_mode;
470 frame_worker_data->pbi->is_annexb = ctx->is_annexb;
471 frame_worker_data->pbi->dec_tile_row = ctx->decode_tile_row;
472 frame_worker_data->pbi->dec_tile_col = ctx->decode_tile_col;
473 frame_worker_data->pbi->operating_point = ctx->operating_point;
474 frame_worker_data->pbi->output_all_layers = ctx->output_all_layers;
475 frame_worker_data->pbi->ext_tile_debug = ctx->ext_tile_debug;
476 frame_worker_data->pbi->row_mt = ctx->row_mt;
477 frame_worker_data->pbi->is_fwd_kf_present = 0;
478 frame_worker_data->pbi->is_arf_frame_present = 0;
479 worker->hook = frame_worker_hook;
481 init_buffer_callbacks(ctx);
483 return AOM_CODEC_OK;
486 static INLINE void check_resync(aom_codec_alg_priv_t *const ctx,
487 const AV1Decoder *const pbi) {
488 // Clear resync flag if worker got a key frame or intra only frame.
489 if (ctx->need_resync == 1 && pbi->need_resync == 0 &&
490 frame_is_intra_only(&pbi->common))
491 ctx->need_resync = 0;
494 static aom_codec_err_t decode_one(aom_codec_alg_priv_t *ctx,
495 const uint8_t **data, size_t data_sz,
496 void *user_priv) {
497 const AVxWorkerInterface *const winterface = aom_get_worker_interface();
499 // Determine the stream parameters. Note that we rely on peek_si to
500 // validate that we have a buffer that does not wrap around the top
501 // of the heap.
502 if (!ctx->si.h) {
503 int is_intra_only = 0;
504 ctx->si.is_annexb = ctx->is_annexb;
505 const aom_codec_err_t res =
506 decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only);
507 if (res != AOM_CODEC_OK) return res;
509 if (!ctx->si.is_kf && !is_intra_only) return AOM_CODEC_ERROR;
512 AVxWorker *const worker = ctx->frame_worker;
513 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
514 frame_worker_data->data = *data;
515 frame_worker_data->data_size = data_sz;
516 frame_worker_data->user_priv = user_priv;
517 frame_worker_data->received_frame = 1;
519 frame_worker_data->pbi->common.tiles.large_scale = ctx->tile_mode;
520 frame_worker_data->pbi->dec_tile_row = ctx->decode_tile_row;
521 frame_worker_data->pbi->dec_tile_col = ctx->decode_tile_col;
522 frame_worker_data->pbi->ext_tile_debug = ctx->ext_tile_debug;
523 frame_worker_data->pbi->row_mt = ctx->row_mt;
524 frame_worker_data->pbi->ext_refs = ctx->ext_refs;
526 frame_worker_data->pbi->is_annexb = ctx->is_annexb;
528 worker->had_error = 0;
529 winterface->execute(worker);
531 // Update data pointer after decode.
532 *data = frame_worker_data->data_end;
534 if (worker->had_error)
535 return update_error_state(ctx, &frame_worker_data->pbi->error);
537 check_resync(ctx, frame_worker_data->pbi);
539 return AOM_CODEC_OK;
542 static void release_pending_output_frames(aom_codec_alg_priv_t *ctx) {
543 // Release any pending output frames from the previous decoder_decode or
544 // decoder_inspect call. We need to do this even if the decoder is being
545 // flushed or the input arguments are invalid.
546 if (ctx->frame_worker) {
547 BufferPool *const pool = ctx->buffer_pool;
548 lock_buffer_pool(pool);
549 AVxWorker *const worker = ctx->frame_worker;
550 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
551 struct AV1Decoder *pbi = frame_worker_data->pbi;
552 for (size_t j = 0; j < pbi->num_output_frames; j++) {
553 decrease_ref_count(pbi->output_frames[j], pool);
555 pbi->num_output_frames = 0;
556 unlock_buffer_pool(pool);
557 for (size_t j = 0; j < ctx->num_grain_image_frame_buffers; j++) {
558 pool->release_fb_cb(pool->cb_priv, &ctx->grain_image_frame_buffers[j]);
559 ctx->grain_image_frame_buffers[j].data = NULL;
560 ctx->grain_image_frame_buffers[j].size = 0;
561 ctx->grain_image_frame_buffers[j].priv = NULL;
563 ctx->num_grain_image_frame_buffers = 0;
567 // This function enables the inspector to inspect non visible frames.
568 static aom_codec_err_t decoder_inspect(aom_codec_alg_priv_t *ctx,
569 const uint8_t *data, size_t data_sz,
570 void *user_priv) {
571 aom_codec_err_t res = AOM_CODEC_OK;
573 release_pending_output_frames(ctx);
575 /* Sanity checks */
576 /* NULL data ptr allowed if data_sz is 0 too */
577 if (data == NULL && data_sz == 0) {
578 ctx->flushed = 1;
579 return AOM_CODEC_OK;
581 if (data == NULL || data_sz == 0) return AOM_CODEC_INVALID_PARAM;
583 // Reset flushed when receiving a valid frame.
584 ctx->flushed = 0;
586 const uint8_t *data_start = data;
587 const uint8_t *data_end = data + data_sz;
589 uint64_t frame_size;
590 if (ctx->is_annexb) {
591 // read the size of this temporal unit
592 size_t length_of_size;
593 uint64_t temporal_unit_size;
594 if (aom_uleb_decode(data_start, data_sz, &temporal_unit_size,
595 &length_of_size) != 0) {
596 return AOM_CODEC_CORRUPT_FRAME;
598 data_start += length_of_size;
599 if (temporal_unit_size > (size_t)(data_end - data_start))
600 return AOM_CODEC_CORRUPT_FRAME;
601 data_end = data_start + temporal_unit_size;
603 // read the size of this frame unit
604 if (aom_uleb_decode(data_start, (size_t)(data_end - data_start),
605 &frame_size, &length_of_size) != 0) {
606 return AOM_CODEC_CORRUPT_FRAME;
608 data_start += length_of_size;
609 if (frame_size > (size_t)(data_end - data_start))
610 return AOM_CODEC_CORRUPT_FRAME;
611 } else {
612 frame_size = (uint64_t)(data_end - data_start);
615 if (ctx->frame_worker == NULL) {
616 res = init_decoder(ctx);
617 if (res != AOM_CODEC_OK) return res;
619 FrameWorkerData *const frame_worker_data =
620 (FrameWorkerData *)ctx->frame_worker->data1;
621 AV1Decoder *const pbi = frame_worker_data->pbi;
622 AV1_COMMON *const cm = &pbi->common;
623 #if CONFIG_INSPECTION
624 frame_worker_data->pbi->inspect_cb = ctx->inspect_cb;
625 frame_worker_data->pbi->inspect_ctx = ctx->inspect_ctx;
626 #endif
627 res = av1_receive_compressed_data(frame_worker_data->pbi, (size_t)frame_size,
628 &data_start);
629 check_resync(ctx, frame_worker_data->pbi);
631 if (ctx->frame_worker->had_error)
632 return update_error_state(ctx, &frame_worker_data->pbi->error);
634 // Allow extra zero bytes after the frame end
635 while (data_start < data_end) {
636 const uint8_t marker = data_start[0];
637 if (marker) break;
638 ++data_start;
641 Av1DecodeReturn *data2 = (Av1DecodeReturn *)user_priv;
642 data2->idx = -1;
643 if (cm->cur_frame) {
644 for (int i = 0; i < REF_FRAMES; ++i)
645 if (cm->ref_frame_map[i] == cm->cur_frame) data2->idx = i;
647 data2->buf = data_start;
648 data2->show_existing = cm->show_existing_frame;
649 return res;
652 static aom_codec_err_t decoder_decode(aom_codec_alg_priv_t *ctx,
653 const uint8_t *data, size_t data_sz,
654 void *user_priv) {
655 aom_codec_err_t res = AOM_CODEC_OK;
657 #if CONFIG_INSPECTION
658 if (user_priv != 0) {
659 return decoder_inspect(ctx, data, data_sz, user_priv);
661 #endif
663 release_pending_output_frames(ctx);
665 /* Sanity checks */
666 /* NULL data ptr allowed if data_sz is 0 too */
667 if (data == NULL && data_sz == 0) {
668 ctx->flushed = 1;
669 return AOM_CODEC_OK;
671 if (data == NULL || data_sz == 0) return AOM_CODEC_INVALID_PARAM;
673 // Reset flushed when receiving a valid frame.
674 ctx->flushed = 0;
676 // Initialize the decoder worker on the first frame.
677 if (ctx->frame_worker == NULL) {
678 res = init_decoder(ctx);
679 if (res != AOM_CODEC_OK) return res;
682 const uint8_t *data_start = data;
683 const uint8_t *data_end = data + data_sz;
685 if (ctx->is_annexb) {
686 // read the size of this temporal unit
687 size_t length_of_size;
688 uint64_t temporal_unit_size;
689 if (aom_uleb_decode(data_start, data_sz, &temporal_unit_size,
690 &length_of_size) != 0) {
691 return AOM_CODEC_CORRUPT_FRAME;
693 data_start += length_of_size;
694 if (temporal_unit_size > (size_t)(data_end - data_start))
695 return AOM_CODEC_CORRUPT_FRAME;
696 data_end = data_start + temporal_unit_size;
699 // Decode in serial mode.
700 while (data_start < data_end) {
701 uint64_t frame_size;
702 if (ctx->is_annexb) {
703 // read the size of this frame unit
704 size_t length_of_size;
705 if (aom_uleb_decode(data_start, (size_t)(data_end - data_start),
706 &frame_size, &length_of_size) != 0) {
707 return AOM_CODEC_CORRUPT_FRAME;
709 data_start += length_of_size;
710 if (frame_size > (size_t)(data_end - data_start))
711 return AOM_CODEC_CORRUPT_FRAME;
712 } else {
713 frame_size = (uint64_t)(data_end - data_start);
716 res = decode_one(ctx, &data_start, (size_t)frame_size, user_priv);
717 if (res != AOM_CODEC_OK) return res;
719 // Allow extra zero bytes after the frame end
720 while (data_start < data_end) {
721 const uint8_t marker = data_start[0];
722 if (marker) break;
723 ++data_start;
727 return res;
730 typedef struct {
731 BufferPool *pool;
732 aom_codec_frame_buffer_t *fb;
733 } AllocCbParam;
735 static void *AllocWithGetFrameBufferCb(void *priv, size_t size) {
736 AllocCbParam *param = (AllocCbParam *)priv;
737 if (param->pool->get_fb_cb(param->pool->cb_priv, size, param->fb) < 0)
738 return NULL;
739 if (param->fb->data == NULL || param->fb->size < size) return NULL;
740 return param->fb->data;
743 // If grain_params->apply_grain is false, returns img. Otherwise, adds film
744 // grain to img, saves the result in grain_img, and returns grain_img.
745 static aom_image_t *add_grain_if_needed(aom_codec_alg_priv_t *ctx,
746 aom_image_t *img,
747 aom_image_t *grain_img,
748 aom_film_grain_t *grain_params) {
749 if (!grain_params->apply_grain) return img;
751 const int w_even = ALIGN_POWER_OF_TWO(img->d_w, 1);
752 const int h_even = ALIGN_POWER_OF_TWO(img->d_h, 1);
754 BufferPool *const pool = ctx->buffer_pool;
755 aom_codec_frame_buffer_t *fb =
756 &ctx->grain_image_frame_buffers[ctx->num_grain_image_frame_buffers];
757 AllocCbParam param;
758 param.pool = pool;
759 param.fb = fb;
760 if (!aom_img_alloc_with_cb(grain_img, img->fmt, w_even, h_even, 16,
761 AllocWithGetFrameBufferCb, &param)) {
762 return NULL;
765 grain_img->user_priv = img->user_priv;
766 grain_img->fb_priv = fb->priv;
767 if (av1_add_film_grain(grain_params, img, grain_img)) {
768 pool->release_fb_cb(pool->cb_priv, fb);
769 return NULL;
772 ctx->num_grain_image_frame_buffers++;
773 return grain_img;
776 // Copies and clears the metadata from AV1Decoder.
777 static void move_decoder_metadata_to_img(AV1Decoder *pbi, aom_image_t *img) {
778 if (pbi->metadata && img) {
779 assert(!img->metadata);
780 img->metadata = pbi->metadata;
781 pbi->metadata = NULL;
785 static aom_image_t *decoder_get_frame(aom_codec_alg_priv_t *ctx,
786 aom_codec_iter_t *iter) {
787 aom_image_t *img = NULL;
789 if (!iter) {
790 return NULL;
793 // To avoid having to allocate any extra storage, treat 'iter' as
794 // simply a pointer to an integer index
795 uintptr_t *index = (uintptr_t *)iter;
797 if (ctx->frame_worker != NULL) {
798 const AVxWorkerInterface *const winterface = aom_get_worker_interface();
799 AVxWorker *const worker = ctx->frame_worker;
800 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
801 AV1Decoder *const pbi = frame_worker_data->pbi;
802 AV1_COMMON *const cm = &pbi->common;
803 CommonTileParams *const tiles = &cm->tiles;
804 // Wait for the frame from worker thread.
805 if (winterface->sync(worker)) {
806 // Check if worker has received any frames.
807 if (frame_worker_data->received_frame == 1) {
808 frame_worker_data->received_frame = 0;
809 check_resync(ctx, frame_worker_data->pbi);
811 YV12_BUFFER_CONFIG *sd;
812 aom_film_grain_t *grain_params;
813 if (av1_get_raw_frame(frame_worker_data->pbi, *index, &sd,
814 &grain_params) == 0) {
815 RefCntBuffer *const output_frame_buf = pbi->output_frames[*index];
816 ctx->last_show_frame = output_frame_buf;
817 if (ctx->need_resync) return NULL;
818 aom_img_remove_metadata(&ctx->img);
819 yuvconfig2image(&ctx->img, sd, frame_worker_data->user_priv);
820 move_decoder_metadata_to_img(pbi, &ctx->img);
822 if (!pbi->ext_tile_debug && tiles->large_scale) {
823 *index += 1; // Advance the iterator to point to the next image
824 aom_img_remove_metadata(&ctx->img);
825 yuvconfig2image(&ctx->img, &pbi->tile_list_outbuf, NULL);
826 move_decoder_metadata_to_img(pbi, &ctx->img);
827 img = &ctx->img;
828 return img;
831 const int num_planes = av1_num_planes(cm);
832 if (pbi->ext_tile_debug && tiles->single_tile_decoding &&
833 pbi->dec_tile_row >= 0) {
834 int tile_width, tile_height;
835 av1_get_uniform_tile_size(cm, &tile_width, &tile_height);
836 const int tile_row = AOMMIN(pbi->dec_tile_row, tiles->rows - 1);
837 const int mi_row = tile_row * tile_height;
838 const int ssy = ctx->img.y_chroma_shift;
839 int plane;
840 ctx->img.planes[0] += mi_row * MI_SIZE * ctx->img.stride[0];
841 if (num_planes > 1) {
842 for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
843 ctx->img.planes[plane] +=
844 mi_row * (MI_SIZE >> ssy) * ctx->img.stride[plane];
847 ctx->img.d_h =
848 AOMMIN(tile_height, cm->mi_params.mi_rows - mi_row) * MI_SIZE;
851 if (pbi->ext_tile_debug && tiles->single_tile_decoding &&
852 pbi->dec_tile_col >= 0) {
853 int tile_width, tile_height;
854 av1_get_uniform_tile_size(cm, &tile_width, &tile_height);
855 const int tile_col = AOMMIN(pbi->dec_tile_col, tiles->cols - 1);
856 const int mi_col = tile_col * tile_width;
857 const int ssx = ctx->img.x_chroma_shift;
858 const int is_hbd = (ctx->img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 1 : 0;
859 int plane;
860 ctx->img.planes[0] += mi_col * MI_SIZE * (1 + is_hbd);
861 if (num_planes > 1) {
862 for (plane = 1; plane < MAX_MB_PLANE; ++plane) {
863 ctx->img.planes[plane] +=
864 mi_col * (MI_SIZE >> ssx) * (1 + is_hbd);
867 ctx->img.d_w =
868 AOMMIN(tile_width, cm->mi_params.mi_cols - mi_col) * MI_SIZE;
871 ctx->img.fb_priv = output_frame_buf->raw_frame_buffer.priv;
872 img = &ctx->img;
873 img->temporal_id = output_frame_buf->temporal_id;
874 img->spatial_id = output_frame_buf->spatial_id;
875 if (pbi->skip_film_grain) grain_params->apply_grain = 0;
876 aom_image_t *res =
877 add_grain_if_needed(ctx, img, &ctx->image_with_grain, grain_params);
878 if (!res) {
879 aom_internal_error(&pbi->error, AOM_CODEC_CORRUPT_FRAME,
880 "Grain systhesis failed\n");
882 *index += 1; // Advance the iterator to point to the next image
883 return res;
885 } else {
886 // Decoding failed. Release the worker thread.
887 frame_worker_data->received_frame = 0;
888 ctx->need_resync = 1;
889 if (ctx->flushed != 1) return NULL;
892 return NULL;
895 static aom_codec_err_t decoder_set_fb_fn(
896 aom_codec_alg_priv_t *ctx, aom_get_frame_buffer_cb_fn_t cb_get,
897 aom_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
898 if (cb_get == NULL || cb_release == NULL) {
899 return AOM_CODEC_INVALID_PARAM;
900 } else if (ctx->frame_worker == NULL) {
901 // If the decoder has already been initialized, do not accept changes to
902 // the frame buffer functions.
903 ctx->get_ext_fb_cb = cb_get;
904 ctx->release_ext_fb_cb = cb_release;
905 ctx->ext_priv = cb_priv;
906 return AOM_CODEC_OK;
909 return AOM_CODEC_ERROR;
912 static aom_codec_err_t ctrl_set_reference(aom_codec_alg_priv_t *ctx,
913 va_list args) {
914 av1_ref_frame_t *const data = va_arg(args, av1_ref_frame_t *);
916 if (data) {
917 av1_ref_frame_t *const frame = data;
918 YV12_BUFFER_CONFIG sd;
919 AVxWorker *const worker = ctx->frame_worker;
920 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
921 image2yuvconfig(&frame->img, &sd);
922 return av1_set_reference_dec(&frame_worker_data->pbi->common, frame->idx,
923 frame->use_external_ref, &sd);
924 } else {
925 return AOM_CODEC_INVALID_PARAM;
929 static aom_codec_err_t ctrl_copy_reference(aom_codec_alg_priv_t *ctx,
930 va_list args) {
931 const av1_ref_frame_t *const frame = va_arg(args, av1_ref_frame_t *);
932 if (frame) {
933 YV12_BUFFER_CONFIG sd;
934 AVxWorker *const worker = ctx->frame_worker;
935 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
936 image2yuvconfig(&frame->img, &sd);
937 return av1_copy_reference_dec(frame_worker_data->pbi, frame->idx, &sd);
938 } else {
939 return AOM_CODEC_INVALID_PARAM;
943 static aom_codec_err_t ctrl_get_reference(aom_codec_alg_priv_t *ctx,
944 va_list args) {
945 av1_ref_frame_t *data = va_arg(args, av1_ref_frame_t *);
946 if (data) {
947 YV12_BUFFER_CONFIG *fb;
948 AVxWorker *const worker = ctx->frame_worker;
949 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
950 fb = get_ref_frame(&frame_worker_data->pbi->common, data->idx);
951 if (fb == NULL) return AOM_CODEC_ERROR;
952 yuvconfig2image(&data->img, fb, NULL);
953 return AOM_CODEC_OK;
954 } else {
955 return AOM_CODEC_INVALID_PARAM;
959 static aom_codec_err_t ctrl_get_new_frame_image(aom_codec_alg_priv_t *ctx,
960 va_list args) {
961 aom_image_t *new_img = va_arg(args, aom_image_t *);
962 if (new_img) {
963 YV12_BUFFER_CONFIG new_frame;
964 AVxWorker *const worker = ctx->frame_worker;
965 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
967 if (av1_get_frame_to_show(frame_worker_data->pbi, &new_frame) == 0) {
968 yuvconfig2image(new_img, &new_frame, NULL);
969 return AOM_CODEC_OK;
970 } else {
971 return AOM_CODEC_ERROR;
973 } else {
974 return AOM_CODEC_INVALID_PARAM;
978 static aom_codec_err_t ctrl_copy_new_frame_image(aom_codec_alg_priv_t *ctx,
979 va_list args) {
980 aom_image_t *img = va_arg(args, aom_image_t *);
981 if (img) {
982 YV12_BUFFER_CONFIG new_frame;
983 AVxWorker *const worker = ctx->frame_worker;
984 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
986 if (av1_get_frame_to_show(frame_worker_data->pbi, &new_frame) == 0) {
987 YV12_BUFFER_CONFIG sd;
988 image2yuvconfig(img, &sd);
989 return av1_copy_new_frame_dec(&frame_worker_data->pbi->common, &new_frame,
990 &sd);
991 } else {
992 return AOM_CODEC_ERROR;
994 } else {
995 return AOM_CODEC_INVALID_PARAM;
999 static aom_codec_err_t ctrl_get_last_ref_updates(aom_codec_alg_priv_t *ctx,
1000 va_list args) {
1001 int *const update_info = va_arg(args, int *);
1003 if (update_info) {
1004 if (ctx->frame_worker) {
1005 AVxWorker *const worker = ctx->frame_worker;
1006 FrameWorkerData *const frame_worker_data =
1007 (FrameWorkerData *)worker->data1;
1008 *update_info =
1009 frame_worker_data->pbi->common.current_frame.refresh_frame_flags;
1010 return AOM_CODEC_OK;
1011 } else {
1012 return AOM_CODEC_ERROR;
1016 return AOM_CODEC_INVALID_PARAM;
1019 static aom_codec_err_t ctrl_get_last_quantizer(aom_codec_alg_priv_t *ctx,
1020 va_list args) {
1021 int *const arg = va_arg(args, int *);
1022 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1023 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1024 *arg = ((FrameWorkerData *)ctx->frame_worker->data1)
1025 ->pbi->common.quant_params.base_qindex;
1026 return AOM_CODEC_OK;
1029 static aom_codec_err_t ctrl_get_fwd_kf_value(aom_codec_alg_priv_t *ctx,
1030 va_list args) {
1031 int *const arg = va_arg(args, int *);
1032 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1033 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1034 *arg = ((FrameWorkerData *)ctx->frame_worker->data1)->pbi->is_fwd_kf_present;
1035 return AOM_CODEC_OK;
1038 static aom_codec_err_t ctrl_get_altref_present(aom_codec_alg_priv_t *ctx,
1039 va_list args) {
1040 int *const arg = va_arg(args, int *);
1041 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1042 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1043 *arg =
1044 ((FrameWorkerData *)ctx->frame_worker->data1)->pbi->is_arf_frame_present;
1045 return AOM_CODEC_OK;
1048 static aom_codec_err_t ctrl_get_frame_flags(aom_codec_alg_priv_t *ctx,
1049 va_list args) {
1050 int *const arg = va_arg(args, int *);
1051 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1052 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1053 AV1Decoder *pbi = ((FrameWorkerData *)ctx->frame_worker->data1)->pbi;
1054 *arg = 0;
1055 switch (pbi->common.current_frame.frame_type) {
1056 case KEY_FRAME:
1057 *arg |= AOM_FRAME_IS_KEY;
1058 *arg |= AOM_FRAME_IS_INTRAONLY;
1059 if (!pbi->common.show_frame) {
1060 *arg |= AOM_FRAME_IS_DELAYED_RANDOM_ACCESS_POINT;
1062 break;
1063 case INTRA_ONLY_FRAME: *arg |= AOM_FRAME_IS_INTRAONLY; break;
1064 case S_FRAME: *arg |= AOM_FRAME_IS_SWITCH; break;
1066 if (pbi->common.features.error_resilient_mode) {
1067 *arg |= AOM_FRAME_IS_ERROR_RESILIENT;
1069 return AOM_CODEC_OK;
1072 static aom_codec_err_t ctrl_get_tile_info(aom_codec_alg_priv_t *ctx,
1073 va_list args) {
1074 aom_tile_info *const tile_info = va_arg(args, aom_tile_info *);
1076 if (tile_info) {
1077 if (ctx->frame_worker) {
1078 AVxWorker *const worker = ctx->frame_worker;
1079 FrameWorkerData *const frame_worker_data =
1080 (FrameWorkerData *)worker->data1;
1081 const AV1Decoder *pbi = frame_worker_data->pbi;
1082 const CommonTileParams *tiles = &pbi->common.tiles;
1084 int tile_rows = tiles->rows;
1085 int tile_cols = tiles->cols;
1087 if (tiles->uniform_spacing) {
1088 tile_info->tile_rows = 1 << tiles->log2_rows;
1089 tile_info->tile_columns = 1 << tiles->log2_cols;
1090 } else {
1091 tile_info->tile_rows = tile_rows;
1092 tile_info->tile_columns = tile_cols;
1095 for (int tile_col = 1; tile_col <= tile_cols; tile_col++) {
1096 tile_info->tile_widths[tile_col - 1] =
1097 tiles->col_start_sb[tile_col] - tiles->col_start_sb[tile_col - 1];
1100 for (int tile_row = 1; tile_row <= tile_rows; tile_row++) {
1101 tile_info->tile_heights[tile_row - 1] =
1102 tiles->row_start_sb[tile_row] - tiles->row_start_sb[tile_row - 1];
1104 tile_info->num_tile_groups = pbi->num_tile_groups;
1105 return AOM_CODEC_OK;
1106 } else {
1107 return AOM_CODEC_ERROR;
1111 return AOM_CODEC_INVALID_PARAM;
1114 static aom_codec_err_t ctrl_get_screen_content_tools_info(
1115 aom_codec_alg_priv_t *ctx, va_list args) {
1116 aom_screen_content_tools_info *const sc_info =
1117 va_arg(args, aom_screen_content_tools_info *);
1118 if (sc_info) {
1119 if (ctx->frame_worker) {
1120 AVxWorker *const worker = ctx->frame_worker;
1121 FrameWorkerData *const frame_worker_data =
1122 (FrameWorkerData *)worker->data1;
1123 const AV1Decoder *pbi = frame_worker_data->pbi;
1124 sc_info->allow_screen_content_tools =
1125 pbi->common.features.allow_screen_content_tools;
1126 sc_info->allow_intrabc = pbi->common.features.allow_intrabc;
1127 sc_info->force_integer_mv =
1128 (int)pbi->common.features.cur_frame_force_integer_mv;
1129 return AOM_CODEC_OK;
1130 } else {
1131 return AOM_CODEC_ERROR;
1134 return AOM_CODEC_INVALID_PARAM;
1137 static aom_codec_err_t ctrl_get_still_picture(aom_codec_alg_priv_t *ctx,
1138 va_list args) {
1139 aom_still_picture_info *const still_picture_info =
1140 va_arg(args, aom_still_picture_info *);
1141 if (still_picture_info) {
1142 if (ctx->frame_worker) {
1143 AVxWorker *const worker = ctx->frame_worker;
1144 FrameWorkerData *const frame_worker_data =
1145 (FrameWorkerData *)worker->data1;
1146 const AV1Decoder *pbi = frame_worker_data->pbi;
1147 still_picture_info->is_still_picture = (int)pbi->seq_params.still_picture;
1148 still_picture_info->is_reduced_still_picture_hdr =
1149 (int)(pbi->seq_params.reduced_still_picture_hdr);
1150 return AOM_CODEC_OK;
1151 } else {
1152 return AOM_CODEC_ERROR;
1155 return AOM_CODEC_INVALID_PARAM;
1158 static aom_codec_err_t ctrl_get_sb_size(aom_codec_alg_priv_t *ctx,
1159 va_list args) {
1160 aom_superblock_size_t *const sb_size = va_arg(args, aom_superblock_size_t *);
1161 if (sb_size) {
1162 if (ctx->frame_worker) {
1163 AVxWorker *const worker = ctx->frame_worker;
1164 FrameWorkerData *const frame_worker_data =
1165 (FrameWorkerData *)worker->data1;
1166 const AV1Decoder *pbi = frame_worker_data->pbi;
1167 if (pbi->seq_params.sb_size == BLOCK_128X128) {
1168 *sb_size = AOM_SUPERBLOCK_SIZE_128X128;
1169 } else {
1170 *sb_size = AOM_SUPERBLOCK_SIZE_64X64;
1172 return AOM_CODEC_OK;
1173 } else {
1174 return AOM_CODEC_ERROR;
1177 return AOM_CODEC_INVALID_PARAM;
1180 static aom_codec_err_t ctrl_get_show_existing_frame_flag(
1181 aom_codec_alg_priv_t *ctx, va_list args) {
1182 int *const arg = va_arg(args, int *);
1183 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1184 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1185 *arg = ((FrameWorkerData *)ctx->frame_worker->data1)
1186 ->pbi->common.show_existing_frame;
1187 return AOM_CODEC_OK;
1190 static aom_codec_err_t ctrl_get_s_frame_info(aom_codec_alg_priv_t *ctx,
1191 va_list args) {
1192 aom_s_frame_info *const s_frame_info = va_arg(args, aom_s_frame_info *);
1193 if (s_frame_info) {
1194 if (ctx->frame_worker) {
1195 AVxWorker *const worker = ctx->frame_worker;
1196 FrameWorkerData *const frame_worker_data =
1197 (FrameWorkerData *)worker->data1;
1198 const AV1Decoder *pbi = frame_worker_data->pbi;
1199 s_frame_info->is_s_frame = pbi->sframe_info.is_s_frame;
1200 s_frame_info->is_s_frame_at_altref =
1201 pbi->sframe_info.is_s_frame_at_altref;
1202 return AOM_CODEC_OK;
1203 } else {
1204 return AOM_CODEC_ERROR;
1207 return AOM_CODEC_INVALID_PARAM;
1210 static aom_codec_err_t ctrl_get_frame_corrupted(aom_codec_alg_priv_t *ctx,
1211 va_list args) {
1212 int *corrupted = va_arg(args, int *);
1214 if (corrupted) {
1215 if (ctx->frame_worker) {
1216 AVxWorker *const worker = ctx->frame_worker;
1217 FrameWorkerData *const frame_worker_data =
1218 (FrameWorkerData *)worker->data1;
1219 AV1Decoder *const pbi = frame_worker_data->pbi;
1220 if (pbi->seen_frame_header && pbi->num_output_frames == 0)
1221 return AOM_CODEC_ERROR;
1222 if (ctx->last_show_frame != NULL)
1223 *corrupted = ctx->last_show_frame->buf.corrupted;
1224 return AOM_CODEC_OK;
1225 } else {
1226 return AOM_CODEC_ERROR;
1230 return AOM_CODEC_INVALID_PARAM;
1233 static aom_codec_err_t ctrl_get_frame_size(aom_codec_alg_priv_t *ctx,
1234 va_list args) {
1235 int *const frame_size = va_arg(args, int *);
1237 if (frame_size) {
1238 if (ctx->frame_worker) {
1239 AVxWorker *const worker = ctx->frame_worker;
1240 FrameWorkerData *const frame_worker_data =
1241 (FrameWorkerData *)worker->data1;
1242 const AV1_COMMON *const cm = &frame_worker_data->pbi->common;
1243 frame_size[0] = cm->width;
1244 frame_size[1] = cm->height;
1245 return AOM_CODEC_OK;
1246 } else {
1247 return AOM_CODEC_ERROR;
1251 return AOM_CODEC_INVALID_PARAM;
1254 static aom_codec_err_t ctrl_get_frame_header_info(aom_codec_alg_priv_t *ctx,
1255 va_list args) {
1256 aom_tile_data *const frame_header_info = va_arg(args, aom_tile_data *);
1258 if (frame_header_info) {
1259 if (ctx->frame_worker) {
1260 AVxWorker *const worker = ctx->frame_worker;
1261 FrameWorkerData *const frame_worker_data =
1262 (FrameWorkerData *)worker->data1;
1263 const AV1Decoder *pbi = frame_worker_data->pbi;
1264 frame_header_info->coded_tile_data_size = pbi->obu_size_hdr.size;
1265 frame_header_info->coded_tile_data = pbi->obu_size_hdr.data;
1266 frame_header_info->extra_size = pbi->frame_header_size;
1267 return AOM_CODEC_OK;
1268 } else {
1269 return AOM_CODEC_ERROR;
1273 return AOM_CODEC_INVALID_PARAM;
1276 static aom_codec_err_t ctrl_get_tile_data(aom_codec_alg_priv_t *ctx,
1277 va_list args) {
1278 aom_tile_data *const tile_data = va_arg(args, aom_tile_data *);
1280 if (tile_data) {
1281 if (ctx->frame_worker) {
1282 AVxWorker *const worker = ctx->frame_worker;
1283 FrameWorkerData *const frame_worker_data =
1284 (FrameWorkerData *)worker->data1;
1285 const AV1Decoder *pbi = frame_worker_data->pbi;
1286 tile_data->coded_tile_data_size =
1287 pbi->tile_buffers[pbi->dec_tile_row][pbi->dec_tile_col].size;
1288 tile_data->coded_tile_data =
1289 pbi->tile_buffers[pbi->dec_tile_row][pbi->dec_tile_col].data;
1290 return AOM_CODEC_OK;
1291 } else {
1292 return AOM_CODEC_ERROR;
1296 return AOM_CODEC_INVALID_PARAM;
1299 static aom_codec_err_t ctrl_set_ext_ref_ptr(aom_codec_alg_priv_t *ctx,
1300 va_list args) {
1301 av1_ext_ref_frame_t *const data = va_arg(args, av1_ext_ref_frame_t *);
1303 if (data) {
1304 av1_ext_ref_frame_t *const ext_frames = data;
1305 ctx->ext_refs.num = ext_frames->num;
1306 for (int i = 0; i < ctx->ext_refs.num; i++) {
1307 image2yuvconfig(ext_frames->img++, &ctx->ext_refs.refs[i]);
1309 return AOM_CODEC_OK;
1310 } else {
1311 return AOM_CODEC_INVALID_PARAM;
1315 static aom_codec_err_t ctrl_get_render_size(aom_codec_alg_priv_t *ctx,
1316 va_list args) {
1317 int *const render_size = va_arg(args, int *);
1319 if (render_size) {
1320 if (ctx->frame_worker) {
1321 AVxWorker *const worker = ctx->frame_worker;
1322 FrameWorkerData *const frame_worker_data =
1323 (FrameWorkerData *)worker->data1;
1324 const AV1_COMMON *const cm = &frame_worker_data->pbi->common;
1325 render_size[0] = cm->render_width;
1326 render_size[1] = cm->render_height;
1327 return AOM_CODEC_OK;
1328 } else {
1329 return AOM_CODEC_ERROR;
1333 return AOM_CODEC_INVALID_PARAM;
1336 static aom_codec_err_t ctrl_get_bit_depth(aom_codec_alg_priv_t *ctx,
1337 va_list args) {
1338 unsigned int *const bit_depth = va_arg(args, unsigned int *);
1339 AVxWorker *const worker = ctx->frame_worker;
1341 if (bit_depth) {
1342 if (worker) {
1343 FrameWorkerData *const frame_worker_data =
1344 (FrameWorkerData *)worker->data1;
1345 const AV1_COMMON *const cm = &frame_worker_data->pbi->common;
1346 *bit_depth = cm->seq_params->bit_depth;
1347 return AOM_CODEC_OK;
1348 } else {
1349 return AOM_CODEC_ERROR;
1353 return AOM_CODEC_INVALID_PARAM;
1356 static aom_img_fmt_t get_img_format(int subsampling_x, int subsampling_y,
1357 int use_highbitdepth) {
1358 aom_img_fmt_t fmt = 0;
1360 if (subsampling_x == 0 && subsampling_y == 0)
1361 fmt = AOM_IMG_FMT_I444;
1362 else if (subsampling_x == 1 && subsampling_y == 0)
1363 fmt = AOM_IMG_FMT_I422;
1364 else if (subsampling_x == 1 && subsampling_y == 1)
1365 fmt = AOM_IMG_FMT_I420;
1367 if (use_highbitdepth) fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
1368 return fmt;
1371 static aom_codec_err_t ctrl_get_img_format(aom_codec_alg_priv_t *ctx,
1372 va_list args) {
1373 aom_img_fmt_t *const img_fmt = va_arg(args, aom_img_fmt_t *);
1374 AVxWorker *const worker = ctx->frame_worker;
1376 if (img_fmt) {
1377 if (worker) {
1378 FrameWorkerData *const frame_worker_data =
1379 (FrameWorkerData *)worker->data1;
1380 const AV1_COMMON *const cm = &frame_worker_data->pbi->common;
1382 *img_fmt = get_img_format(cm->seq_params->subsampling_x,
1383 cm->seq_params->subsampling_y,
1384 cm->seq_params->use_highbitdepth);
1385 return AOM_CODEC_OK;
1386 } else {
1387 return AOM_CODEC_ERROR;
1391 return AOM_CODEC_INVALID_PARAM;
1394 static aom_codec_err_t ctrl_get_tile_size(aom_codec_alg_priv_t *ctx,
1395 va_list args) {
1396 unsigned int *const tile_size = va_arg(args, unsigned int *);
1397 AVxWorker *const worker = ctx->frame_worker;
1399 if (tile_size) {
1400 if (worker) {
1401 FrameWorkerData *const frame_worker_data =
1402 (FrameWorkerData *)worker->data1;
1403 const AV1_COMMON *const cm = &frame_worker_data->pbi->common;
1404 int tile_width, tile_height;
1405 av1_get_uniform_tile_size(cm, &tile_width, &tile_height);
1406 *tile_size = ((tile_width * MI_SIZE) << 16) + tile_height * MI_SIZE;
1407 return AOM_CODEC_OK;
1408 } else {
1409 return AOM_CODEC_ERROR;
1412 return AOM_CODEC_INVALID_PARAM;
1415 static aom_codec_err_t ctrl_get_tile_count(aom_codec_alg_priv_t *ctx,
1416 va_list args) {
1417 unsigned int *const tile_count = va_arg(args, unsigned int *);
1419 if (tile_count) {
1420 AVxWorker *const worker = ctx->frame_worker;
1421 if (worker) {
1422 FrameWorkerData *const frame_worker_data =
1423 (FrameWorkerData *)worker->data1;
1424 *tile_count = frame_worker_data->pbi->tile_count_minus_1 + 1;
1425 return AOM_CODEC_OK;
1426 } else {
1427 return AOM_CODEC_ERROR;
1430 return AOM_CODEC_INVALID_PARAM;
1433 static aom_codec_err_t ctrl_get_base_q_idx(aom_codec_alg_priv_t *ctx,
1434 va_list args) {
1435 int *const arg = va_arg(args, int *);
1436 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1437 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1438 FrameWorkerData *const frame_worker_data =
1439 (FrameWorkerData *)ctx->frame_worker->data1;
1440 *arg = frame_worker_data->pbi->common.quant_params.base_qindex;
1441 return AOM_CODEC_OK;
1444 static aom_codec_err_t ctrl_get_show_frame_flag(aom_codec_alg_priv_t *ctx,
1445 va_list args) {
1446 int *const arg = va_arg(args, int *);
1447 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1448 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1449 FrameWorkerData *const frame_worker_data =
1450 (FrameWorkerData *)ctx->frame_worker->data1;
1451 *arg = frame_worker_data->pbi->common.show_frame;
1452 return AOM_CODEC_OK;
1455 static aom_codec_err_t ctrl_get_order_hint(aom_codec_alg_priv_t *ctx,
1456 va_list args) {
1457 unsigned int *const arg = va_arg(args, unsigned int *);
1458 if (arg == NULL) return AOM_CODEC_INVALID_PARAM;
1459 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1460 FrameWorkerData *const frame_worker_data =
1461 (FrameWorkerData *)ctx->frame_worker->data1;
1462 *arg = frame_worker_data->pbi->common.current_frame.order_hint;
1463 return AOM_CODEC_OK;
1466 static aom_codec_err_t ctrl_get_mi_info(aom_codec_alg_priv_t *ctx,
1467 va_list args) {
1468 int mi_row = va_arg(args, int);
1469 int mi_col = va_arg(args, int);
1470 MB_MODE_INFO *mi = va_arg(args, MB_MODE_INFO *);
1471 if (mi == NULL) return AOM_CODEC_INVALID_PARAM;
1472 if (ctx->frame_worker == NULL) return AOM_CODEC_ERROR;
1473 FrameWorkerData *const frame_worker_data =
1474 (FrameWorkerData *)ctx->frame_worker->data1;
1475 if (frame_worker_data == NULL) return AOM_CODEC_ERROR;
1477 AV1_COMMON *cm = &frame_worker_data->pbi->common;
1478 const int mi_rows = cm->mi_params.mi_rows;
1479 const int mi_cols = cm->mi_params.mi_cols;
1480 const int mi_stride = cm->mi_params.mi_stride;
1481 const int offset = mi_row * mi_stride + mi_col;
1483 if (mi_row < 0 || mi_row >= mi_rows || mi_col < 0 || mi_col >= mi_cols) {
1484 return AOM_CODEC_INVALID_PARAM;
1487 memcpy(mi, cm->mi_params.mi_grid_base[offset], sizeof(*mi));
1489 return AOM_CODEC_OK;
1492 static aom_codec_err_t ctrl_set_invert_tile_order(aom_codec_alg_priv_t *ctx,
1493 va_list args) {
1494 ctx->invert_tile_order = va_arg(args, int);
1495 return AOM_CODEC_OK;
1498 static aom_codec_err_t ctrl_set_byte_alignment(aom_codec_alg_priv_t *ctx,
1499 va_list args) {
1500 const int legacy_byte_alignment = 0;
1501 const int min_byte_alignment = 32;
1502 const int max_byte_alignment = 1024;
1503 const int byte_alignment = va_arg(args, int);
1505 if (byte_alignment != legacy_byte_alignment &&
1506 (byte_alignment < min_byte_alignment ||
1507 byte_alignment > max_byte_alignment ||
1508 (byte_alignment & (byte_alignment - 1)) != 0))
1509 return AOM_CODEC_INVALID_PARAM;
1511 ctx->byte_alignment = byte_alignment;
1512 if (ctx->frame_worker) {
1513 AVxWorker *const worker = ctx->frame_worker;
1514 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
1515 frame_worker_data->pbi->common.features.byte_alignment = byte_alignment;
1517 return AOM_CODEC_OK;
1520 static aom_codec_err_t ctrl_set_skip_loop_filter(aom_codec_alg_priv_t *ctx,
1521 va_list args) {
1522 ctx->skip_loop_filter = va_arg(args, int);
1524 if (ctx->frame_worker) {
1525 AVxWorker *const worker = ctx->frame_worker;
1526 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
1527 frame_worker_data->pbi->skip_loop_filter = ctx->skip_loop_filter;
1530 return AOM_CODEC_OK;
1533 static aom_codec_err_t ctrl_set_skip_film_grain(aom_codec_alg_priv_t *ctx,
1534 va_list args) {
1535 ctx->skip_film_grain = va_arg(args, int);
1537 if (ctx->frame_worker) {
1538 AVxWorker *const worker = ctx->frame_worker;
1539 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
1540 frame_worker_data->pbi->skip_film_grain = ctx->skip_film_grain;
1543 return AOM_CODEC_OK;
1546 static aom_codec_err_t ctrl_get_accounting(aom_codec_alg_priv_t *ctx,
1547 va_list args) {
1548 #if !CONFIG_ACCOUNTING
1549 (void)ctx;
1550 (void)args;
1551 return AOM_CODEC_INCAPABLE;
1552 #else
1553 Accounting **acct = va_arg(args, Accounting **);
1555 if (acct) {
1556 if (ctx->frame_worker) {
1557 AVxWorker *const worker = ctx->frame_worker;
1558 FrameWorkerData *const frame_worker_data =
1559 (FrameWorkerData *)worker->data1;
1560 AV1Decoder *pbi = frame_worker_data->pbi;
1561 *acct = &pbi->accounting;
1562 return AOM_CODEC_OK;
1563 } else {
1564 return AOM_CODEC_ERROR;
1568 return AOM_CODEC_INVALID_PARAM;
1569 #endif
1572 static aom_codec_err_t ctrl_set_decode_tile_row(aom_codec_alg_priv_t *ctx,
1573 va_list args) {
1574 ctx->decode_tile_row = va_arg(args, int);
1575 return AOM_CODEC_OK;
1578 static aom_codec_err_t ctrl_set_decode_tile_col(aom_codec_alg_priv_t *ctx,
1579 va_list args) {
1580 ctx->decode_tile_col = va_arg(args, int);
1581 return AOM_CODEC_OK;
1584 static aom_codec_err_t ctrl_set_tile_mode(aom_codec_alg_priv_t *ctx,
1585 va_list args) {
1586 ctx->tile_mode = va_arg(args, unsigned int);
1587 return AOM_CODEC_OK;
1590 static aom_codec_err_t ctrl_set_is_annexb(aom_codec_alg_priv_t *ctx,
1591 va_list args) {
1592 ctx->is_annexb = va_arg(args, unsigned int);
1593 return AOM_CODEC_OK;
1596 static aom_codec_err_t ctrl_set_operating_point(aom_codec_alg_priv_t *ctx,
1597 va_list args) {
1598 ctx->operating_point = va_arg(args, int);
1599 return AOM_CODEC_OK;
1602 static aom_codec_err_t ctrl_set_output_all_layers(aom_codec_alg_priv_t *ctx,
1603 va_list args) {
1604 ctx->output_all_layers = va_arg(args, int);
1605 return AOM_CODEC_OK;
1608 static aom_codec_err_t ctrl_set_inspection_callback(aom_codec_alg_priv_t *ctx,
1609 va_list args) {
1610 #if !CONFIG_INSPECTION
1611 (void)ctx;
1612 (void)args;
1613 return AOM_CODEC_INCAPABLE;
1614 #else
1615 aom_inspect_init *init = va_arg(args, aom_inspect_init *);
1616 ctx->inspect_cb = init->inspect_cb;
1617 ctx->inspect_ctx = init->inspect_ctx;
1618 return AOM_CODEC_OK;
1619 #endif
1622 static aom_codec_err_t ctrl_ext_tile_debug(aom_codec_alg_priv_t *ctx,
1623 va_list args) {
1624 ctx->ext_tile_debug = va_arg(args, int);
1625 return AOM_CODEC_OK;
1628 static aom_codec_err_t ctrl_set_row_mt(aom_codec_alg_priv_t *ctx,
1629 va_list args) {
1630 ctx->row_mt = va_arg(args, unsigned int);
1631 return AOM_CODEC_OK;
1634 static aom_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
1635 { AV1_COPY_REFERENCE, ctrl_copy_reference },
1637 // Setters
1638 { AV1_SET_REFERENCE, ctrl_set_reference },
1639 { AV1_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order },
1640 { AV1_SET_BYTE_ALIGNMENT, ctrl_set_byte_alignment },
1641 { AV1_SET_SKIP_LOOP_FILTER, ctrl_set_skip_loop_filter },
1642 { AV1_SET_DECODE_TILE_ROW, ctrl_set_decode_tile_row },
1643 { AV1_SET_DECODE_TILE_COL, ctrl_set_decode_tile_col },
1644 { AV1_SET_TILE_MODE, ctrl_set_tile_mode },
1645 { AV1D_SET_IS_ANNEXB, ctrl_set_is_annexb },
1646 { AV1D_SET_OPERATING_POINT, ctrl_set_operating_point },
1647 { AV1D_SET_OUTPUT_ALL_LAYERS, ctrl_set_output_all_layers },
1648 { AV1_SET_INSPECTION_CALLBACK, ctrl_set_inspection_callback },
1649 { AV1D_EXT_TILE_DEBUG, ctrl_ext_tile_debug },
1650 { AV1D_SET_ROW_MT, ctrl_set_row_mt },
1651 { AV1D_SET_EXT_REF_PTR, ctrl_set_ext_ref_ptr },
1652 { AV1D_SET_SKIP_FILM_GRAIN, ctrl_set_skip_film_grain },
1654 // Getters
1655 { AOMD_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted },
1656 { AOMD_GET_LAST_QUANTIZER, ctrl_get_last_quantizer },
1657 { AOMD_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates },
1658 { AV1D_GET_BIT_DEPTH, ctrl_get_bit_depth },
1659 { AV1D_GET_IMG_FORMAT, ctrl_get_img_format },
1660 { AV1D_GET_TILE_SIZE, ctrl_get_tile_size },
1661 { AV1D_GET_TILE_COUNT, ctrl_get_tile_count },
1662 { AV1D_GET_DISPLAY_SIZE, ctrl_get_render_size },
1663 { AV1D_GET_FRAME_SIZE, ctrl_get_frame_size },
1664 { AV1_GET_ACCOUNTING, ctrl_get_accounting },
1665 { AV1_GET_NEW_FRAME_IMAGE, ctrl_get_new_frame_image },
1666 { AV1_COPY_NEW_FRAME_IMAGE, ctrl_copy_new_frame_image },
1667 { AV1_GET_REFERENCE, ctrl_get_reference },
1668 { AV1D_GET_FRAME_HEADER_INFO, ctrl_get_frame_header_info },
1669 { AV1D_GET_TILE_DATA, ctrl_get_tile_data },
1670 { AOMD_GET_FWD_KF_PRESENT, ctrl_get_fwd_kf_value },
1671 { AOMD_GET_ALTREF_PRESENT, ctrl_get_altref_present },
1672 { AOMD_GET_FRAME_FLAGS, ctrl_get_frame_flags },
1673 { AOMD_GET_TILE_INFO, ctrl_get_tile_info },
1674 { AOMD_GET_SCREEN_CONTENT_TOOLS_INFO, ctrl_get_screen_content_tools_info },
1675 { AOMD_GET_STILL_PICTURE, ctrl_get_still_picture },
1676 { AOMD_GET_SB_SIZE, ctrl_get_sb_size },
1677 { AOMD_GET_SHOW_EXISTING_FRAME_FLAG, ctrl_get_show_existing_frame_flag },
1678 { AOMD_GET_S_FRAME_INFO, ctrl_get_s_frame_info },
1679 { AOMD_GET_SHOW_FRAME_FLAG, ctrl_get_show_frame_flag },
1680 { AOMD_GET_BASE_Q_IDX, ctrl_get_base_q_idx },
1681 { AOMD_GET_ORDER_HINT, ctrl_get_order_hint },
1682 { AV1D_GET_MI_INFO, ctrl_get_mi_info },
1683 CTRL_MAP_END,
1686 // This data structure and function are exported in aom/aomdx.h
1687 #ifndef VERSION_STRING
1688 #define VERSION_STRING
1689 #endif
1690 aom_codec_iface_t aom_codec_av1_dx_algo = {
1691 "AOMedia Project AV1 Decoder" VERSION_STRING,
1692 AOM_CODEC_INTERNAL_ABI_VERSION,
1693 AOM_CODEC_CAP_DECODER |
1694 AOM_CODEC_CAP_EXTERNAL_FRAME_BUFFER, // aom_codec_caps_t
1695 decoder_init, // aom_codec_init_fn_t
1696 decoder_destroy, // aom_codec_destroy_fn_t
1697 decoder_ctrl_maps, // aom_codec_ctrl_fn_map_t
1699 // NOLINT
1700 decoder_peek_si, // aom_codec_peek_si_fn_t
1701 decoder_get_si, // aom_codec_get_si_fn_t
1702 decoder_decode, // aom_codec_decode_fn_t
1703 decoder_get_frame, // aom_codec_get_frame_fn_t
1704 decoder_set_fb_fn, // aom_codec_set_fb_fn_t
1707 // NOLINT
1709 NULL, // aom_codec_enc_cfg_t
1710 NULL, // aom_codec_encode_fn_t
1711 NULL, // aom_codec_get_cx_data_fn_t
1712 NULL, // aom_codec_enc_config_set_fn_t
1713 NULL, // aom_codec_get_global_headers_fn_t
1714 NULL // aom_codec_get_preview_frame_fn_t
1716 NULL // aom_codec_set_option_fn_t
1719 // Decoder interface for inspecting frame data. It uses decoder_inspect instead
1720 // of decoder_decode so it only decodes one frame at a time, whether the frame
1721 // is shown or not.
1722 aom_codec_iface_t aom_codec_av1_inspect_algo = {
1723 "AOMedia Project AV1 Decoder Inspector" VERSION_STRING,
1724 AOM_CODEC_INTERNAL_ABI_VERSION,
1725 AOM_CODEC_CAP_DECODER |
1726 AOM_CODEC_CAP_EXTERNAL_FRAME_BUFFER, // aom_codec_caps_t
1727 decoder_init, // aom_codec_init_fn_t
1728 decoder_destroy, // aom_codec_destroy_fn_t
1729 decoder_ctrl_maps, // aom_codec_ctrl_fn_map_t
1731 // NOLINT
1732 decoder_peek_si, // aom_codec_peek_si_fn_t
1733 decoder_get_si, // aom_codec_get_si_fn_t
1734 decoder_inspect, // aom_codec_decode_fn_t
1735 decoder_get_frame, // aom_codec_get_frame_fn_t
1736 decoder_set_fb_fn, // aom_codec_set_fb_fn_t
1739 // NOLINT
1741 NULL, // aom_codec_enc_cfg_t
1742 NULL, // aom_codec_encode_fn_t
1743 NULL, // aom_codec_get_cx_data_fn_t
1744 NULL, // aom_codec_enc_config_set_fn_t
1745 NULL, // aom_codec_get_global_headers_fn_t
1746 NULL // aom_codec_get_preview_frame_fn_t
1748 NULL // aom_codec_set_option_fn_t
1751 aom_codec_iface_t *aom_codec_av1_dx(void) { return &aom_codec_av1_dx_algo; }