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