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