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, ¶m)) {
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