• 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/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 
decoder_init(aom_codec_ctx_t * ctx,aom_codec_priv_enc_mr_cfg_t * data)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 
decoder_destroy(aom_codec_alg_priv_t * ctx)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 
parse_timing_info(struct aom_read_bit_buffer * rb)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 
parse_decoder_model_info(struct aom_read_bit_buffer * rb,int * buffer_delay_length_minus_1)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 
parse_op_parameters_info(struct aom_read_bit_buffer * rb,int buffer_delay_length_minus_1)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].
parse_operating_points(struct aom_read_bit_buffer * rb,int is_reduced_header,aom_codec_stream_info_t * si)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 
decoder_peek_si_internal(const uint8_t * data,size_t data_sz,aom_codec_stream_info_t * si,int * is_intra_only)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 
decoder_peek_si(const uint8_t * data,size_t data_sz,aom_codec_stream_info_t * si)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 
decoder_get_si(aom_codec_alg_priv_t * ctx,aom_codec_stream_info_t * si)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 
set_error_detail(aom_codec_alg_priv_t * ctx,const char * const error)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 
update_error_state(aom_codec_alg_priv_t * ctx,const struct aom_internal_error_info * error)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 
init_buffer_callbacks(aom_codec_alg_priv_t * ctx)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 
set_default_ppflags(aom_postproc_cfg_t * cfg)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 
frame_worker_hook(void * arg1,void * arg2)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 
init_decoder(aom_codec_alg_priv_t * ctx)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 
check_resync(aom_codec_alg_priv_t * const ctx,const AV1Decoder * const pbi)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 
decode_one(aom_codec_alg_priv_t * ctx,const uint8_t ** data,size_t data_sz,void * user_priv)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.
decoder_inspect(aom_codec_alg_priv_t * ctx,const uint8_t * data,size_t data_sz,void * user_priv)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 
decoder_decode(aom_codec_alg_priv_t * ctx,const uint8_t * data,size_t data_sz,void * user_priv)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.
add_grain_if_needed(aom_image_t * img,aom_image_t ** grain_img_ptr,aom_film_grain_t * grain_params)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 
decoder_get_frame(aom_codec_alg_priv_t * ctx,aom_codec_iter_t * iter)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 
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)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 
ctrl_set_reference(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_copy_reference(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_reference(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_new_frame_image(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_copy_new_frame_image(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_postproc(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_dbg_options(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_last_ref_updates(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_last_quantizer(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_frame_corrupted(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_frame_size(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_frame_header_info(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_tile_data(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_ext_ref_ptr(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_render_size(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_bit_depth(aom_codec_alg_priv_t * ctx,va_list args)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 
get_img_format(int subsampling_x,int subsampling_y,int use_highbitdepth)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 
ctrl_get_img_format(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_tile_size(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_tile_count(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_invert_tile_order(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_byte_alignment(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_skip_loop_filter(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_skip_film_grain(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_get_accounting(aom_codec_alg_priv_t * ctx,va_list args)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 }
ctrl_set_decode_tile_row(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_decode_tile_col(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_tile_mode(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_is_annexb(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_operating_point(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_output_all_layers(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_inspection_callback(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_ext_tile_debug(aom_codec_alg_priv_t * ctx,va_list args)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 
ctrl_set_row_mt(aom_codec_alg_priv_t * ctx,va_list args)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