Home | History | Annotate | Download | only in av1
      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