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