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