2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
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.
15 #include "./aom_config.h"
16 #include "./aom_version.h"
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"
26 #include "av1/common/alloccommon.h"
27 #include "av1/common/frame_buffers.h"
28 #include "av1/common/enums.h"
30 #include "av1/decoder/decoder.h"
31 #include "av1/decoder/decodeframe.h"
32 #include "av1/decoder/obu.h"
34 #include "av1/av1_iface_common.h"
36 // This limit is due to framebuffer numbers.
37 // TODO(hkuang): Remove this limit after implementing ondemand framebuffers.
38 #define FRAME_CACHE_SIZE 6 // Cache maximum 6 decoded frames.
40 typedef struct cache_frame
{
44 aom_film_grain_t film_grain_params
;
48 struct aom_codec_alg_priv
{
49 aom_codec_priv_t base
;
50 aom_codec_dec_cfg_t cfg
;
51 aom_codec_stream_info_t si
;
53 aom_postproc_cfg_t postproc_cfg
;
57 int invert_tile_order
;
58 int last_show_frame
; // Index of last output frame.
63 unsigned int tile_mode
;
65 AVxWorker
*frame_workers
;
66 int num_frame_workers
;
67 int next_submit_worker_id
;
68 int last_submit_worker_id
;
69 int next_output_worker_id
;
70 int available_threads
;
71 cache_frame frame_cache
[FRAME_CACHE_SIZE
];
73 aom_image_t
*image_with_grain
;
75 int frame_cache_write
;
78 int need_resync
; // wait for key/intra-only frame
79 // BufferPool that holds all reference frames. Shared by all the FrameWorkers.
80 BufferPool
*buffer_pool
;
82 // External frame buffer info to save for AV1 common.
83 void *ext_priv
; // Private data associated with the external frame buffers.
84 aom_get_frame_buffer_cb_fn_t get_ext_fb_cb
;
85 aom_release_frame_buffer_cb_fn_t release_ext_fb_cb
;
88 aom_inspect_cb inspect_cb
;
93 static aom_codec_err_t
decoder_init(aom_codec_ctx_t
*ctx
,
94 aom_codec_priv_enc_mr_cfg_t
*data
) {
95 // This function only allocates space for the aom_codec_alg_priv_t
96 // structure. More memory may be required at the time the stream
97 // information becomes known.
101 aom_codec_alg_priv_t
*const priv
=
102 (aom_codec_alg_priv_t
*)aom_calloc(1, sizeof(*priv
));
103 if (priv
== NULL
) return AOM_CODEC_MEM_ERROR
;
105 ctx
->priv
= (aom_codec_priv_t
*)priv
;
106 ctx
->priv
->init_flags
= ctx
->init_flags
;
109 // TODO(tdaede): this should not be exposed to the API
110 priv
->cfg
.allow_lowbitdepth
= CONFIG_LOWBITDEPTH
;
111 if (ctx
->config
.dec
) {
112 priv
->cfg
= *ctx
->config
.dec
;
113 ctx
->config
.dec
= &priv
->cfg
;
115 priv
->cfg
.cfg
.ext_partition
= 1;
117 #if CONFIG_FILM_GRAIN
118 priv
->image_with_grain
= NULL
;
125 static aom_codec_err_t
decoder_destroy(aom_codec_alg_priv_t
*ctx
) {
126 if (ctx
->frame_workers
!= NULL
) {
128 for (i
= 0; i
< ctx
->num_frame_workers
; ++i
) {
129 AVxWorker
*const worker
= &ctx
->frame_workers
[i
];
130 FrameWorkerData
*const frame_worker_data
=
131 (FrameWorkerData
*)worker
->data1
;
132 aom_get_worker_interface()->end(worker
);
133 aom_free(frame_worker_data
->pbi
->common
.tpl_mvs
);
134 frame_worker_data
->pbi
->common
.tpl_mvs
= NULL
;
135 av1_remove_common(&frame_worker_data
->pbi
->common
);
136 av1_free_restoration_buffers(&frame_worker_data
->pbi
->common
);
137 av1_decoder_remove(frame_worker_data
->pbi
);
138 aom_free(frame_worker_data
->scratch_buffer
);
139 #if CONFIG_MULTITHREAD
140 pthread_mutex_destroy(&frame_worker_data
->stats_mutex
);
141 pthread_cond_destroy(&frame_worker_data
->stats_cond
);
143 aom_free(frame_worker_data
);
145 #if CONFIG_MULTITHREAD
146 pthread_mutex_destroy(&ctx
->buffer_pool
->pool_mutex
);
150 if (ctx
->buffer_pool
) {
151 av1_free_ref_frame_buffers(ctx
->buffer_pool
);
152 av1_free_internal_frame_buffers(&ctx
->buffer_pool
->int_frame_buffers
);
155 aom_free(ctx
->frame_workers
);
156 aom_free(ctx
->buffer_pool
);
157 #if CONFIG_FILM_GRAIN
158 if (ctx
->image_with_grain
) aom_img_free(ctx
->image_with_grain
);
164 static size_t get_obu_length_field_size(const uint8_t *data
, size_t data_sz
) {
165 const size_t max_bytes
= AOMMIN(sizeof(uint64_t), data_sz
);
166 size_t length_field_size
= 1;
167 for (size_t i
= 0; i
< max_bytes
&& (data
[i
] & 0x80); ++i
) {
170 return length_field_size
;
173 static aom_codec_err_t
decoder_peek_si_internal(const uint8_t *data
,
174 unsigned int data_sz
,
175 aom_codec_stream_info_t
*si
,
176 int *is_intra_only
) {
177 int intra_only_flag
= 0;
179 if (data
+ data_sz
<= data
|| data_sz
< 1) return AOM_CODEC_INVALID_PARAM
;
185 // TODO(tomfinegan): This function needs Sequence and Frame Header OBUs to
186 // operate properly. At present it hard codes the values to 1 for the keyframe
187 // and intra only flags, and assumes the data being parsed is a Sequence
192 struct aom_read_bit_buffer rb
= { data
, data
+ data_sz
, 0, NULL
, NULL
};
193 const uint8_t obu_header
= (uint8_t)aom_rb_read_literal(&rb
, 8);
196 if (get_obu_type(obu_header
, &obu_type
) != 0)
197 return AOM_CODEC_UNSUP_BITSTREAM
;
199 // One byte has been consumed by the OBU header.
200 rb
.bit_buffer
+= get_obu_length_field_size(data
+ 1, data_sz
- 1) * 8;
202 // This check is disabled because existing behavior is depended upon by
203 // decoder tests (see decode_test_driver.cc), scalability_decoder (see
204 // scalable_decoder.c), and decode_once() in this file.
205 // if (obu_type != OBU_SEQUENCE_HEADER)
206 // return AOM_CODEC_INVALID_PARAM;
208 av1_read_profile(&rb
); // profile
209 #if !CONFIG_SCALABILITY
210 aom_rb_read_literal(&rb
, 4); // level
213 si
->enhancement_layers_cnt
= aom_rb_read_literal(&rb
, 2);
214 for (i
= 0; i
<= (int)si
->enhancement_layers_cnt
; i
++) {
215 aom_rb_read_literal(&rb
, 4); // level for each enhancement layer
217 #endif // CONFIG_SCALABILITY
219 int num_bits_width
= aom_rb_read_literal(&rb
, 4) + 1;
220 int num_bits_height
= aom_rb_read_literal(&rb
, 4) + 1;
221 int max_frame_width
= aom_rb_read_literal(&rb
, num_bits_width
) + 1;
222 int max_frame_height
= aom_rb_read_literal(&rb
, num_bits_height
) + 1;
223 si
->w
= max_frame_width
;
224 si
->h
= max_frame_height
;
226 if (is_intra_only
!= NULL
) *is_intra_only
= intra_only_flag
;
230 static aom_codec_err_t
decoder_peek_si(const uint8_t *data
,
231 unsigned int data_sz
,
232 aom_codec_stream_info_t
*si
) {
233 return decoder_peek_si_internal(data
, data_sz
, si
, NULL
);
236 static aom_codec_err_t
decoder_get_si(aom_codec_alg_priv_t
*ctx
,
237 aom_codec_stream_info_t
*si
) {
238 memcpy(si
, &ctx
->si
, sizeof(*si
));
243 static void set_error_detail(aom_codec_alg_priv_t
*ctx
,
244 const char *const error
) {
245 ctx
->base
.err_detail
= error
;
248 static aom_codec_err_t
update_error_state(
249 aom_codec_alg_priv_t
*ctx
, const struct aom_internal_error_info
*error
) {
250 if (error
->error_code
)
251 set_error_detail(ctx
, error
->has_detail
? error
->detail
: NULL
);
253 return error
->error_code
;
256 static void init_buffer_callbacks(aom_codec_alg_priv_t
*ctx
) {
259 for (i
= 0; i
< ctx
->num_frame_workers
; ++i
) {
260 AVxWorker
*const worker
= &ctx
->frame_workers
[i
];
261 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
262 AV1_COMMON
*const cm
= &frame_worker_data
->pbi
->common
;
263 BufferPool
*const pool
= cm
->buffer_pool
;
265 cm
->new_fb_idx
= INVALID_IDX
;
266 cm
->byte_alignment
= ctx
->byte_alignment
;
267 cm
->skip_loop_filter
= ctx
->skip_loop_filter
;
269 if (ctx
->get_ext_fb_cb
!= NULL
&& ctx
->release_ext_fb_cb
!= NULL
) {
270 pool
->get_fb_cb
= ctx
->get_ext_fb_cb
;
271 pool
->release_fb_cb
= ctx
->release_ext_fb_cb
;
272 pool
->cb_priv
= ctx
->ext_priv
;
274 pool
->get_fb_cb
= av1_get_frame_buffer
;
275 pool
->release_fb_cb
= av1_release_frame_buffer
;
277 if (av1_alloc_internal_frame_buffers(&pool
->int_frame_buffers
))
278 aom_internal_error(&cm
->error
, AOM_CODEC_MEM_ERROR
,
279 "Failed to initialize internal frame buffers");
281 pool
->cb_priv
= &pool
->int_frame_buffers
;
286 static void set_default_ppflags(aom_postproc_cfg_t
*cfg
) {
287 cfg
->post_proc_flag
= AOM_DEBLOCK
| AOM_DEMACROBLOCK
;
288 cfg
->deblocking_level
= 4;
289 cfg
->noise_level
= 0;
292 static int frame_worker_hook(void *arg1
, void *arg2
) {
293 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)arg1
;
294 const uint8_t *data
= frame_worker_data
->data
;
297 frame_worker_data
->result
= av1_receive_compressed_data(
298 frame_worker_data
->pbi
, frame_worker_data
->data_size
, &data
);
299 frame_worker_data
->data_end
= data
;
301 if (frame_worker_data
->result
!= 0) {
302 // Check decode result in serial decode.
303 frame_worker_data
->pbi
->cur_buf
->buf
.corrupted
= 1;
304 frame_worker_data
->pbi
->need_resync
= 1;
306 return !frame_worker_data
->result
;
309 static aom_codec_err_t
init_decoder(aom_codec_alg_priv_t
*ctx
) {
311 const AVxWorkerInterface
*const winterface
= aom_get_worker_interface();
313 ctx
->last_show_frame
= -1;
314 ctx
->next_submit_worker_id
= 0;
315 ctx
->last_submit_worker_id
= 0;
316 ctx
->next_output_worker_id
= 0;
317 ctx
->frame_cache_read
= 0;
318 ctx
->frame_cache_write
= 0;
319 ctx
->num_cache_frames
= 0;
320 ctx
->need_resync
= 1;
321 ctx
->num_frame_workers
= 1;
322 if (ctx
->num_frame_workers
> MAX_DECODE_THREADS
)
323 ctx
->num_frame_workers
= MAX_DECODE_THREADS
;
324 ctx
->available_threads
= ctx
->num_frame_workers
;
327 ctx
->buffer_pool
= (BufferPool
*)aom_calloc(1, sizeof(BufferPool
));
328 if (ctx
->buffer_pool
== NULL
) return AOM_CODEC_MEM_ERROR
;
330 #if CONFIG_MULTITHREAD
331 if (pthread_mutex_init(&ctx
->buffer_pool
->pool_mutex
, NULL
)) {
332 set_error_detail(ctx
, "Failed to allocate buffer pool mutex");
333 return AOM_CODEC_MEM_ERROR
;
337 ctx
->frame_workers
= (AVxWorker
*)aom_malloc(ctx
->num_frame_workers
*
338 sizeof(*ctx
->frame_workers
));
339 if (ctx
->frame_workers
== NULL
) {
340 set_error_detail(ctx
, "Failed to allocate frame_workers");
341 return AOM_CODEC_MEM_ERROR
;
344 for (i
= 0; i
< ctx
->num_frame_workers
; ++i
) {
345 AVxWorker
*const worker
= &ctx
->frame_workers
[i
];
346 FrameWorkerData
*frame_worker_data
= NULL
;
347 winterface
->init(worker
);
348 worker
->data1
= aom_memalign(32, sizeof(FrameWorkerData
));
349 if (worker
->data1
== NULL
) {
350 set_error_detail(ctx
, "Failed to allocate frame_worker_data");
351 return AOM_CODEC_MEM_ERROR
;
353 frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
354 frame_worker_data
->pbi
= av1_decoder_create(ctx
->buffer_pool
);
355 if (frame_worker_data
->pbi
== NULL
) {
356 set_error_detail(ctx
, "Failed to allocate frame_worker_data");
357 return AOM_CODEC_MEM_ERROR
;
359 frame_worker_data
->pbi
->common
.options
= &ctx
->cfg
.cfg
;
360 frame_worker_data
->pbi
->frame_worker_owner
= worker
;
361 frame_worker_data
->worker_id
= i
;
362 frame_worker_data
->scratch_buffer
= NULL
;
363 frame_worker_data
->scratch_buffer_size
= 0;
364 frame_worker_data
->frame_context_ready
= 0;
365 frame_worker_data
->received_frame
= 0;
366 #if CONFIG_MULTITHREAD
367 if (pthread_mutex_init(&frame_worker_data
->stats_mutex
, NULL
)) {
368 set_error_detail(ctx
, "Failed to allocate frame_worker_data mutex");
369 return AOM_CODEC_MEM_ERROR
;
372 if (pthread_cond_init(&frame_worker_data
->stats_cond
, NULL
)) {
373 set_error_detail(ctx
, "Failed to allocate frame_worker_data cond");
374 return AOM_CODEC_MEM_ERROR
;
377 frame_worker_data
->pbi
->allow_lowbitdepth
= ctx
->cfg
.allow_lowbitdepth
;
379 // If decoding in serial mode, FrameWorker thread could create tile worker
380 // thread or loopfilter thread.
381 frame_worker_data
->pbi
->max_threads
= ctx
->cfg
.threads
;
382 frame_worker_data
->pbi
->inv_tile_order
= ctx
->invert_tile_order
;
383 frame_worker_data
->pbi
->common
.large_scale_tile
= ctx
->tile_mode
;
384 frame_worker_data
->pbi
->dec_tile_row
= ctx
->decode_tile_row
;
385 frame_worker_data
->pbi
->dec_tile_col
= ctx
->decode_tile_col
;
386 worker
->hook
= (AVxWorkerHook
)frame_worker_hook
;
387 if (!winterface
->reset(worker
)) {
388 set_error_detail(ctx
, "Frame Worker thread creation failed");
389 return AOM_CODEC_MEM_ERROR
;
393 // If postprocessing was enabled by the application and a
394 // configuration has not been provided, default it.
395 if (!ctx
->postproc_cfg_set
&& (ctx
->base
.init_flags
& AOM_CODEC_USE_POSTPROC
))
396 set_default_ppflags(&ctx
->postproc_cfg
);
398 init_buffer_callbacks(ctx
);
403 static INLINE
void check_resync(aom_codec_alg_priv_t
*const ctx
,
404 const AV1Decoder
*const pbi
) {
405 // Clear resync flag if worker got a key frame or intra only frame.
406 if (ctx
->need_resync
== 1 && pbi
->need_resync
== 0 &&
407 (pbi
->common
.intra_only
|| pbi
->common
.frame_type
== KEY_FRAME
))
408 ctx
->need_resync
= 0;
411 static aom_codec_err_t
decode_one(aom_codec_alg_priv_t
*ctx
,
412 const uint8_t **data
, unsigned int data_sz
,
414 const AVxWorkerInterface
*const winterface
= aom_get_worker_interface();
416 // Determine the stream parameters. Note that we rely on peek_si to
417 // validate that we have a buffer that does not wrap around the top
420 int is_intra_only
= 0;
421 const aom_codec_err_t res
=
422 decoder_peek_si_internal(*data
, data_sz
, &ctx
->si
, &is_intra_only
);
423 if (res
!= AOM_CODEC_OK
) return res
;
425 if (!ctx
->si
.is_kf
&& !is_intra_only
) return AOM_CODEC_ERROR
;
428 AVxWorker
*const worker
= ctx
->frame_workers
;
429 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
430 frame_worker_data
->data
= *data
;
431 frame_worker_data
->data_size
= data_sz
;
432 frame_worker_data
->user_priv
= user_priv
;
433 frame_worker_data
->received_frame
= 1;
435 #if CONFIG_INSPECTION
436 frame_worker_data
->pbi
->inspect_cb
= ctx
->inspect_cb
;
437 frame_worker_data
->pbi
->inspect_ctx
= ctx
->inspect_ctx
;
440 frame_worker_data
->pbi
->common
.large_scale_tile
= ctx
->tile_mode
;
441 frame_worker_data
->pbi
->dec_tile_row
= ctx
->decode_tile_row
;
442 frame_worker_data
->pbi
->dec_tile_col
= ctx
->decode_tile_col
;
444 worker
->had_error
= 0;
445 winterface
->execute(worker
);
447 // Update data pointer after decode.
448 *data
= frame_worker_data
->data_end
;
450 if (worker
->had_error
)
451 return update_error_state(ctx
, &frame_worker_data
->pbi
->common
.error
);
453 check_resync(ctx
, frame_worker_data
->pbi
);
458 static void wait_worker_and_cache_frame(aom_codec_alg_priv_t
*ctx
) {
459 YV12_BUFFER_CONFIG sd
;
460 const AVxWorkerInterface
*const winterface
= aom_get_worker_interface();
461 AVxWorker
*const worker
= &ctx
->frame_workers
[ctx
->next_output_worker_id
];
462 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
463 ctx
->next_output_worker_id
=
464 (ctx
->next_output_worker_id
+ 1) % ctx
->num_frame_workers
;
465 // TODO(hkuang): Add worker error handling here.
466 winterface
->sync(worker
);
467 frame_worker_data
->received_frame
= 0;
468 ++ctx
->available_threads
;
470 check_resync(ctx
, frame_worker_data
->pbi
);
472 if (av1_get_raw_frame(frame_worker_data
->pbi
, &sd
) == 0) {
473 AV1_COMMON
*const cm
= &frame_worker_data
->pbi
->common
;
474 RefCntBuffer
*const frame_bufs
= cm
->buffer_pool
->frame_bufs
;
475 ctx
->frame_cache
[ctx
->frame_cache_write
].fb_idx
= cm
->new_fb_idx
;
476 yuvconfig2image(&ctx
->frame_cache
[ctx
->frame_cache_write
].img
, &sd
,
477 frame_worker_data
->user_priv
);
478 ctx
->frame_cache
[ctx
->frame_cache_write
].img
.fb_priv
=
479 frame_bufs
[cm
->new_fb_idx
].raw_frame_buffer
.priv
;
480 #if CONFIG_FILM_GRAIN
481 memcpy(&ctx
->frame_cache
[ctx
->frame_cache_write
].film_grain_params
,
482 &cm
->film_grain_params
, sizeof(aom_film_grain_t
));
484 ctx
->frame_cache_write
= (ctx
->frame_cache_write
+ 1) % FRAME_CACHE_SIZE
;
485 ++ctx
->num_cache_frames
;
489 static aom_codec_err_t
decoder_decode(aom_codec_alg_priv_t
*ctx
,
490 const uint8_t *data
, unsigned int data_sz
,
492 const uint8_t *data_start
= data
;
493 const uint8_t *const data_end
= data
+ data_sz
;
494 aom_codec_err_t res
= AOM_CODEC_OK
;
495 uint32_t frame_sizes
[8];
498 if (data
== NULL
&& data_sz
== 0) {
503 // Reset flushed when receiving a valid frame.
506 // Initialize the decoder workers on the first frame.
507 if (ctx
->frame_workers
== NULL
) {
508 res
= init_decoder(ctx
);
509 if (res
!= AOM_CODEC_OK
) return res
;
511 // Decode in serial mode.
512 if (frame_count
> 0) {
515 for (i
= 0; i
< frame_count
; ++i
) {
516 const uint8_t *data_start_copy
= data_start
;
517 const uint32_t frame_size
= frame_sizes
[i
];
518 if (data_start
< data
|| frame_size
> (uint32_t)(data_end
- data_start
)) {
519 set_error_detail(ctx
, "Invalid frame size in index");
520 return AOM_CODEC_CORRUPT_FRAME
;
523 res
= decode_one(ctx
, &data_start_copy
, frame_size
, user_priv
);
524 if (res
!= AOM_CODEC_OK
) return res
;
526 data_start
+= frame_size
;
529 while (data_start
< data_end
) {
530 const uint32_t frame_size
= (uint32_t)(data_end
- data_start
);
531 res
= decode_one(ctx
, &data_start
, frame_size
, user_priv
);
532 if (res
!= AOM_CODEC_OK
) return res
;
534 // Account for suboptimal termination by the encoder.
535 while (data_start
< data_end
) {
536 const uint8_t marker
= data_start
[0];
546 #if CONFIG_FILM_GRAIN
547 aom_image_t
*add_grain_if_needed(aom_image_t
*img
, aom_image_t
*grain_img_buf
,
548 aom_film_grain_t
*grain_params
) {
549 if (!grain_params
->apply_grain
) return img
;
552 (img
->d_w
!= grain_img_buf
->d_w
|| img
->d_h
!= grain_img_buf
->d_h
||
553 img
->fmt
!= grain_img_buf
->fmt
)) {
554 aom_img_free(grain_img_buf
);
555 grain_img_buf
= NULL
;
557 if (!grain_img_buf
) {
558 grain_img_buf
= aom_img_alloc(NULL
, img
->fmt
, img
->d_w
, img
->d_h
, 16);
559 grain_img_buf
->bit_depth
= img
->bit_depth
;
562 av1_add_film_grain(grain_params
, img
, grain_img_buf
);
564 return grain_img_buf
;
568 static aom_image_t
*decoder_get_frame(aom_codec_alg_priv_t
*ctx
,
569 aom_codec_iter_t
*iter
) {
570 aom_image_t
*img
= NULL
;
572 // Output the frames in the cache first.
573 if (ctx
->num_cache_frames
> 0) {
574 ctx
->last_show_frame
= ctx
->frame_cache
[ctx
->frame_cache_read
].fb_idx
;
575 if (ctx
->need_resync
) return NULL
;
576 img
= &ctx
->frame_cache
[ctx
->frame_cache_read
].img
;
577 ctx
->frame_cache_read
= (ctx
->frame_cache_read
+ 1) % FRAME_CACHE_SIZE
;
578 --ctx
->num_cache_frames
;
579 #if CONFIG_FILM_GRAIN
580 return add_grain_if_needed(
581 img
, ctx
->image_with_grain
,
582 &ctx
->frame_cache
[ctx
->frame_cache_read
].film_grain_params
);
588 // iter acts as a flip flop, so an image is only returned on the first
589 // call to get_frame.
590 if (*iter
== NULL
&& ctx
->frame_workers
!= NULL
) {
592 YV12_BUFFER_CONFIG sd
;
593 const AVxWorkerInterface
*const winterface
= aom_get_worker_interface();
594 AVxWorker
*const worker
= &ctx
->frame_workers
[ctx
->next_output_worker_id
];
595 FrameWorkerData
*const frame_worker_data
=
596 (FrameWorkerData
*)worker
->data1
;
597 ctx
->next_output_worker_id
=
598 (ctx
->next_output_worker_id
+ 1) % ctx
->num_frame_workers
;
599 // Wait for the frame from worker thread.
600 if (winterface
->sync(worker
)) {
601 // Check if worker has received any frames.
602 if (frame_worker_data
->received_frame
== 1) {
603 ++ctx
->available_threads
;
604 frame_worker_data
->received_frame
= 0;
605 check_resync(ctx
, frame_worker_data
->pbi
);
607 if (av1_get_raw_frame(frame_worker_data
->pbi
, &sd
) == 0) {
608 AV1_COMMON
*const cm
= &frame_worker_data
->pbi
->common
;
609 RefCntBuffer
*const frame_bufs
= cm
->buffer_pool
->frame_bufs
;
610 ctx
->last_show_frame
= frame_worker_data
->pbi
->common
.new_fb_idx
;
611 if (ctx
->need_resync
) return NULL
;
612 yuvconfig2image(&ctx
->img
, &sd
, frame_worker_data
->user_priv
);
614 const int num_planes
= av1_num_planes(cm
);
615 if (cm
->single_tile_decoding
&&
616 frame_worker_data
->pbi
->dec_tile_row
>= 0) {
618 AOMMIN(frame_worker_data
->pbi
->dec_tile_row
, cm
->tile_rows
- 1);
619 const int mi_row
= tile_row
* cm
->tile_height
;
620 const int ssy
= ctx
->img
.y_chroma_shift
;
622 ctx
->img
.planes
[0] += mi_row
* MI_SIZE
* ctx
->img
.stride
[0];
623 if (num_planes
> 1) {
624 for (plane
= 1; plane
< MAX_MB_PLANE
; ++plane
) {
625 ctx
->img
.planes
[plane
] +=
626 mi_row
* (MI_SIZE
>> ssy
) * ctx
->img
.stride
[plane
];
630 AOMMIN(cm
->tile_height
, cm
->mi_rows
- mi_row
) * MI_SIZE
;
633 if (cm
->single_tile_decoding
&&
634 frame_worker_data
->pbi
->dec_tile_col
>= 0) {
636 AOMMIN(frame_worker_data
->pbi
->dec_tile_col
, cm
->tile_cols
- 1);
637 const int mi_col
= tile_col
* cm
->tile_width
;
638 const int ssx
= ctx
->img
.x_chroma_shift
;
640 ctx
->img
.planes
[0] += mi_col
* MI_SIZE
;
641 if (num_planes
> 1) {
642 for (plane
= 1; plane
< MAX_MB_PLANE
; ++plane
) {
643 ctx
->img
.planes
[plane
] += mi_col
* (MI_SIZE
>> ssx
);
647 AOMMIN(cm
->tile_width
, cm
->mi_cols
- mi_col
) * MI_SIZE
;
650 ctx
->img
.fb_priv
= frame_bufs
[cm
->new_fb_idx
].raw_frame_buffer
.priv
;
652 #if CONFIG_SCALABILITY
653 img
->temporal_id
= cm
->temporal_layer_id
;
654 img
->enhancement_id
= cm
->enhancement_layer_id
;
656 #if CONFIG_FILM_GRAIN
657 return add_grain_if_needed(
658 img
, ctx
->image_with_grain
,
659 &frame_worker_data
->pbi
->common
.film_grain_params
);
665 // Decoding failed. Release the worker thread.
666 frame_worker_data
->received_frame
= 0;
667 ++ctx
->available_threads
;
668 ctx
->need_resync
= 1;
669 if (ctx
->flushed
!= 1) return NULL
;
671 } while (ctx
->next_output_worker_id
!= ctx
->next_submit_worker_id
);
676 static aom_codec_err_t
decoder_set_fb_fn(
677 aom_codec_alg_priv_t
*ctx
, aom_get_frame_buffer_cb_fn_t cb_get
,
678 aom_release_frame_buffer_cb_fn_t cb_release
, void *cb_priv
) {
679 if (cb_get
== NULL
|| cb_release
== NULL
) {
680 return AOM_CODEC_INVALID_PARAM
;
681 } else if (ctx
->frame_workers
== NULL
) {
682 // If the decoder has already been initialized, do not accept changes to
683 // the frame buffer functions.
684 ctx
->get_ext_fb_cb
= cb_get
;
685 ctx
->release_ext_fb_cb
= cb_release
;
686 ctx
->ext_priv
= cb_priv
;
690 return AOM_CODEC_ERROR
;
693 static aom_codec_err_t
ctrl_set_reference(aom_codec_alg_priv_t
*ctx
,
695 av1_ref_frame_t
*const data
= va_arg(args
, av1_ref_frame_t
*);
698 av1_ref_frame_t
*const frame
= data
;
699 YV12_BUFFER_CONFIG sd
;
700 AVxWorker
*const worker
= ctx
->frame_workers
;
701 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
702 image2yuvconfig(&frame
->img
, &sd
);
703 return av1_set_reference_dec(&frame_worker_data
->pbi
->common
, frame
->idx
,
706 return AOM_CODEC_INVALID_PARAM
;
710 static aom_codec_err_t
ctrl_copy_reference(aom_codec_alg_priv_t
*ctx
,
712 const av1_ref_frame_t
*const frame
= va_arg(args
, av1_ref_frame_t
*);
714 YV12_BUFFER_CONFIG sd
;
715 AVxWorker
*const worker
= ctx
->frame_workers
;
716 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
717 image2yuvconfig(&frame
->img
, &sd
);
718 return av1_copy_reference_dec(frame_worker_data
->pbi
, frame
->idx
, &sd
);
720 return AOM_CODEC_INVALID_PARAM
;
724 static aom_codec_err_t
ctrl_get_reference(aom_codec_alg_priv_t
*ctx
,
726 av1_ref_frame_t
*data
= va_arg(args
, av1_ref_frame_t
*);
728 YV12_BUFFER_CONFIG
*fb
;
729 AVxWorker
*const worker
= ctx
->frame_workers
;
730 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
731 fb
= get_ref_frame(&frame_worker_data
->pbi
->common
, data
->idx
);
732 if (fb
== NULL
) return AOM_CODEC_ERROR
;
733 yuvconfig2image(&data
->img
, fb
, NULL
);
736 return AOM_CODEC_INVALID_PARAM
;
740 static aom_codec_err_t
ctrl_get_new_frame_image(aom_codec_alg_priv_t
*ctx
,
742 aom_image_t
*new_img
= va_arg(args
, aom_image_t
*);
744 YV12_BUFFER_CONFIG new_frame
;
745 AVxWorker
*const worker
= ctx
->frame_workers
;
746 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
748 if (av1_get_frame_to_show(frame_worker_data
->pbi
, &new_frame
) == 0) {
749 yuvconfig2image(new_img
, &new_frame
, NULL
);
752 return AOM_CODEC_ERROR
;
755 return AOM_CODEC_INVALID_PARAM
;
759 static aom_codec_err_t
ctrl_set_postproc(aom_codec_alg_priv_t
*ctx
,
763 return AOM_CODEC_INCAPABLE
;
766 static aom_codec_err_t
ctrl_set_dbg_options(aom_codec_alg_priv_t
*ctx
,
770 return AOM_CODEC_INCAPABLE
;
773 static aom_codec_err_t
ctrl_get_last_ref_updates(aom_codec_alg_priv_t
*ctx
,
775 int *const update_info
= va_arg(args
, int *);
778 if (ctx
->frame_workers
) {
779 AVxWorker
*const worker
= ctx
->frame_workers
;
780 FrameWorkerData
*const frame_worker_data
=
781 (FrameWorkerData
*)worker
->data1
;
782 *update_info
= frame_worker_data
->pbi
->refresh_frame_flags
;
785 return AOM_CODEC_ERROR
;
789 return AOM_CODEC_INVALID_PARAM
;
792 static aom_codec_err_t
ctrl_get_last_quantizer(aom_codec_alg_priv_t
*ctx
,
794 int *const arg
= va_arg(args
, int *);
795 if (arg
== NULL
) return AOM_CODEC_INVALID_PARAM
;
797 ((FrameWorkerData
*)ctx
->frame_workers
[0].data1
)->pbi
->common
.base_qindex
;
801 static aom_codec_err_t
ctrl_get_frame_corrupted(aom_codec_alg_priv_t
*ctx
,
803 int *corrupted
= va_arg(args
, int *);
806 if (ctx
->frame_workers
) {
807 AVxWorker
*const worker
= ctx
->frame_workers
;
808 FrameWorkerData
*const frame_worker_data
=
809 (FrameWorkerData
*)worker
->data1
;
810 RefCntBuffer
*const frame_bufs
=
811 frame_worker_data
->pbi
->common
.buffer_pool
->frame_bufs
;
812 if (frame_worker_data
->pbi
->common
.frame_to_show
== NULL
)
813 return AOM_CODEC_ERROR
;
814 if (ctx
->last_show_frame
>= 0)
815 *corrupted
= frame_bufs
[ctx
->last_show_frame
].buf
.corrupted
;
818 return AOM_CODEC_ERROR
;
822 return AOM_CODEC_INVALID_PARAM
;
825 static aom_codec_err_t
ctrl_get_frame_size(aom_codec_alg_priv_t
*ctx
,
827 int *const frame_size
= va_arg(args
, int *);
830 if (ctx
->frame_workers
) {
831 AVxWorker
*const worker
= ctx
->frame_workers
;
832 FrameWorkerData
*const frame_worker_data
=
833 (FrameWorkerData
*)worker
->data1
;
834 const AV1_COMMON
*const cm
= &frame_worker_data
->pbi
->common
;
835 frame_size
[0] = cm
->width
;
836 frame_size
[1] = cm
->height
;
839 return AOM_CODEC_ERROR
;
843 return AOM_CODEC_INVALID_PARAM
;
846 static aom_codec_err_t
ctrl_get_render_size(aom_codec_alg_priv_t
*ctx
,
848 int *const render_size
= va_arg(args
, int *);
851 if (ctx
->frame_workers
) {
852 AVxWorker
*const worker
= ctx
->frame_workers
;
853 FrameWorkerData
*const frame_worker_data
=
854 (FrameWorkerData
*)worker
->data1
;
855 const AV1_COMMON
*const cm
= &frame_worker_data
->pbi
->common
;
856 render_size
[0] = cm
->render_width
;
857 render_size
[1] = cm
->render_height
;
860 return AOM_CODEC_ERROR
;
864 return AOM_CODEC_INVALID_PARAM
;
867 static aom_codec_err_t
ctrl_get_bit_depth(aom_codec_alg_priv_t
*ctx
,
869 unsigned int *const bit_depth
= va_arg(args
, unsigned int *);
870 AVxWorker
*const worker
= &ctx
->frame_workers
[ctx
->next_output_worker_id
];
874 FrameWorkerData
*const frame_worker_data
=
875 (FrameWorkerData
*)worker
->data1
;
876 const AV1_COMMON
*const cm
= &frame_worker_data
->pbi
->common
;
877 *bit_depth
= cm
->bit_depth
;
880 return AOM_CODEC_ERROR
;
884 return AOM_CODEC_INVALID_PARAM
;
887 static aom_codec_err_t
ctrl_set_invert_tile_order(aom_codec_alg_priv_t
*ctx
,
889 ctx
->invert_tile_order
= va_arg(args
, int);
893 static aom_codec_err_t
ctrl_set_byte_alignment(aom_codec_alg_priv_t
*ctx
,
895 const int legacy_byte_alignment
= 0;
896 const int min_byte_alignment
= 32;
897 const int max_byte_alignment
= 1024;
898 const int byte_alignment
= va_arg(args
, int);
900 if (byte_alignment
!= legacy_byte_alignment
&&
901 (byte_alignment
< min_byte_alignment
||
902 byte_alignment
> max_byte_alignment
||
903 (byte_alignment
& (byte_alignment
- 1)) != 0))
904 return AOM_CODEC_INVALID_PARAM
;
906 ctx
->byte_alignment
= byte_alignment
;
907 if (ctx
->frame_workers
) {
908 AVxWorker
*const worker
= ctx
->frame_workers
;
909 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
910 frame_worker_data
->pbi
->common
.byte_alignment
= byte_alignment
;
915 static aom_codec_err_t
ctrl_set_skip_loop_filter(aom_codec_alg_priv_t
*ctx
,
917 ctx
->skip_loop_filter
= va_arg(args
, int);
919 if (ctx
->frame_workers
) {
920 AVxWorker
*const worker
= ctx
->frame_workers
;
921 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
922 frame_worker_data
->pbi
->common
.skip_loop_filter
= ctx
->skip_loop_filter
;
928 static aom_codec_err_t
ctrl_get_accounting(aom_codec_alg_priv_t
*ctx
,
930 #if !CONFIG_ACCOUNTING
933 return AOM_CODEC_INCAPABLE
;
935 if (ctx
->frame_workers
) {
936 AVxWorker
*const worker
= ctx
->frame_workers
;
937 FrameWorkerData
*const frame_worker_data
= (FrameWorkerData
*)worker
->data1
;
938 AV1Decoder
*pbi
= frame_worker_data
->pbi
;
939 Accounting
**acct
= va_arg(args
, Accounting
**);
940 *acct
= &pbi
->accounting
;
943 return AOM_CODEC_ERROR
;
946 static aom_codec_err_t
ctrl_set_decode_tile_row(aom_codec_alg_priv_t
*ctx
,
948 ctx
->decode_tile_row
= va_arg(args
, int);
952 static aom_codec_err_t
ctrl_set_decode_tile_col(aom_codec_alg_priv_t
*ctx
,
954 ctx
->decode_tile_col
= va_arg(args
, int);
958 static aom_codec_err_t
ctrl_set_tile_mode(aom_codec_alg_priv_t
*ctx
,
960 ctx
->tile_mode
= va_arg(args
, unsigned int);
964 static aom_codec_err_t
ctrl_set_inspection_callback(aom_codec_alg_priv_t
*ctx
,
966 #if !CONFIG_INSPECTION
969 return AOM_CODEC_INCAPABLE
;
971 aom_inspect_init
*init
= va_arg(args
, aom_inspect_init
*);
972 ctx
->inspect_cb
= init
->inspect_cb
;
973 ctx
->inspect_ctx
= init
->inspect_ctx
;
978 static aom_codec_ctrl_fn_map_t decoder_ctrl_maps
[] = {
979 { AV1_COPY_REFERENCE
, ctrl_copy_reference
},
982 { AV1_SET_REFERENCE
, ctrl_set_reference
},
983 { AOM_SET_POSTPROC
, ctrl_set_postproc
},
984 { AOM_SET_DBG_COLOR_REF_FRAME
, ctrl_set_dbg_options
},
985 { AOM_SET_DBG_COLOR_MB_MODES
, ctrl_set_dbg_options
},
986 { AOM_SET_DBG_COLOR_B_MODES
, ctrl_set_dbg_options
},
987 { AOM_SET_DBG_DISPLAY_MV
, ctrl_set_dbg_options
},
988 { AV1_INVERT_TILE_DECODE_ORDER
, ctrl_set_invert_tile_order
},
989 { AV1_SET_BYTE_ALIGNMENT
, ctrl_set_byte_alignment
},
990 { AV1_SET_SKIP_LOOP_FILTER
, ctrl_set_skip_loop_filter
},
991 { AV1_SET_DECODE_TILE_ROW
, ctrl_set_decode_tile_row
},
992 { AV1_SET_DECODE_TILE_COL
, ctrl_set_decode_tile_col
},
993 { AV1_SET_TILE_MODE
, ctrl_set_tile_mode
},
994 { AV1_SET_INSPECTION_CALLBACK
, ctrl_set_inspection_callback
},
997 { AOMD_GET_FRAME_CORRUPTED
, ctrl_get_frame_corrupted
},
998 { AOMD_GET_LAST_QUANTIZER
, ctrl_get_last_quantizer
},
999 { AOMD_GET_LAST_REF_UPDATES
, ctrl_get_last_ref_updates
},
1000 { AV1D_GET_BIT_DEPTH
, ctrl_get_bit_depth
},
1001 { AV1D_GET_DISPLAY_SIZE
, ctrl_get_render_size
},
1002 { AV1D_GET_FRAME_SIZE
, ctrl_get_frame_size
},
1003 { AV1_GET_ACCOUNTING
, ctrl_get_accounting
},
1004 { AV1_GET_NEW_FRAME_IMAGE
, ctrl_get_new_frame_image
},
1005 { AV1_GET_REFERENCE
, ctrl_get_reference
},
1010 #ifndef VERSION_STRING
1011 #define VERSION_STRING
1013 CODEC_INTERFACE(aom_codec_av1_dx
) = {
1014 "AOMedia Project AV1 Decoder" VERSION_STRING
,
1015 AOM_CODEC_INTERNAL_ABI_VERSION
,
1016 AOM_CODEC_CAP_DECODER
|
1017 AOM_CODEC_CAP_EXTERNAL_FRAME_BUFFER
, // aom_codec_caps_t
1018 decoder_init
, // aom_codec_init_fn_t
1019 decoder_destroy
, // aom_codec_destroy_fn_t
1020 decoder_ctrl_maps
, // aom_codec_ctrl_fn_map_t
1023 decoder_peek_si
, // aom_codec_peek_si_fn_t
1024 decoder_get_si
, // aom_codec_get_si_fn_t
1025 decoder_decode
, // aom_codec_decode_fn_t
1026 decoder_get_frame
, // aom_codec_frame_get_fn_t
1027 decoder_set_fb_fn
, // aom_codec_set_fb_fn_t
1032 NULL
, // aom_codec_enc_cfg_map_t
1033 NULL
, // aom_codec_encode_fn_t
1034 NULL
, // aom_codec_get_cx_data_fn_t
1035 NULL
, // aom_codec_enc_config_set_fn_t
1036 NULL
, // aom_codec_get_global_headers_fn_t
1037 NULL
, // aom_codec_get_preview_frame_fn_t
1038 NULL
// aom_codec_enc_mr_get_mem_loc_fn_t