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