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