xref: /aosp_15_r20/external/libaom/aom_dsp/pyramid.h (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2022, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #ifndef AOM_AOM_DSP_PYRAMID_H_
13*77c1e3ccSAndroid Build Coastguard Worker #define AOM_AOM_DSP_PYRAMID_H_
14*77c1e3ccSAndroid Build Coastguard Worker 
15*77c1e3ccSAndroid Build Coastguard Worker #include <stddef.h>
16*77c1e3ccSAndroid Build Coastguard Worker #include <stdint.h>
17*77c1e3ccSAndroid Build Coastguard Worker #include <stdbool.h>
18*77c1e3ccSAndroid Build Coastguard Worker 
19*77c1e3ccSAndroid Build Coastguard Worker #include "config/aom_config.h"
20*77c1e3ccSAndroid Build Coastguard Worker 
21*77c1e3ccSAndroid Build Coastguard Worker #include "aom_scale/yv12config.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "aom_util/aom_pthread.h"
23*77c1e3ccSAndroid Build Coastguard Worker 
24*77c1e3ccSAndroid Build Coastguard Worker #ifdef __cplusplus
25*77c1e3ccSAndroid Build Coastguard Worker extern "C" {
26*77c1e3ccSAndroid Build Coastguard Worker #endif
27*77c1e3ccSAndroid Build Coastguard Worker 
28*77c1e3ccSAndroid Build Coastguard Worker // Minimum dimensions of a downsampled image
29*77c1e3ccSAndroid Build Coastguard Worker #define MIN_PYRAMID_SIZE_LOG2 3
30*77c1e3ccSAndroid Build Coastguard Worker #define MIN_PYRAMID_SIZE (1 << MIN_PYRAMID_SIZE_LOG2)
31*77c1e3ccSAndroid Build Coastguard Worker 
32*77c1e3ccSAndroid Build Coastguard Worker // Size of border around each pyramid image, in pixels
33*77c1e3ccSAndroid Build Coastguard Worker // Similarly to the border around regular image buffers, this border is filled
34*77c1e3ccSAndroid Build Coastguard Worker // with copies of the outermost pixels of the frame, to allow for more efficient
35*77c1e3ccSAndroid Build Coastguard Worker // convolution code
36*77c1e3ccSAndroid Build Coastguard Worker // TODO(rachelbarker): How many pixels do we actually need here?
37*77c1e3ccSAndroid Build Coastguard Worker // I think we only need 9 for disflow, but how many for corner matching?
38*77c1e3ccSAndroid Build Coastguard Worker #define PYRAMID_PADDING 16
39*77c1e3ccSAndroid Build Coastguard Worker 
40*77c1e3ccSAndroid Build Coastguard Worker // Byte alignment of each line within the image pyramids.
41*77c1e3ccSAndroid Build Coastguard Worker // That is, the first pixel inside the image (ie, not in the border region),
42*77c1e3ccSAndroid Build Coastguard Worker // on each row of each pyramid level, is aligned to this byte alignment.
43*77c1e3ccSAndroid Build Coastguard Worker // This value must be a power of 2.
44*77c1e3ccSAndroid Build Coastguard Worker #define PYRAMID_ALIGNMENT 32
45*77c1e3ccSAndroid Build Coastguard Worker 
46*77c1e3ccSAndroid Build Coastguard Worker typedef struct {
47*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *buffer;
48*77c1e3ccSAndroid Build Coastguard Worker   int width;
49*77c1e3ccSAndroid Build Coastguard Worker   int height;
50*77c1e3ccSAndroid Build Coastguard Worker   int stride;
51*77c1e3ccSAndroid Build Coastguard Worker } PyramidLayer;
52*77c1e3ccSAndroid Build Coastguard Worker 
53*77c1e3ccSAndroid Build Coastguard Worker // Struct for an image pyramid
54*77c1e3ccSAndroid Build Coastguard Worker typedef struct image_pyramid {
55*77c1e3ccSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
56*77c1e3ccSAndroid Build Coastguard Worker   // Mutex which is used to prevent the pyramid being computed twice at the
57*77c1e3ccSAndroid Build Coastguard Worker   // same time
58*77c1e3ccSAndroid Build Coastguard Worker   //
59*77c1e3ccSAndroid Build Coastguard Worker   // Semantics:
60*77c1e3ccSAndroid Build Coastguard Worker   // * This mutex must be held whenever reading or writing the
61*77c1e3ccSAndroid Build Coastguard Worker   //   `filled_levels` field
62*77c1e3ccSAndroid Build Coastguard Worker   //
63*77c1e3ccSAndroid Build Coastguard Worker   // * This mutex must also be held while computing the image pyramid,
64*77c1e3ccSAndroid Build Coastguard Worker   //   to ensure that only one thread may do so at a time.
65*77c1e3ccSAndroid Build Coastguard Worker   //
66*77c1e3ccSAndroid Build Coastguard Worker   // * However, once you have read the filled_levels field and observed
67*77c1e3ccSAndroid Build Coastguard Worker   //   a value N, it is safe to drop the mutex and read from the remaining
68*77c1e3ccSAndroid Build Coastguard Worker   //   fields, including the first N pyramid levels (but no higher).
69*77c1e3ccSAndroid Build Coastguard Worker   //   Note that filled_levels must be read once and cached in a local variable
70*77c1e3ccSAndroid Build Coastguard Worker   //   in order for this to be safe - it cannot be re-read without retaking
71*77c1e3ccSAndroid Build Coastguard Worker   //   the mutex.
72*77c1e3ccSAndroid Build Coastguard Worker   //
73*77c1e3ccSAndroid Build Coastguard Worker   //   This works because, once the image pyramid is computed, its contents
74*77c1e3ccSAndroid Build Coastguard Worker   //   will not be changed until the parent frame buffer is recycled,
75*77c1e3ccSAndroid Build Coastguard Worker   //   which will not happen until there are no more outstanding references
76*77c1e3ccSAndroid Build Coastguard Worker   //   to the frame buffer.
77*77c1e3ccSAndroid Build Coastguard Worker   pthread_mutex_t mutex;
78*77c1e3ccSAndroid Build Coastguard Worker #endif
79*77c1e3ccSAndroid Build Coastguard Worker   // Maximum number of levels for the given frame size
80*77c1e3ccSAndroid Build Coastguard Worker   // We always allocate enough memory for this many levels, as the memory
81*77c1e3ccSAndroid Build Coastguard Worker   // cost of higher levels of the pyramid is minimal.
82*77c1e3ccSAndroid Build Coastguard Worker   int max_levels;
83*77c1e3ccSAndroid Build Coastguard Worker   // Number of levels which currently hold valid data
84*77c1e3ccSAndroid Build Coastguard Worker   int filled_levels;
85*77c1e3ccSAndroid Build Coastguard Worker   // Pointer to allocated buffer
86*77c1e3ccSAndroid Build Coastguard Worker   uint8_t *buffer_alloc;
87*77c1e3ccSAndroid Build Coastguard Worker   // Data for each level
88*77c1e3ccSAndroid Build Coastguard Worker   // The `buffer` pointers inside this array point into the region which
89*77c1e3ccSAndroid Build Coastguard Worker   // is stored in the `buffer_alloc` field here
90*77c1e3ccSAndroid Build Coastguard Worker   PyramidLayer *layers;
91*77c1e3ccSAndroid Build Coastguard Worker } ImagePyramid;
92*77c1e3ccSAndroid Build Coastguard Worker 
93*77c1e3ccSAndroid Build Coastguard Worker size_t aom_get_pyramid_alloc_size(int width, int height, bool image_is_16bit);
94*77c1e3ccSAndroid Build Coastguard Worker 
95*77c1e3ccSAndroid Build Coastguard Worker ImagePyramid *aom_alloc_pyramid(int width, int height, bool image_is_16bit);
96*77c1e3ccSAndroid Build Coastguard Worker 
97*77c1e3ccSAndroid Build Coastguard Worker // Fill out a downsampling pyramid for a given frame.
98*77c1e3ccSAndroid Build Coastguard Worker //
99*77c1e3ccSAndroid Build Coastguard Worker // The top level (index 0) will always be an 8-bit copy of the input frame,
100*77c1e3ccSAndroid Build Coastguard Worker // regardless of the input bit depth. Additional levels are then downscaled
101*77c1e3ccSAndroid Build Coastguard Worker // by powers of 2.
102*77c1e3ccSAndroid Build Coastguard Worker //
103*77c1e3ccSAndroid Build Coastguard Worker // This function will ensure that the first `n_levels` levels of the pyramid
104*77c1e3ccSAndroid Build Coastguard Worker // are filled, unless the frame is too small to have this many levels.
105*77c1e3ccSAndroid Build Coastguard Worker // In that case, we will fill all available levels and then stop.
106*77c1e3ccSAndroid Build Coastguard Worker //
107*77c1e3ccSAndroid Build Coastguard Worker // Returns the actual number of levels filled, capped at n_levels,
108*77c1e3ccSAndroid Build Coastguard Worker // or -1 on error.
109*77c1e3ccSAndroid Build Coastguard Worker int aom_compute_pyramid(const YV12_BUFFER_CONFIG *frame, int bit_depth,
110*77c1e3ccSAndroid Build Coastguard Worker                         int n_levels, ImagePyramid *pyr);
111*77c1e3ccSAndroid Build Coastguard Worker 
112*77c1e3ccSAndroid Build Coastguard Worker #ifndef NDEBUG
113*77c1e3ccSAndroid Build Coastguard Worker // Check if a pyramid has already been computed to at least n levels
114*77c1e3ccSAndroid Build Coastguard Worker // This is mostly a debug helper - as it is necessary to hold pyr->mutex
115*77c1e3ccSAndroid Build Coastguard Worker // while reading the number of already-computed levels, we cannot just write:
116*77c1e3ccSAndroid Build Coastguard Worker //   assert(pyr->filled_levels >= n_levels);
117*77c1e3ccSAndroid Build Coastguard Worker // This function allows the check to be correctly written as:
118*77c1e3ccSAndroid Build Coastguard Worker //   assert(aom_is_pyramid_valid(pyr, n_levels));
119*77c1e3ccSAndroid Build Coastguard Worker //
120*77c1e3ccSAndroid Build Coastguard Worker // Note: This deliberately does not restrict n_levels based on the maximum
121*77c1e3ccSAndroid Build Coastguard Worker // number of permitted levels for the frame size. This allows the check to
122*77c1e3ccSAndroid Build Coastguard Worker // catch cases where the caller forgets to handle the case where
123*77c1e3ccSAndroid Build Coastguard Worker // max_levels is less than the requested number of levels
124*77c1e3ccSAndroid Build Coastguard Worker bool aom_is_pyramid_valid(ImagePyramid *pyr, int n_levels);
125*77c1e3ccSAndroid Build Coastguard Worker #endif
126*77c1e3ccSAndroid Build Coastguard Worker 
127*77c1e3ccSAndroid Build Coastguard Worker // Mark a pyramid as no longer containing valid data.
128*77c1e3ccSAndroid Build Coastguard Worker // This must be done whenever the corresponding frame buffer is reused
129*77c1e3ccSAndroid Build Coastguard Worker void aom_invalidate_pyramid(ImagePyramid *pyr);
130*77c1e3ccSAndroid Build Coastguard Worker 
131*77c1e3ccSAndroid Build Coastguard Worker // Release the memory associated with a pyramid
132*77c1e3ccSAndroid Build Coastguard Worker void aom_free_pyramid(ImagePyramid *pyr);
133*77c1e3ccSAndroid Build Coastguard Worker 
134*77c1e3ccSAndroid Build Coastguard Worker #ifdef __cplusplus
135*77c1e3ccSAndroid Build Coastguard Worker }
136*77c1e3ccSAndroid Build Coastguard Worker #endif
137*77c1e3ccSAndroid Build Coastguard Worker 
138*77c1e3ccSAndroid Build Coastguard Worker #endif  // AOM_AOM_DSP_PYRAMID_H_
139