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