1*c0909341SAndroid Build Coastguard Worker /*
2*c0909341SAndroid Build Coastguard Worker * Copyright © 2018, VideoLAN and dav1d authors
3*c0909341SAndroid Build Coastguard Worker * Copyright © 2018, Two Orioles, LLC
4*c0909341SAndroid Build Coastguard Worker * All rights reserved.
5*c0909341SAndroid Build Coastguard Worker *
6*c0909341SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
7*c0909341SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met:
8*c0909341SAndroid Build Coastguard Worker *
9*c0909341SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright notice, this
10*c0909341SAndroid Build Coastguard Worker * list of conditions and the following disclaimer.
11*c0909341SAndroid Build Coastguard Worker *
12*c0909341SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright notice,
13*c0909341SAndroid Build Coastguard Worker * this list of conditions and the following disclaimer in the documentation
14*c0909341SAndroid Build Coastguard Worker * and/or other materials provided with the distribution.
15*c0909341SAndroid Build Coastguard Worker *
16*c0909341SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*c0909341SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*c0909341SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*c0909341SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20*c0909341SAndroid Build Coastguard Worker * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*c0909341SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*c0909341SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*c0909341SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c0909341SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*c0909341SAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c0909341SAndroid Build Coastguard Worker */
27*c0909341SAndroid Build Coastguard Worker
28*c0909341SAndroid Build Coastguard Worker #include "config.h"
29*c0909341SAndroid Build Coastguard Worker #include "vcs_version.h"
30*c0909341SAndroid Build Coastguard Worker
31*c0909341SAndroid Build Coastguard Worker #include <errno.h>
32*c0909341SAndroid Build Coastguard Worker #include <string.h>
33*c0909341SAndroid Build Coastguard Worker
34*c0909341SAndroid Build Coastguard Worker #if defined(__linux__) && HAVE_DLSYM
35*c0909341SAndroid Build Coastguard Worker #include <dlfcn.h>
36*c0909341SAndroid Build Coastguard Worker #endif
37*c0909341SAndroid Build Coastguard Worker
38*c0909341SAndroid Build Coastguard Worker #include "dav1d/dav1d.h"
39*c0909341SAndroid Build Coastguard Worker #include "dav1d/data.h"
40*c0909341SAndroid Build Coastguard Worker
41*c0909341SAndroid Build Coastguard Worker #include "common/validate.h"
42*c0909341SAndroid Build Coastguard Worker
43*c0909341SAndroid Build Coastguard Worker #include "src/cpu.h"
44*c0909341SAndroid Build Coastguard Worker #include "src/fg_apply.h"
45*c0909341SAndroid Build Coastguard Worker #include "src/internal.h"
46*c0909341SAndroid Build Coastguard Worker #include "src/log.h"
47*c0909341SAndroid Build Coastguard Worker #include "src/obu.h"
48*c0909341SAndroid Build Coastguard Worker #include "src/qm.h"
49*c0909341SAndroid Build Coastguard Worker #include "src/ref.h"
50*c0909341SAndroid Build Coastguard Worker #include "src/thread_task.h"
51*c0909341SAndroid Build Coastguard Worker #include "src/wedge.h"
52*c0909341SAndroid Build Coastguard Worker
init_internal(void)53*c0909341SAndroid Build Coastguard Worker static COLD void init_internal(void) {
54*c0909341SAndroid Build Coastguard Worker dav1d_init_cpu();
55*c0909341SAndroid Build Coastguard Worker dav1d_init_ii_wedge_masks();
56*c0909341SAndroid Build Coastguard Worker dav1d_init_intra_edge_tree();
57*c0909341SAndroid Build Coastguard Worker dav1d_init_qm_tables();
58*c0909341SAndroid Build Coastguard Worker dav1d_init_thread();
59*c0909341SAndroid Build Coastguard Worker }
60*c0909341SAndroid Build Coastguard Worker
dav1d_version(void)61*c0909341SAndroid Build Coastguard Worker COLD const char *dav1d_version(void) {
62*c0909341SAndroid Build Coastguard Worker return DAV1D_VERSION;
63*c0909341SAndroid Build Coastguard Worker }
64*c0909341SAndroid Build Coastguard Worker
dav1d_version_api(void)65*c0909341SAndroid Build Coastguard Worker COLD unsigned dav1d_version_api(void) {
66*c0909341SAndroid Build Coastguard Worker return (DAV1D_API_VERSION_MAJOR << 16) |
67*c0909341SAndroid Build Coastguard Worker (DAV1D_API_VERSION_MINOR << 8) |
68*c0909341SAndroid Build Coastguard Worker (DAV1D_API_VERSION_PATCH << 0);
69*c0909341SAndroid Build Coastguard Worker }
70*c0909341SAndroid Build Coastguard Worker
dav1d_default_settings(Dav1dSettings * const s)71*c0909341SAndroid Build Coastguard Worker COLD void dav1d_default_settings(Dav1dSettings *const s) {
72*c0909341SAndroid Build Coastguard Worker s->n_threads = 0;
73*c0909341SAndroid Build Coastguard Worker s->max_frame_delay = 0;
74*c0909341SAndroid Build Coastguard Worker s->apply_grain = 1;
75*c0909341SAndroid Build Coastguard Worker s->allocator.cookie = NULL;
76*c0909341SAndroid Build Coastguard Worker s->allocator.alloc_picture_callback = dav1d_default_picture_alloc;
77*c0909341SAndroid Build Coastguard Worker s->allocator.release_picture_callback = dav1d_default_picture_release;
78*c0909341SAndroid Build Coastguard Worker s->logger.cookie = NULL;
79*c0909341SAndroid Build Coastguard Worker s->logger.callback = dav1d_log_default_callback;
80*c0909341SAndroid Build Coastguard Worker s->operating_point = 0;
81*c0909341SAndroid Build Coastguard Worker s->all_layers = 1; // just until the tests are adjusted
82*c0909341SAndroid Build Coastguard Worker s->frame_size_limit = 0;
83*c0909341SAndroid Build Coastguard Worker s->strict_std_compliance = 0;
84*c0909341SAndroid Build Coastguard Worker s->output_invisible_frames = 0;
85*c0909341SAndroid Build Coastguard Worker s->inloop_filters = DAV1D_INLOOPFILTER_ALL;
86*c0909341SAndroid Build Coastguard Worker s->decode_frame_type = DAV1D_DECODEFRAMETYPE_ALL;
87*c0909341SAndroid Build Coastguard Worker }
88*c0909341SAndroid Build Coastguard Worker
89*c0909341SAndroid Build Coastguard Worker static void close_internal(Dav1dContext **const c_out, int flush);
90*c0909341SAndroid Build Coastguard Worker
91*c0909341SAndroid Build Coastguard Worker NO_SANITIZE("cfi-icall") // CFI is broken with dlsym()
get_stack_size_internal(const pthread_attr_t * const thread_attr)92*c0909341SAndroid Build Coastguard Worker static COLD size_t get_stack_size_internal(const pthread_attr_t *const thread_attr) {
93*c0909341SAndroid Build Coastguard Worker #if defined(__linux__) && HAVE_DLSYM && defined(__GLIBC__)
94*c0909341SAndroid Build Coastguard Worker /* glibc has an issue where the size of the TLS is subtracted from the stack
95*c0909341SAndroid Build Coastguard Worker * size instead of allocated separately. As a result the specified stack
96*c0909341SAndroid Build Coastguard Worker * size may be insufficient when used in an application with large amounts
97*c0909341SAndroid Build Coastguard Worker * of TLS data. The following is a workaround to compensate for that.
98*c0909341SAndroid Build Coastguard Worker * See https://sourceware.org/bugzilla/show_bug.cgi?id=11787 */
99*c0909341SAndroid Build Coastguard Worker size_t (*const get_minstack)(const pthread_attr_t*) =
100*c0909341SAndroid Build Coastguard Worker dlsym(RTLD_DEFAULT, "__pthread_get_minstack");
101*c0909341SAndroid Build Coastguard Worker if (get_minstack)
102*c0909341SAndroid Build Coastguard Worker return get_minstack(thread_attr) - PTHREAD_STACK_MIN;
103*c0909341SAndroid Build Coastguard Worker #endif
104*c0909341SAndroid Build Coastguard Worker return 0;
105*c0909341SAndroid Build Coastguard Worker }
106*c0909341SAndroid Build Coastguard Worker
get_num_threads(Dav1dContext * const c,const Dav1dSettings * const s,unsigned * n_tc,unsigned * n_fc)107*c0909341SAndroid Build Coastguard Worker static COLD void get_num_threads(Dav1dContext *const c, const Dav1dSettings *const s,
108*c0909341SAndroid Build Coastguard Worker unsigned *n_tc, unsigned *n_fc)
109*c0909341SAndroid Build Coastguard Worker {
110*c0909341SAndroid Build Coastguard Worker /* ceil(sqrt(n)) */
111*c0909341SAndroid Build Coastguard Worker static const uint8_t fc_lut[49] = {
112*c0909341SAndroid Build Coastguard Worker 1, /* 1 */
113*c0909341SAndroid Build Coastguard Worker 2, 2, 2, /* 2- 4 */
114*c0909341SAndroid Build Coastguard Worker 3, 3, 3, 3, 3, /* 5- 9 */
115*c0909341SAndroid Build Coastguard Worker 4, 4, 4, 4, 4, 4, 4, /* 10-16 */
116*c0909341SAndroid Build Coastguard Worker 5, 5, 5, 5, 5, 5, 5, 5, 5, /* 17-25 */
117*c0909341SAndroid Build Coastguard Worker 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, /* 26-36 */
118*c0909341SAndroid Build Coastguard Worker 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* 37-49 */
119*c0909341SAndroid Build Coastguard Worker };
120*c0909341SAndroid Build Coastguard Worker *n_tc = s->n_threads ? s->n_threads :
121*c0909341SAndroid Build Coastguard Worker iclip(dav1d_num_logical_processors(c), 1, DAV1D_MAX_THREADS);
122*c0909341SAndroid Build Coastguard Worker *n_fc = s->max_frame_delay ? umin(s->max_frame_delay, *n_tc) :
123*c0909341SAndroid Build Coastguard Worker *n_tc < 50 ? fc_lut[*n_tc - 1] : 8; // min(8, ceil(sqrt(n)))
124*c0909341SAndroid Build Coastguard Worker }
125*c0909341SAndroid Build Coastguard Worker
dav1d_get_frame_delay(const Dav1dSettings * const s)126*c0909341SAndroid Build Coastguard Worker COLD int dav1d_get_frame_delay(const Dav1dSettings *const s) {
127*c0909341SAndroid Build Coastguard Worker unsigned n_tc, n_fc;
128*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s != NULL, DAV1D_ERR(EINVAL));
129*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->n_threads >= 0 &&
130*c0909341SAndroid Build Coastguard Worker s->n_threads <= DAV1D_MAX_THREADS, DAV1D_ERR(EINVAL));
131*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->max_frame_delay >= 0 &&
132*c0909341SAndroid Build Coastguard Worker s->max_frame_delay <= DAV1D_MAX_FRAME_DELAY, DAV1D_ERR(EINVAL));
133*c0909341SAndroid Build Coastguard Worker
134*c0909341SAndroid Build Coastguard Worker get_num_threads(NULL, s, &n_tc, &n_fc);
135*c0909341SAndroid Build Coastguard Worker return n_fc;
136*c0909341SAndroid Build Coastguard Worker }
137*c0909341SAndroid Build Coastguard Worker
dav1d_open(Dav1dContext ** const c_out,const Dav1dSettings * const s)138*c0909341SAndroid Build Coastguard Worker COLD int dav1d_open(Dav1dContext **const c_out, const Dav1dSettings *const s) {
139*c0909341SAndroid Build Coastguard Worker static pthread_once_t initted = PTHREAD_ONCE_INIT;
140*c0909341SAndroid Build Coastguard Worker pthread_once(&initted, init_internal);
141*c0909341SAndroid Build Coastguard Worker
142*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(c_out != NULL, DAV1D_ERR(EINVAL));
143*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s != NULL, DAV1D_ERR(EINVAL));
144*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->n_threads >= 0 &&
145*c0909341SAndroid Build Coastguard Worker s->n_threads <= DAV1D_MAX_THREADS, DAV1D_ERR(EINVAL));
146*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->max_frame_delay >= 0 &&
147*c0909341SAndroid Build Coastguard Worker s->max_frame_delay <= DAV1D_MAX_FRAME_DELAY, DAV1D_ERR(EINVAL));
148*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->allocator.alloc_picture_callback != NULL,
149*c0909341SAndroid Build Coastguard Worker DAV1D_ERR(EINVAL));
150*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->allocator.release_picture_callback != NULL,
151*c0909341SAndroid Build Coastguard Worker DAV1D_ERR(EINVAL));
152*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->operating_point >= 0 &&
153*c0909341SAndroid Build Coastguard Worker s->operating_point <= 31, DAV1D_ERR(EINVAL));
154*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(s->decode_frame_type >= DAV1D_DECODEFRAMETYPE_ALL &&
155*c0909341SAndroid Build Coastguard Worker s->decode_frame_type <= DAV1D_DECODEFRAMETYPE_KEY, DAV1D_ERR(EINVAL));
156*c0909341SAndroid Build Coastguard Worker
157*c0909341SAndroid Build Coastguard Worker pthread_attr_t thread_attr;
158*c0909341SAndroid Build Coastguard Worker if (pthread_attr_init(&thread_attr)) return DAV1D_ERR(ENOMEM);
159*c0909341SAndroid Build Coastguard Worker size_t stack_size = 1024 * 1024 + get_stack_size_internal(&thread_attr);
160*c0909341SAndroid Build Coastguard Worker
161*c0909341SAndroid Build Coastguard Worker pthread_attr_setstacksize(&thread_attr, stack_size);
162*c0909341SAndroid Build Coastguard Worker
163*c0909341SAndroid Build Coastguard Worker Dav1dContext *const c = *c_out = dav1d_alloc_aligned(ALLOC_COMMON_CTX, sizeof(*c), 64);
164*c0909341SAndroid Build Coastguard Worker if (!c) goto error;
165*c0909341SAndroid Build Coastguard Worker memset(c, 0, sizeof(*c));
166*c0909341SAndroid Build Coastguard Worker
167*c0909341SAndroid Build Coastguard Worker c->allocator = s->allocator;
168*c0909341SAndroid Build Coastguard Worker c->logger = s->logger;
169*c0909341SAndroid Build Coastguard Worker c->apply_grain = s->apply_grain;
170*c0909341SAndroid Build Coastguard Worker c->operating_point = s->operating_point;
171*c0909341SAndroid Build Coastguard Worker c->all_layers = s->all_layers;
172*c0909341SAndroid Build Coastguard Worker c->frame_size_limit = s->frame_size_limit;
173*c0909341SAndroid Build Coastguard Worker c->strict_std_compliance = s->strict_std_compliance;
174*c0909341SAndroid Build Coastguard Worker c->output_invisible_frames = s->output_invisible_frames;
175*c0909341SAndroid Build Coastguard Worker c->inloop_filters = s->inloop_filters;
176*c0909341SAndroid Build Coastguard Worker c->decode_frame_type = s->decode_frame_type;
177*c0909341SAndroid Build Coastguard Worker
178*c0909341SAndroid Build Coastguard Worker dav1d_data_props_set_defaults(&c->cached_error_props);
179*c0909341SAndroid Build Coastguard Worker
180*c0909341SAndroid Build Coastguard Worker if (dav1d_mem_pool_init(ALLOC_OBU_HDR, &c->seq_hdr_pool) ||
181*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_init(ALLOC_OBU_HDR, &c->frame_hdr_pool) ||
182*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_init(ALLOC_SEGMAP, &c->segmap_pool) ||
183*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_init(ALLOC_REFMVS, &c->refmvs_pool) ||
184*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_init(ALLOC_PIC_CTX, &c->pic_ctx_pool) ||
185*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_init(ALLOC_CDF, &c->cdf_pool))
186*c0909341SAndroid Build Coastguard Worker {
187*c0909341SAndroid Build Coastguard Worker goto error;
188*c0909341SAndroid Build Coastguard Worker }
189*c0909341SAndroid Build Coastguard Worker
190*c0909341SAndroid Build Coastguard Worker if (c->allocator.alloc_picture_callback == dav1d_default_picture_alloc &&
191*c0909341SAndroid Build Coastguard Worker c->allocator.release_picture_callback == dav1d_default_picture_release)
192*c0909341SAndroid Build Coastguard Worker {
193*c0909341SAndroid Build Coastguard Worker if (c->allocator.cookie) goto error;
194*c0909341SAndroid Build Coastguard Worker if (dav1d_mem_pool_init(ALLOC_PIC, &c->picture_pool)) goto error;
195*c0909341SAndroid Build Coastguard Worker c->allocator.cookie = c->picture_pool;
196*c0909341SAndroid Build Coastguard Worker } else if (c->allocator.alloc_picture_callback == dav1d_default_picture_alloc ||
197*c0909341SAndroid Build Coastguard Worker c->allocator.release_picture_callback == dav1d_default_picture_release)
198*c0909341SAndroid Build Coastguard Worker {
199*c0909341SAndroid Build Coastguard Worker goto error;
200*c0909341SAndroid Build Coastguard Worker }
201*c0909341SAndroid Build Coastguard Worker
202*c0909341SAndroid Build Coastguard Worker /* On 32-bit systems extremely large frame sizes can cause overflows in
203*c0909341SAndroid Build Coastguard Worker * dav1d_decode_frame() malloc size calculations. Prevent that from occuring
204*c0909341SAndroid Build Coastguard Worker * by enforcing a maximum frame size limit, chosen to roughly correspond to
205*c0909341SAndroid Build Coastguard Worker * the largest size possible to decode without exhausting virtual memory. */
206*c0909341SAndroid Build Coastguard Worker if (sizeof(size_t) < 8 && s->frame_size_limit - 1 >= 8192 * 8192) {
207*c0909341SAndroid Build Coastguard Worker c->frame_size_limit = 8192 * 8192;
208*c0909341SAndroid Build Coastguard Worker if (s->frame_size_limit)
209*c0909341SAndroid Build Coastguard Worker dav1d_log(c, "Frame size limit reduced from %u to %u.\n",
210*c0909341SAndroid Build Coastguard Worker s->frame_size_limit, c->frame_size_limit);
211*c0909341SAndroid Build Coastguard Worker }
212*c0909341SAndroid Build Coastguard Worker
213*c0909341SAndroid Build Coastguard Worker c->flush = &c->flush_mem;
214*c0909341SAndroid Build Coastguard Worker atomic_init(c->flush, 0);
215*c0909341SAndroid Build Coastguard Worker
216*c0909341SAndroid Build Coastguard Worker get_num_threads(c, s, &c->n_tc, &c->n_fc);
217*c0909341SAndroid Build Coastguard Worker
218*c0909341SAndroid Build Coastguard Worker c->fc = dav1d_alloc_aligned(ALLOC_THREAD_CTX, sizeof(*c->fc) * c->n_fc, 32);
219*c0909341SAndroid Build Coastguard Worker if (!c->fc) goto error;
220*c0909341SAndroid Build Coastguard Worker memset(c->fc, 0, sizeof(*c->fc) * c->n_fc);
221*c0909341SAndroid Build Coastguard Worker
222*c0909341SAndroid Build Coastguard Worker c->tc = dav1d_alloc_aligned(ALLOC_THREAD_CTX, sizeof(*c->tc) * c->n_tc, 64);
223*c0909341SAndroid Build Coastguard Worker if (!c->tc) goto error;
224*c0909341SAndroid Build Coastguard Worker memset(c->tc, 0, sizeof(*c->tc) * c->n_tc);
225*c0909341SAndroid Build Coastguard Worker if (c->n_tc > 1) {
226*c0909341SAndroid Build Coastguard Worker if (pthread_mutex_init(&c->task_thread.lock, NULL)) goto error;
227*c0909341SAndroid Build Coastguard Worker if (pthread_cond_init(&c->task_thread.cond, NULL)) {
228*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&c->task_thread.lock);
229*c0909341SAndroid Build Coastguard Worker goto error;
230*c0909341SAndroid Build Coastguard Worker }
231*c0909341SAndroid Build Coastguard Worker if (pthread_cond_init(&c->task_thread.delayed_fg.cond, NULL)) {
232*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&c->task_thread.cond);
233*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&c->task_thread.lock);
234*c0909341SAndroid Build Coastguard Worker goto error;
235*c0909341SAndroid Build Coastguard Worker }
236*c0909341SAndroid Build Coastguard Worker c->task_thread.cur = c->n_fc;
237*c0909341SAndroid Build Coastguard Worker atomic_init(&c->task_thread.reset_task_cur, UINT_MAX);
238*c0909341SAndroid Build Coastguard Worker atomic_init(&c->task_thread.cond_signaled, 0);
239*c0909341SAndroid Build Coastguard Worker c->task_thread.inited = 1;
240*c0909341SAndroid Build Coastguard Worker }
241*c0909341SAndroid Build Coastguard Worker
242*c0909341SAndroid Build Coastguard Worker if (c->n_fc > 1) {
243*c0909341SAndroid Build Coastguard Worker const size_t out_delayed_sz = sizeof(*c->frame_thread.out_delayed) * c->n_fc;
244*c0909341SAndroid Build Coastguard Worker c->frame_thread.out_delayed =
245*c0909341SAndroid Build Coastguard Worker dav1d_malloc(ALLOC_THREAD_CTX, out_delayed_sz);
246*c0909341SAndroid Build Coastguard Worker if (!c->frame_thread.out_delayed) goto error;
247*c0909341SAndroid Build Coastguard Worker memset(c->frame_thread.out_delayed, 0, out_delayed_sz);
248*c0909341SAndroid Build Coastguard Worker }
249*c0909341SAndroid Build Coastguard Worker for (unsigned n = 0; n < c->n_fc; n++) {
250*c0909341SAndroid Build Coastguard Worker Dav1dFrameContext *const f = &c->fc[n];
251*c0909341SAndroid Build Coastguard Worker if (c->n_tc > 1) {
252*c0909341SAndroid Build Coastguard Worker if (pthread_mutex_init(&f->task_thread.lock, NULL)) goto error;
253*c0909341SAndroid Build Coastguard Worker if (pthread_cond_init(&f->task_thread.cond, NULL)) {
254*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&f->task_thread.lock);
255*c0909341SAndroid Build Coastguard Worker goto error;
256*c0909341SAndroid Build Coastguard Worker }
257*c0909341SAndroid Build Coastguard Worker if (pthread_mutex_init(&f->task_thread.pending_tasks.lock, NULL)) {
258*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&f->task_thread.cond);
259*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&f->task_thread.lock);
260*c0909341SAndroid Build Coastguard Worker goto error;
261*c0909341SAndroid Build Coastguard Worker }
262*c0909341SAndroid Build Coastguard Worker }
263*c0909341SAndroid Build Coastguard Worker f->c = c;
264*c0909341SAndroid Build Coastguard Worker f->task_thread.ttd = &c->task_thread;
265*c0909341SAndroid Build Coastguard Worker f->lf.last_sharpness = -1;
266*c0909341SAndroid Build Coastguard Worker }
267*c0909341SAndroid Build Coastguard Worker
268*c0909341SAndroid Build Coastguard Worker for (unsigned m = 0; m < c->n_tc; m++) {
269*c0909341SAndroid Build Coastguard Worker Dav1dTaskContext *const t = &c->tc[m];
270*c0909341SAndroid Build Coastguard Worker t->f = &c->fc[0];
271*c0909341SAndroid Build Coastguard Worker t->task_thread.ttd = &c->task_thread;
272*c0909341SAndroid Build Coastguard Worker t->c = c;
273*c0909341SAndroid Build Coastguard Worker memset(t->cf_16bpc, 0, sizeof(t->cf_16bpc));
274*c0909341SAndroid Build Coastguard Worker if (c->n_tc > 1) {
275*c0909341SAndroid Build Coastguard Worker if (pthread_mutex_init(&t->task_thread.td.lock, NULL)) goto error;
276*c0909341SAndroid Build Coastguard Worker if (pthread_cond_init(&t->task_thread.td.cond, NULL)) {
277*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&t->task_thread.td.lock);
278*c0909341SAndroid Build Coastguard Worker goto error;
279*c0909341SAndroid Build Coastguard Worker }
280*c0909341SAndroid Build Coastguard Worker if (pthread_create(&t->task_thread.td.thread, &thread_attr, dav1d_worker_task, t)) {
281*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&t->task_thread.td.cond);
282*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&t->task_thread.td.lock);
283*c0909341SAndroid Build Coastguard Worker goto error;
284*c0909341SAndroid Build Coastguard Worker }
285*c0909341SAndroid Build Coastguard Worker t->task_thread.td.inited = 1;
286*c0909341SAndroid Build Coastguard Worker }
287*c0909341SAndroid Build Coastguard Worker }
288*c0909341SAndroid Build Coastguard Worker dav1d_pal_dsp_init(&c->pal_dsp);
289*c0909341SAndroid Build Coastguard Worker dav1d_refmvs_dsp_init(&c->refmvs_dsp);
290*c0909341SAndroid Build Coastguard Worker
291*c0909341SAndroid Build Coastguard Worker pthread_attr_destroy(&thread_attr);
292*c0909341SAndroid Build Coastguard Worker
293*c0909341SAndroid Build Coastguard Worker return 0;
294*c0909341SAndroid Build Coastguard Worker
295*c0909341SAndroid Build Coastguard Worker error:
296*c0909341SAndroid Build Coastguard Worker if (c) close_internal(c_out, 0);
297*c0909341SAndroid Build Coastguard Worker pthread_attr_destroy(&thread_attr);
298*c0909341SAndroid Build Coastguard Worker return DAV1D_ERR(ENOMEM);
299*c0909341SAndroid Build Coastguard Worker }
300*c0909341SAndroid Build Coastguard Worker
has_grain(const Dav1dPicture * const pic)301*c0909341SAndroid Build Coastguard Worker static int has_grain(const Dav1dPicture *const pic)
302*c0909341SAndroid Build Coastguard Worker {
303*c0909341SAndroid Build Coastguard Worker const Dav1dFilmGrainData *fgdata = &pic->frame_hdr->film_grain.data;
304*c0909341SAndroid Build Coastguard Worker return fgdata->num_y_points || fgdata->num_uv_points[0] ||
305*c0909341SAndroid Build Coastguard Worker fgdata->num_uv_points[1] || (fgdata->clip_to_restricted_range &&
306*c0909341SAndroid Build Coastguard Worker fgdata->chroma_scaling_from_luma);
307*c0909341SAndroid Build Coastguard Worker }
308*c0909341SAndroid Build Coastguard Worker
output_image(Dav1dContext * const c,Dav1dPicture * const out)309*c0909341SAndroid Build Coastguard Worker static int output_image(Dav1dContext *const c, Dav1dPicture *const out)
310*c0909341SAndroid Build Coastguard Worker {
311*c0909341SAndroid Build Coastguard Worker int res = 0;
312*c0909341SAndroid Build Coastguard Worker
313*c0909341SAndroid Build Coastguard Worker Dav1dThreadPicture *const in = (c->all_layers || !c->max_spatial_id)
314*c0909341SAndroid Build Coastguard Worker ? &c->out : &c->cache;
315*c0909341SAndroid Build Coastguard Worker if (!c->apply_grain || !has_grain(&in->p)) {
316*c0909341SAndroid Build Coastguard Worker dav1d_picture_move_ref(out, &in->p);
317*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(in);
318*c0909341SAndroid Build Coastguard Worker goto end;
319*c0909341SAndroid Build Coastguard Worker }
320*c0909341SAndroid Build Coastguard Worker
321*c0909341SAndroid Build Coastguard Worker res = dav1d_apply_grain(c, out, &in->p);
322*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(in);
323*c0909341SAndroid Build Coastguard Worker end:
324*c0909341SAndroid Build Coastguard Worker if (!c->all_layers && c->max_spatial_id && c->out.p.data[0]) {
325*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_move_ref(in, &c->out);
326*c0909341SAndroid Build Coastguard Worker }
327*c0909341SAndroid Build Coastguard Worker return res;
328*c0909341SAndroid Build Coastguard Worker }
329*c0909341SAndroid Build Coastguard Worker
output_picture_ready(Dav1dContext * const c,const int drain)330*c0909341SAndroid Build Coastguard Worker static int output_picture_ready(Dav1dContext *const c, const int drain) {
331*c0909341SAndroid Build Coastguard Worker if (c->cached_error) return 1;
332*c0909341SAndroid Build Coastguard Worker if (!c->all_layers && c->max_spatial_id) {
333*c0909341SAndroid Build Coastguard Worker if (c->out.p.data[0] && c->cache.p.data[0]) {
334*c0909341SAndroid Build Coastguard Worker if (c->max_spatial_id == c->cache.p.frame_hdr->spatial_id ||
335*c0909341SAndroid Build Coastguard Worker c->out.flags & PICTURE_FLAG_NEW_TEMPORAL_UNIT)
336*c0909341SAndroid Build Coastguard Worker return 1;
337*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(&c->cache);
338*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_move_ref(&c->cache, &c->out);
339*c0909341SAndroid Build Coastguard Worker return 0;
340*c0909341SAndroid Build Coastguard Worker } else if (c->cache.p.data[0] && drain) {
341*c0909341SAndroid Build Coastguard Worker return 1;
342*c0909341SAndroid Build Coastguard Worker } else if (c->out.p.data[0]) {
343*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_move_ref(&c->cache, &c->out);
344*c0909341SAndroid Build Coastguard Worker return 0;
345*c0909341SAndroid Build Coastguard Worker }
346*c0909341SAndroid Build Coastguard Worker }
347*c0909341SAndroid Build Coastguard Worker
348*c0909341SAndroid Build Coastguard Worker return !!c->out.p.data[0];
349*c0909341SAndroid Build Coastguard Worker }
350*c0909341SAndroid Build Coastguard Worker
drain_picture(Dav1dContext * const c,Dav1dPicture * const out)351*c0909341SAndroid Build Coastguard Worker static int drain_picture(Dav1dContext *const c, Dav1dPicture *const out) {
352*c0909341SAndroid Build Coastguard Worker unsigned drain_count = 0;
353*c0909341SAndroid Build Coastguard Worker int drained = 0;
354*c0909341SAndroid Build Coastguard Worker do {
355*c0909341SAndroid Build Coastguard Worker const unsigned next = c->frame_thread.next;
356*c0909341SAndroid Build Coastguard Worker Dav1dFrameContext *const f = &c->fc[next];
357*c0909341SAndroid Build Coastguard Worker pthread_mutex_lock(&c->task_thread.lock);
358*c0909341SAndroid Build Coastguard Worker while (f->n_tile_data > 0)
359*c0909341SAndroid Build Coastguard Worker pthread_cond_wait(&f->task_thread.cond,
360*c0909341SAndroid Build Coastguard Worker &f->task_thread.ttd->lock);
361*c0909341SAndroid Build Coastguard Worker Dav1dThreadPicture *const out_delayed =
362*c0909341SAndroid Build Coastguard Worker &c->frame_thread.out_delayed[next];
363*c0909341SAndroid Build Coastguard Worker if (out_delayed->p.data[0] || atomic_load(&f->task_thread.error)) {
364*c0909341SAndroid Build Coastguard Worker unsigned first = atomic_load(&c->task_thread.first);
365*c0909341SAndroid Build Coastguard Worker if (first + 1U < c->n_fc)
366*c0909341SAndroid Build Coastguard Worker atomic_fetch_add(&c->task_thread.first, 1U);
367*c0909341SAndroid Build Coastguard Worker else
368*c0909341SAndroid Build Coastguard Worker atomic_store(&c->task_thread.first, 0);
369*c0909341SAndroid Build Coastguard Worker atomic_compare_exchange_strong(&c->task_thread.reset_task_cur,
370*c0909341SAndroid Build Coastguard Worker &first, UINT_MAX);
371*c0909341SAndroid Build Coastguard Worker if (c->task_thread.cur && c->task_thread.cur < c->n_fc)
372*c0909341SAndroid Build Coastguard Worker c->task_thread.cur--;
373*c0909341SAndroid Build Coastguard Worker drained = 1;
374*c0909341SAndroid Build Coastguard Worker } else if (drained) {
375*c0909341SAndroid Build Coastguard Worker pthread_mutex_unlock(&c->task_thread.lock);
376*c0909341SAndroid Build Coastguard Worker break;
377*c0909341SAndroid Build Coastguard Worker }
378*c0909341SAndroid Build Coastguard Worker if (++c->frame_thread.next == c->n_fc)
379*c0909341SAndroid Build Coastguard Worker c->frame_thread.next = 0;
380*c0909341SAndroid Build Coastguard Worker pthread_mutex_unlock(&c->task_thread.lock);
381*c0909341SAndroid Build Coastguard Worker const int error = f->task_thread.retval;
382*c0909341SAndroid Build Coastguard Worker if (error) {
383*c0909341SAndroid Build Coastguard Worker f->task_thread.retval = 0;
384*c0909341SAndroid Build Coastguard Worker dav1d_data_props_copy(&c->cached_error_props, &out_delayed->p.m);
385*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(out_delayed);
386*c0909341SAndroid Build Coastguard Worker return error;
387*c0909341SAndroid Build Coastguard Worker }
388*c0909341SAndroid Build Coastguard Worker if (out_delayed->p.data[0]) {
389*c0909341SAndroid Build Coastguard Worker const unsigned progress =
390*c0909341SAndroid Build Coastguard Worker atomic_load_explicit(&out_delayed->progress[1],
391*c0909341SAndroid Build Coastguard Worker memory_order_relaxed);
392*c0909341SAndroid Build Coastguard Worker if ((out_delayed->visible || c->output_invisible_frames) &&
393*c0909341SAndroid Build Coastguard Worker progress != FRAME_ERROR)
394*c0909341SAndroid Build Coastguard Worker {
395*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_ref(&c->out, out_delayed);
396*c0909341SAndroid Build Coastguard Worker c->event_flags |= dav1d_picture_get_event_flags(out_delayed);
397*c0909341SAndroid Build Coastguard Worker }
398*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(out_delayed);
399*c0909341SAndroid Build Coastguard Worker if (output_picture_ready(c, 0))
400*c0909341SAndroid Build Coastguard Worker return output_image(c, out);
401*c0909341SAndroid Build Coastguard Worker }
402*c0909341SAndroid Build Coastguard Worker } while (++drain_count < c->n_fc);
403*c0909341SAndroid Build Coastguard Worker
404*c0909341SAndroid Build Coastguard Worker if (output_picture_ready(c, 1))
405*c0909341SAndroid Build Coastguard Worker return output_image(c, out);
406*c0909341SAndroid Build Coastguard Worker
407*c0909341SAndroid Build Coastguard Worker return DAV1D_ERR(EAGAIN);
408*c0909341SAndroid Build Coastguard Worker }
409*c0909341SAndroid Build Coastguard Worker
gen_picture(Dav1dContext * const c)410*c0909341SAndroid Build Coastguard Worker static int gen_picture(Dav1dContext *const c)
411*c0909341SAndroid Build Coastguard Worker {
412*c0909341SAndroid Build Coastguard Worker Dav1dData *const in = &c->in;
413*c0909341SAndroid Build Coastguard Worker
414*c0909341SAndroid Build Coastguard Worker if (output_picture_ready(c, 0))
415*c0909341SAndroid Build Coastguard Worker return 0;
416*c0909341SAndroid Build Coastguard Worker
417*c0909341SAndroid Build Coastguard Worker while (in->sz > 0) {
418*c0909341SAndroid Build Coastguard Worker const ptrdiff_t res = dav1d_parse_obus(c, in);
419*c0909341SAndroid Build Coastguard Worker if (res < 0) {
420*c0909341SAndroid Build Coastguard Worker dav1d_data_unref_internal(in);
421*c0909341SAndroid Build Coastguard Worker } else {
422*c0909341SAndroid Build Coastguard Worker assert((size_t)res <= in->sz);
423*c0909341SAndroid Build Coastguard Worker in->sz -= res;
424*c0909341SAndroid Build Coastguard Worker in->data += res;
425*c0909341SAndroid Build Coastguard Worker if (!in->sz) dav1d_data_unref_internal(in);
426*c0909341SAndroid Build Coastguard Worker }
427*c0909341SAndroid Build Coastguard Worker if (output_picture_ready(c, 0))
428*c0909341SAndroid Build Coastguard Worker break;
429*c0909341SAndroid Build Coastguard Worker if (res < 0)
430*c0909341SAndroid Build Coastguard Worker return (int)res;
431*c0909341SAndroid Build Coastguard Worker }
432*c0909341SAndroid Build Coastguard Worker
433*c0909341SAndroid Build Coastguard Worker return 0;
434*c0909341SAndroid Build Coastguard Worker }
435*c0909341SAndroid Build Coastguard Worker
dav1d_send_data(Dav1dContext * const c,Dav1dData * const in)436*c0909341SAndroid Build Coastguard Worker int dav1d_send_data(Dav1dContext *const c, Dav1dData *const in)
437*c0909341SAndroid Build Coastguard Worker {
438*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(c != NULL, DAV1D_ERR(EINVAL));
439*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(in != NULL, DAV1D_ERR(EINVAL));
440*c0909341SAndroid Build Coastguard Worker
441*c0909341SAndroid Build Coastguard Worker if (in->data) {
442*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(in->sz > 0 && in->sz <= SIZE_MAX / 2, DAV1D_ERR(EINVAL));
443*c0909341SAndroid Build Coastguard Worker c->drain = 0;
444*c0909341SAndroid Build Coastguard Worker }
445*c0909341SAndroid Build Coastguard Worker if (c->in.data)
446*c0909341SAndroid Build Coastguard Worker return DAV1D_ERR(EAGAIN);
447*c0909341SAndroid Build Coastguard Worker dav1d_data_ref(&c->in, in);
448*c0909341SAndroid Build Coastguard Worker
449*c0909341SAndroid Build Coastguard Worker int res = gen_picture(c);
450*c0909341SAndroid Build Coastguard Worker if (!res)
451*c0909341SAndroid Build Coastguard Worker dav1d_data_unref_internal(in);
452*c0909341SAndroid Build Coastguard Worker
453*c0909341SAndroid Build Coastguard Worker return res;
454*c0909341SAndroid Build Coastguard Worker }
455*c0909341SAndroid Build Coastguard Worker
dav1d_get_picture(Dav1dContext * const c,Dav1dPicture * const out)456*c0909341SAndroid Build Coastguard Worker int dav1d_get_picture(Dav1dContext *const c, Dav1dPicture *const out)
457*c0909341SAndroid Build Coastguard Worker {
458*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(c != NULL, DAV1D_ERR(EINVAL));
459*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(out != NULL, DAV1D_ERR(EINVAL));
460*c0909341SAndroid Build Coastguard Worker
461*c0909341SAndroid Build Coastguard Worker const int drain = c->drain;
462*c0909341SAndroid Build Coastguard Worker c->drain = 1;
463*c0909341SAndroid Build Coastguard Worker
464*c0909341SAndroid Build Coastguard Worker int res = gen_picture(c);
465*c0909341SAndroid Build Coastguard Worker if (res < 0)
466*c0909341SAndroid Build Coastguard Worker return res;
467*c0909341SAndroid Build Coastguard Worker
468*c0909341SAndroid Build Coastguard Worker if (c->cached_error) {
469*c0909341SAndroid Build Coastguard Worker const int res = c->cached_error;
470*c0909341SAndroid Build Coastguard Worker c->cached_error = 0;
471*c0909341SAndroid Build Coastguard Worker return res;
472*c0909341SAndroid Build Coastguard Worker }
473*c0909341SAndroid Build Coastguard Worker
474*c0909341SAndroid Build Coastguard Worker if (output_picture_ready(c, c->n_fc == 1))
475*c0909341SAndroid Build Coastguard Worker return output_image(c, out);
476*c0909341SAndroid Build Coastguard Worker
477*c0909341SAndroid Build Coastguard Worker if (c->n_fc > 1 && drain)
478*c0909341SAndroid Build Coastguard Worker return drain_picture(c, out);
479*c0909341SAndroid Build Coastguard Worker
480*c0909341SAndroid Build Coastguard Worker return DAV1D_ERR(EAGAIN);
481*c0909341SAndroid Build Coastguard Worker }
482*c0909341SAndroid Build Coastguard Worker
dav1d_apply_grain(Dav1dContext * const c,Dav1dPicture * const out,const Dav1dPicture * const in)483*c0909341SAndroid Build Coastguard Worker int dav1d_apply_grain(Dav1dContext *const c, Dav1dPicture *const out,
484*c0909341SAndroid Build Coastguard Worker const Dav1dPicture *const in)
485*c0909341SAndroid Build Coastguard Worker {
486*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(c != NULL, DAV1D_ERR(EINVAL));
487*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(out != NULL, DAV1D_ERR(EINVAL));
488*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(in != NULL, DAV1D_ERR(EINVAL));
489*c0909341SAndroid Build Coastguard Worker
490*c0909341SAndroid Build Coastguard Worker if (!has_grain(in)) {
491*c0909341SAndroid Build Coastguard Worker dav1d_picture_ref(out, in);
492*c0909341SAndroid Build Coastguard Worker return 0;
493*c0909341SAndroid Build Coastguard Worker }
494*c0909341SAndroid Build Coastguard Worker
495*c0909341SAndroid Build Coastguard Worker int res = dav1d_picture_alloc_copy(c, out, in->p.w, in);
496*c0909341SAndroid Build Coastguard Worker if (res < 0) goto error;
497*c0909341SAndroid Build Coastguard Worker
498*c0909341SAndroid Build Coastguard Worker if (c->n_tc > 1) {
499*c0909341SAndroid Build Coastguard Worker dav1d_task_delayed_fg(c, out, in);
500*c0909341SAndroid Build Coastguard Worker } else {
501*c0909341SAndroid Build Coastguard Worker switch (out->p.bpc) {
502*c0909341SAndroid Build Coastguard Worker #if CONFIG_8BPC
503*c0909341SAndroid Build Coastguard Worker case 8:
504*c0909341SAndroid Build Coastguard Worker dav1d_apply_grain_8bpc(&c->dsp[0].fg, out, in);
505*c0909341SAndroid Build Coastguard Worker break;
506*c0909341SAndroid Build Coastguard Worker #endif
507*c0909341SAndroid Build Coastguard Worker #if CONFIG_16BPC
508*c0909341SAndroid Build Coastguard Worker case 10:
509*c0909341SAndroid Build Coastguard Worker case 12:
510*c0909341SAndroid Build Coastguard Worker dav1d_apply_grain_16bpc(&c->dsp[(out->p.bpc >> 1) - 4].fg, out, in);
511*c0909341SAndroid Build Coastguard Worker break;
512*c0909341SAndroid Build Coastguard Worker #endif
513*c0909341SAndroid Build Coastguard Worker default: abort();
514*c0909341SAndroid Build Coastguard Worker }
515*c0909341SAndroid Build Coastguard Worker }
516*c0909341SAndroid Build Coastguard Worker
517*c0909341SAndroid Build Coastguard Worker return 0;
518*c0909341SAndroid Build Coastguard Worker
519*c0909341SAndroid Build Coastguard Worker error:
520*c0909341SAndroid Build Coastguard Worker dav1d_picture_unref_internal(out);
521*c0909341SAndroid Build Coastguard Worker return res;
522*c0909341SAndroid Build Coastguard Worker }
523*c0909341SAndroid Build Coastguard Worker
dav1d_flush(Dav1dContext * const c)524*c0909341SAndroid Build Coastguard Worker void dav1d_flush(Dav1dContext *const c) {
525*c0909341SAndroid Build Coastguard Worker dav1d_data_unref_internal(&c->in);
526*c0909341SAndroid Build Coastguard Worker if (c->out.p.frame_hdr)
527*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(&c->out);
528*c0909341SAndroid Build Coastguard Worker if (c->cache.p.frame_hdr)
529*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(&c->cache);
530*c0909341SAndroid Build Coastguard Worker
531*c0909341SAndroid Build Coastguard Worker c->drain = 0;
532*c0909341SAndroid Build Coastguard Worker c->cached_error = 0;
533*c0909341SAndroid Build Coastguard Worker
534*c0909341SAndroid Build Coastguard Worker for (int i = 0; i < 8; i++) {
535*c0909341SAndroid Build Coastguard Worker if (c->refs[i].p.p.frame_hdr)
536*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(&c->refs[i].p);
537*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->refs[i].segmap);
538*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->refs[i].refmvs);
539*c0909341SAndroid Build Coastguard Worker dav1d_cdf_thread_unref(&c->cdf[i]);
540*c0909341SAndroid Build Coastguard Worker }
541*c0909341SAndroid Build Coastguard Worker c->frame_hdr = NULL;
542*c0909341SAndroid Build Coastguard Worker c->seq_hdr = NULL;
543*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->seq_hdr_ref);
544*c0909341SAndroid Build Coastguard Worker
545*c0909341SAndroid Build Coastguard Worker c->mastering_display = NULL;
546*c0909341SAndroid Build Coastguard Worker c->content_light = NULL;
547*c0909341SAndroid Build Coastguard Worker c->itut_t35 = NULL;
548*c0909341SAndroid Build Coastguard Worker c->n_itut_t35 = 0;
549*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->mastering_display_ref);
550*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->content_light_ref);
551*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->itut_t35_ref);
552*c0909341SAndroid Build Coastguard Worker
553*c0909341SAndroid Build Coastguard Worker dav1d_data_props_unref_internal(&c->cached_error_props);
554*c0909341SAndroid Build Coastguard Worker
555*c0909341SAndroid Build Coastguard Worker if (c->n_fc == 1 && c->n_tc == 1) return;
556*c0909341SAndroid Build Coastguard Worker atomic_store(c->flush, 1);
557*c0909341SAndroid Build Coastguard Worker
558*c0909341SAndroid Build Coastguard Worker // stop running tasks in worker threads
559*c0909341SAndroid Build Coastguard Worker if (c->n_tc > 1) {
560*c0909341SAndroid Build Coastguard Worker pthread_mutex_lock(&c->task_thread.lock);
561*c0909341SAndroid Build Coastguard Worker for (unsigned i = 0; i < c->n_tc; i++) {
562*c0909341SAndroid Build Coastguard Worker Dav1dTaskContext *const tc = &c->tc[i];
563*c0909341SAndroid Build Coastguard Worker while (!tc->task_thread.flushed) {
564*c0909341SAndroid Build Coastguard Worker pthread_cond_wait(&tc->task_thread.td.cond, &c->task_thread.lock);
565*c0909341SAndroid Build Coastguard Worker }
566*c0909341SAndroid Build Coastguard Worker }
567*c0909341SAndroid Build Coastguard Worker for (unsigned i = 0; i < c->n_fc; i++) {
568*c0909341SAndroid Build Coastguard Worker c->fc[i].task_thread.task_head = NULL;
569*c0909341SAndroid Build Coastguard Worker c->fc[i].task_thread.task_tail = NULL;
570*c0909341SAndroid Build Coastguard Worker c->fc[i].task_thread.task_cur_prev = NULL;
571*c0909341SAndroid Build Coastguard Worker c->fc[i].task_thread.pending_tasks.head = NULL;
572*c0909341SAndroid Build Coastguard Worker c->fc[i].task_thread.pending_tasks.tail = NULL;
573*c0909341SAndroid Build Coastguard Worker atomic_init(&c->fc[i].task_thread.pending_tasks.merge, 0);
574*c0909341SAndroid Build Coastguard Worker }
575*c0909341SAndroid Build Coastguard Worker atomic_init(&c->task_thread.first, 0);
576*c0909341SAndroid Build Coastguard Worker c->task_thread.cur = c->n_fc;
577*c0909341SAndroid Build Coastguard Worker atomic_store(&c->task_thread.reset_task_cur, UINT_MAX);
578*c0909341SAndroid Build Coastguard Worker atomic_store(&c->task_thread.cond_signaled, 0);
579*c0909341SAndroid Build Coastguard Worker pthread_mutex_unlock(&c->task_thread.lock);
580*c0909341SAndroid Build Coastguard Worker }
581*c0909341SAndroid Build Coastguard Worker
582*c0909341SAndroid Build Coastguard Worker // wait for threads to complete flushing
583*c0909341SAndroid Build Coastguard Worker if (c->n_fc > 1) {
584*c0909341SAndroid Build Coastguard Worker for (unsigned n = 0, next = c->frame_thread.next; n < c->n_fc; n++, next++) {
585*c0909341SAndroid Build Coastguard Worker if (next == c->n_fc) next = 0;
586*c0909341SAndroid Build Coastguard Worker Dav1dFrameContext *const f = &c->fc[next];
587*c0909341SAndroid Build Coastguard Worker dav1d_decode_frame_exit(f, -1);
588*c0909341SAndroid Build Coastguard Worker f->n_tile_data = 0;
589*c0909341SAndroid Build Coastguard Worker f->task_thread.retval = 0;
590*c0909341SAndroid Build Coastguard Worker Dav1dThreadPicture *out_delayed = &c->frame_thread.out_delayed[next];
591*c0909341SAndroid Build Coastguard Worker if (out_delayed->p.frame_hdr) {
592*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(out_delayed);
593*c0909341SAndroid Build Coastguard Worker }
594*c0909341SAndroid Build Coastguard Worker }
595*c0909341SAndroid Build Coastguard Worker c->frame_thread.next = 0;
596*c0909341SAndroid Build Coastguard Worker }
597*c0909341SAndroid Build Coastguard Worker atomic_store(c->flush, 0);
598*c0909341SAndroid Build Coastguard Worker }
599*c0909341SAndroid Build Coastguard Worker
dav1d_close(Dav1dContext ** const c_out)600*c0909341SAndroid Build Coastguard Worker COLD void dav1d_close(Dav1dContext **const c_out) {
601*c0909341SAndroid Build Coastguard Worker validate_input(c_out != NULL);
602*c0909341SAndroid Build Coastguard Worker #if TRACK_HEAP_ALLOCATIONS
603*c0909341SAndroid Build Coastguard Worker dav1d_log_alloc_stats(*c_out);
604*c0909341SAndroid Build Coastguard Worker #endif
605*c0909341SAndroid Build Coastguard Worker close_internal(c_out, 1);
606*c0909341SAndroid Build Coastguard Worker }
607*c0909341SAndroid Build Coastguard Worker
close_internal(Dav1dContext ** const c_out,int flush)608*c0909341SAndroid Build Coastguard Worker static COLD void close_internal(Dav1dContext **const c_out, int flush) {
609*c0909341SAndroid Build Coastguard Worker Dav1dContext *const c = *c_out;
610*c0909341SAndroid Build Coastguard Worker if (!c) return;
611*c0909341SAndroid Build Coastguard Worker
612*c0909341SAndroid Build Coastguard Worker if (flush) dav1d_flush(c);
613*c0909341SAndroid Build Coastguard Worker
614*c0909341SAndroid Build Coastguard Worker if (c->tc) {
615*c0909341SAndroid Build Coastguard Worker struct TaskThreadData *ttd = &c->task_thread;
616*c0909341SAndroid Build Coastguard Worker if (ttd->inited) {
617*c0909341SAndroid Build Coastguard Worker pthread_mutex_lock(&ttd->lock);
618*c0909341SAndroid Build Coastguard Worker for (unsigned n = 0; n < c->n_tc && c->tc[n].task_thread.td.inited; n++)
619*c0909341SAndroid Build Coastguard Worker c->tc[n].task_thread.die = 1;
620*c0909341SAndroid Build Coastguard Worker pthread_cond_broadcast(&ttd->cond);
621*c0909341SAndroid Build Coastguard Worker pthread_mutex_unlock(&ttd->lock);
622*c0909341SAndroid Build Coastguard Worker for (unsigned n = 0; n < c->n_tc; n++) {
623*c0909341SAndroid Build Coastguard Worker Dav1dTaskContext *const pf = &c->tc[n];
624*c0909341SAndroid Build Coastguard Worker if (!pf->task_thread.td.inited) break;
625*c0909341SAndroid Build Coastguard Worker pthread_join(pf->task_thread.td.thread, NULL);
626*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&pf->task_thread.td.cond);
627*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&pf->task_thread.td.lock);
628*c0909341SAndroid Build Coastguard Worker }
629*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&ttd->delayed_fg.cond);
630*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&ttd->cond);
631*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&ttd->lock);
632*c0909341SAndroid Build Coastguard Worker }
633*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(c->tc);
634*c0909341SAndroid Build Coastguard Worker }
635*c0909341SAndroid Build Coastguard Worker
636*c0909341SAndroid Build Coastguard Worker for (unsigned n = 0; c->fc && n < c->n_fc; n++) {
637*c0909341SAndroid Build Coastguard Worker Dav1dFrameContext *const f = &c->fc[n];
638*c0909341SAndroid Build Coastguard Worker
639*c0909341SAndroid Build Coastguard Worker // clean-up threading stuff
640*c0909341SAndroid Build Coastguard Worker if (c->n_fc > 1) {
641*c0909341SAndroid Build Coastguard Worker dav1d_free(f->tile_thread.lowest_pixel_mem);
642*c0909341SAndroid Build Coastguard Worker dav1d_free(f->frame_thread.b);
643*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->frame_thread.cbi);
644*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->frame_thread.pal_idx);
645*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->frame_thread.cf);
646*c0909341SAndroid Build Coastguard Worker dav1d_free(f->frame_thread.tile_start_off);
647*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->frame_thread.pal);
648*c0909341SAndroid Build Coastguard Worker }
649*c0909341SAndroid Build Coastguard Worker if (c->n_tc > 1) {
650*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&f->task_thread.pending_tasks.lock);
651*c0909341SAndroid Build Coastguard Worker pthread_cond_destroy(&f->task_thread.cond);
652*c0909341SAndroid Build Coastguard Worker pthread_mutex_destroy(&f->task_thread.lock);
653*c0909341SAndroid Build Coastguard Worker }
654*c0909341SAndroid Build Coastguard Worker dav1d_free(f->frame_thread.frame_progress);
655*c0909341SAndroid Build Coastguard Worker dav1d_free(f->task_thread.tasks);
656*c0909341SAndroid Build Coastguard Worker dav1d_free(f->task_thread.tile_tasks[0]);
657*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->ts);
658*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->ipred_edge[0]);
659*c0909341SAndroid Build Coastguard Worker dav1d_free(f->a);
660*c0909341SAndroid Build Coastguard Worker dav1d_free(f->tile);
661*c0909341SAndroid Build Coastguard Worker dav1d_free(f->lf.mask);
662*c0909341SAndroid Build Coastguard Worker dav1d_free(f->lf.level);
663*c0909341SAndroid Build Coastguard Worker dav1d_free(f->lf.lr_mask);
664*c0909341SAndroid Build Coastguard Worker dav1d_free(f->lf.tx_lpf_right_edge[0]);
665*c0909341SAndroid Build Coastguard Worker dav1d_free(f->lf.start_of_tile_row);
666*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->rf.r);
667*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->lf.cdef_line_buf);
668*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(f->lf.lr_line_buf);
669*c0909341SAndroid Build Coastguard Worker }
670*c0909341SAndroid Build Coastguard Worker dav1d_free_aligned(c->fc);
671*c0909341SAndroid Build Coastguard Worker if (c->n_fc > 1 && c->frame_thread.out_delayed) {
672*c0909341SAndroid Build Coastguard Worker for (unsigned n = 0; n < c->n_fc; n++)
673*c0909341SAndroid Build Coastguard Worker if (c->frame_thread.out_delayed[n].p.frame_hdr)
674*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(&c->frame_thread.out_delayed[n]);
675*c0909341SAndroid Build Coastguard Worker dav1d_free(c->frame_thread.out_delayed);
676*c0909341SAndroid Build Coastguard Worker }
677*c0909341SAndroid Build Coastguard Worker for (int n = 0; n < c->n_tile_data; n++)
678*c0909341SAndroid Build Coastguard Worker dav1d_data_unref_internal(&c->tile[n].data);
679*c0909341SAndroid Build Coastguard Worker dav1d_free(c->tile);
680*c0909341SAndroid Build Coastguard Worker for (int n = 0; n < 8; n++) {
681*c0909341SAndroid Build Coastguard Worker dav1d_cdf_thread_unref(&c->cdf[n]);
682*c0909341SAndroid Build Coastguard Worker if (c->refs[n].p.p.frame_hdr)
683*c0909341SAndroid Build Coastguard Worker dav1d_thread_picture_unref(&c->refs[n].p);
684*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->refs[n].refmvs);
685*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->refs[n].segmap);
686*c0909341SAndroid Build Coastguard Worker }
687*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->seq_hdr_ref);
688*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->frame_hdr_ref);
689*c0909341SAndroid Build Coastguard Worker
690*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->mastering_display_ref);
691*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->content_light_ref);
692*c0909341SAndroid Build Coastguard Worker dav1d_ref_dec(&c->itut_t35_ref);
693*c0909341SAndroid Build Coastguard Worker
694*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->seq_hdr_pool);
695*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->frame_hdr_pool);
696*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->segmap_pool);
697*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->refmvs_pool);
698*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->cdf_pool);
699*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->picture_pool);
700*c0909341SAndroid Build Coastguard Worker dav1d_mem_pool_end(c->pic_ctx_pool);
701*c0909341SAndroid Build Coastguard Worker
702*c0909341SAndroid Build Coastguard Worker dav1d_freep_aligned(c_out);
703*c0909341SAndroid Build Coastguard Worker }
704*c0909341SAndroid Build Coastguard Worker
dav1d_get_event_flags(Dav1dContext * const c,enum Dav1dEventFlags * const flags)705*c0909341SAndroid Build Coastguard Worker int dav1d_get_event_flags(Dav1dContext *const c, enum Dav1dEventFlags *const flags) {
706*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(c != NULL, DAV1D_ERR(EINVAL));
707*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(flags != NULL, DAV1D_ERR(EINVAL));
708*c0909341SAndroid Build Coastguard Worker
709*c0909341SAndroid Build Coastguard Worker *flags = c->event_flags;
710*c0909341SAndroid Build Coastguard Worker c->event_flags = 0;
711*c0909341SAndroid Build Coastguard Worker return 0;
712*c0909341SAndroid Build Coastguard Worker }
713*c0909341SAndroid Build Coastguard Worker
dav1d_get_decode_error_data_props(Dav1dContext * const c,Dav1dDataProps * const out)714*c0909341SAndroid Build Coastguard Worker int dav1d_get_decode_error_data_props(Dav1dContext *const c, Dav1dDataProps *const out) {
715*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(c != NULL, DAV1D_ERR(EINVAL));
716*c0909341SAndroid Build Coastguard Worker validate_input_or_ret(out != NULL, DAV1D_ERR(EINVAL));
717*c0909341SAndroid Build Coastguard Worker
718*c0909341SAndroid Build Coastguard Worker dav1d_data_props_unref_internal(out);
719*c0909341SAndroid Build Coastguard Worker *out = c->cached_error_props;
720*c0909341SAndroid Build Coastguard Worker dav1d_data_props_set_defaults(&c->cached_error_props);
721*c0909341SAndroid Build Coastguard Worker
722*c0909341SAndroid Build Coastguard Worker return 0;
723*c0909341SAndroid Build Coastguard Worker }
724*c0909341SAndroid Build Coastguard Worker
dav1d_picture_unref(Dav1dPicture * const p)725*c0909341SAndroid Build Coastguard Worker void dav1d_picture_unref(Dav1dPicture *const p) {
726*c0909341SAndroid Build Coastguard Worker dav1d_picture_unref_internal(p);
727*c0909341SAndroid Build Coastguard Worker }
728*c0909341SAndroid Build Coastguard Worker
dav1d_data_create(Dav1dData * const buf,const size_t sz)729*c0909341SAndroid Build Coastguard Worker uint8_t *dav1d_data_create(Dav1dData *const buf, const size_t sz) {
730*c0909341SAndroid Build Coastguard Worker return dav1d_data_create_internal(buf, sz);
731*c0909341SAndroid Build Coastguard Worker }
732*c0909341SAndroid Build Coastguard Worker
dav1d_data_wrap(Dav1dData * const buf,const uint8_t * const ptr,const size_t sz,void (* const free_callback)(const uint8_t * data,void * user_data),void * const user_data)733*c0909341SAndroid Build Coastguard Worker int dav1d_data_wrap(Dav1dData *const buf, const uint8_t *const ptr,
734*c0909341SAndroid Build Coastguard Worker const size_t sz,
735*c0909341SAndroid Build Coastguard Worker void (*const free_callback)(const uint8_t *data,
736*c0909341SAndroid Build Coastguard Worker void *user_data),
737*c0909341SAndroid Build Coastguard Worker void *const user_data)
738*c0909341SAndroid Build Coastguard Worker {
739*c0909341SAndroid Build Coastguard Worker return dav1d_data_wrap_internal(buf, ptr, sz, free_callback, user_data);
740*c0909341SAndroid Build Coastguard Worker }
741*c0909341SAndroid Build Coastguard Worker
dav1d_data_wrap_user_data(Dav1dData * const buf,const uint8_t * const user_data,void (* const free_callback)(const uint8_t * user_data,void * cookie),void * const cookie)742*c0909341SAndroid Build Coastguard Worker int dav1d_data_wrap_user_data(Dav1dData *const buf,
743*c0909341SAndroid Build Coastguard Worker const uint8_t *const user_data,
744*c0909341SAndroid Build Coastguard Worker void (*const free_callback)(const uint8_t *user_data,
745*c0909341SAndroid Build Coastguard Worker void *cookie),
746*c0909341SAndroid Build Coastguard Worker void *const cookie)
747*c0909341SAndroid Build Coastguard Worker {
748*c0909341SAndroid Build Coastguard Worker return dav1d_data_wrap_user_data_internal(buf,
749*c0909341SAndroid Build Coastguard Worker user_data,
750*c0909341SAndroid Build Coastguard Worker free_callback,
751*c0909341SAndroid Build Coastguard Worker cookie);
752*c0909341SAndroid Build Coastguard Worker }
753*c0909341SAndroid Build Coastguard Worker
dav1d_data_unref(Dav1dData * const buf)754*c0909341SAndroid Build Coastguard Worker void dav1d_data_unref(Dav1dData *const buf) {
755*c0909341SAndroid Build Coastguard Worker dav1d_data_unref_internal(buf);
756*c0909341SAndroid Build Coastguard Worker }
757*c0909341SAndroid Build Coastguard Worker
dav1d_data_props_unref(Dav1dDataProps * const props)758*c0909341SAndroid Build Coastguard Worker void dav1d_data_props_unref(Dav1dDataProps *const props) {
759*c0909341SAndroid Build Coastguard Worker dav1d_data_props_unref_internal(props);
760*c0909341SAndroid Build Coastguard Worker }
761