1 /*****************************************************************************
2  * Copyright (C) 2013-2020 MulticoreWare, Inc
3  *
4  * Authors: Pooja Venkatesan <pooja@multicorewareinc.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
19  *
20  * This program is also available under a commercial proprietary license.
21  * For more information, contact us at license @ x265.com.
22  *****************************************************************************/
23 
24 #ifndef X265_SCALER_H
25 #define X265_SCALER_H
26 
27 #include "common.h"
28 
29 namespace X265_NS {
30 //x265 private namespace
31 
32 class ScalerSlice;
33 class VideoDesc;
34 
35 #define MAX_NUM_LINES_AHEAD 4
36 #define SCALER_ALIGN(x, j) (((x)+(j)-1)&~((j)-1))
37 #define X265_ABS(j) ((j) >= 0 ? (j) : (-(j)))
38 #define SCALER_MAX_REDUCE_CUTOFF 0.002
39 #define SCALER_BITEXACT  0x80000
40 #define ROUNDED_DIVISION(i,j) (((i)>0 ? (i) + ((j)>>1) : (i) - ((j)>>1))/(j))
41 #define UH_CEIL_SHIFTR(i,j) (!scale_builtin_constant_p(j) ? -((-(i)) >> (j)) \
42                                                           : ((i) + (1<<(j)) - 1) >> (j))
43 
44 #if defined(__GNUC__) || defined(__clang__)
45 #    define scale_builtin_constant_p __builtin_constant_p
46 #else
47 #    define scale_builtin_constant_p(x) 0
48 #endif
49 
50 enum ResFactor
51 {
52     RES_FACTOR_64, RES_FACTOR_32, RES_FACTOR_16, RES_FACTOR_8,
53     RES_FACTOR_4, RES_FACTOR_DEF, NUM_RES_FACTOR
54 };
55 
56 enum ScalerFactor
57 {
58     FACTOR_4, FACTOR_8, NUM_FACTOR
59 };
60 
61 enum FilterSize
62 {
63     FIL_4, FIL_6, FIL_8, FIL_9, FIL_10, FIL_11, FIL_13, FIL_15,
64     FIL_16, FIL_17, FIL_19, FIL_22, FIL_24, FIL_DEF, NUM_FIL
65 };
66 
67 class ScalerFilter {
68 public:
69     int             m_filtLen;
70     int32_t*        m_filtPos;      // Array of horizontal/vertical starting pos for each dst for luma / chroma planes.
71     int16_t*        m_filt;         // Array of horizontal/vertical filter coefficients for luma / chroma planes.
72     ScalerSlice*    m_sourceSlice;  // Source slice
73     ScalerSlice*    m_destSlice;    // Output slice
74     ScalerFilter();
75     virtual ~ScalerFilter();
76     virtual void process(int sliceVer, int sliceHor) = 0;
77     int initCoeff(int flag, int inc, int srcW, int dstW, int filtAlign, int one, int sourcePos, int destPos);
setSlice(ScalerSlice * source,ScalerSlice * dest)78     void setSlice(ScalerSlice* source, ScalerSlice* dest) { m_sourceSlice = source; m_destSlice = dest; }
79 };
80 
81 class VideoDesc {
82 public:
83     int         m_width;
84     int         m_height;
85     int         m_csp;
86     int         m_inputDepth;
87 
VideoDesc(int w,int h,int csp,int bitDepth)88     VideoDesc(int w, int h, int csp, int bitDepth)
89     {
90         m_width = w;
91         m_height = h;
92         m_csp = csp;
93         m_inputDepth = bitDepth;
94     }
95 };
96 
97 typedef struct ScalerPlane
98 {
99     int       availLines; // max number of lines that can be held by this plane
100     int       sliceVer;   // index of first line
101     int       sliceHor;   // number of lines
102     uint8_t** lineBuf;    // line buffer
103 } ScalerPlane;
104 
105 // Assist horizontal filtering, base class
106 class HFilterScaler {
107 public:
108     int m_bitDepth;
109 public:
HFilterScaler()110     HFilterScaler() :m_bitDepth(0) {};
~HFilterScaler()111     virtual ~HFilterScaler() {};
112     virtual void doScaling(int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize) = 0;
113 };
114 
115 // Assist vertical filtering, base class
116 class VFilterScaler {
117 public:
118     int m_bitDepth;
119 public:
VFilterScaler()120     VFilterScaler() :m_bitDepth(0) {};
~VFilterScaler()121     virtual ~VFilterScaler() {};
122     virtual void yuv2PlaneX(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW) = 0;
123 };
124 
125 //  Assist horizontal filtering, process 8 bit case
126 class HFilterScaler8Bit : public HFilterScaler {
127 public:
HFilterScaler8Bit()128     HFilterScaler8Bit() { m_bitDepth = 8; }
129     virtual void doScaling(int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize);
130 };
131 
132 //  Assist horizontal filtering, process 10 bit case
133 class HFilterScaler10Bit : public HFilterScaler {
134 public:
HFilterScaler10Bit()135     HFilterScaler10Bit() { m_bitDepth = 10; }
136     virtual void doScaling(int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize);
137 };
138 
139 //  Assist vertical filtering, process 8 bit case
140 class VFilterScaler8Bit : public VFilterScaler {
141 public:
VFilterScaler8Bit()142     VFilterScaler8Bit() { m_bitDepth = 8; }
143     virtual void yuv2PlaneX(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW);
144 };
145 
146 //  Assist vertical filtering, process 10 bit case
147 class VFilterScaler10Bit : public VFilterScaler {
148 public:
VFilterScaler10Bit()149     VFilterScaler10Bit() { m_bitDepth = 10; }
150     virtual void yuv2PlaneX(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW);
151 };
152 
153 // Horizontal filter for luma
154 class ScalerHLumFilter : public ScalerFilter {
155 private:
156     HFilterScaler* m_hFilterScaler;
157 public:
ScalerHLumFilter(int bitDepth)158     ScalerHLumFilter(int bitDepth) { bitDepth == 8 ? m_hFilterScaler = new HFilterScaler8Bit : bitDepth == 10 ? m_hFilterScaler = new HFilterScaler10Bit : NULL;}
~ScalerHLumFilter()159     ~ScalerHLumFilter() { if (m_hFilterScaler) X265_FREE(m_hFilterScaler); }
160     virtual void process(int sliceVer, int sliceHor);
161 };
162 
163 // Horizontal filter for chroma
164 class ScalerHCrFilter : public ScalerFilter {
165 private:
166     HFilterScaler* m_hFilterScaler;
167 public:
ScalerHCrFilter(int bitDepth)168     ScalerHCrFilter(int bitDepth) { bitDepth == 8 ? m_hFilterScaler = new HFilterScaler8Bit : bitDepth == 10 ? m_hFilterScaler = new HFilterScaler10Bit : NULL;}
~ScalerHCrFilter()169     ~ScalerHCrFilter() { if (m_hFilterScaler) X265_FREE(m_hFilterScaler); }
170     virtual void process(int sliceVer, int sliceHor);
171 };
172 
173 // Vertical filter for luma
174 class ScalerVLumFilter : public ScalerFilter {
175 private:
176     VFilterScaler* m_vFilterScaler;
177 public:
ScalerVLumFilter(int bitDepth)178     ScalerVLumFilter(int bitDepth) { bitDepth == 8 ? m_vFilterScaler = new VFilterScaler8Bit : bitDepth == 10 ? m_vFilterScaler = new VFilterScaler10Bit : NULL;}
~ScalerVLumFilter()179     ~ScalerVLumFilter() { if (m_vFilterScaler) X265_FREE(m_vFilterScaler); }
180     virtual void process(int sliceVer, int sliceHor);
181 };
182 
183 // Vertical filter for chroma
184 class ScalerVCrFilter : public ScalerFilter {
185 private:
186     VFilterScaler*    m_vFilterScaler;
187 public:
ScalerVCrFilter(int bitDepth)188     ScalerVCrFilter(int bitDepth) { bitDepth == 8 ? m_vFilterScaler = new VFilterScaler8Bit : bitDepth == 10 ? m_vFilterScaler = new VFilterScaler10Bit : NULL;}
~ScalerVCrFilter()189     ~ScalerVCrFilter() { if (m_vFilterScaler) X265_FREE(m_vFilterScaler); }
190     virtual void process(int sliceVer, int sliceHor);
191 };
192 
193 class ScalerSlice
194 {
195 private:
196     enum ScalerSlicePlaneNum { m_numSlicePlane = 4 };
197 public:
198     int m_width;        // Slice line width
199     int m_hCrSubSample; // horizontal Chroma subsampling factor
200     int m_vCrSubSample; // vertical chroma subsampling factor
201     int m_isRing;       // flag to identify if this ScalerSlice is a ring buffer
202     int m_destroyLines; // flag to identify if there are dynamic allocated lines
203     ScalerPlane m_plane[m_numSlicePlane];
204 public:
205     ScalerSlice();
~ScalerSlice()206     ~ScalerSlice() { destroy(); }
207     int rotate(int lum, int cr);
208     void fillOnes(int n, int is16bit);
209     int create(int lumLines, int crLines, int h_sub_sample, int v_sub_sample, int ring);
210     int createLines(int size, int width);
211     void destroyLines();
212     void destroy();
213     int initFromSrc(uint8_t *src[4], const int stride[4], int srcW, int lumY, int lumH, int crY, int crH, int relative);
214 };
215 
216 class ScalerFilterManager {
217 private:
218     enum ScalerFilterNum { m_numSlice = 3, m_numFilter = 4 };
219 
220 private:
221     int                     m_bitDepth;
222     int                     m_algorithmFlags;  // 1, bilinear; 4 bicubic, default is bicubic
223     int                     m_srcW;            // Width  of source luma planes.
224     int                     m_srcH;            // Height of source luma planes.
225     int                     m_dstW;            // Width of dest luma planes.
226     int                     m_dstH;            // Height of dest luma planes.
227     int                     m_crSrcW;          // Width  of source chroma planes.
228     int                     m_crSrcH;          // Height of source chroma planes.
229     int                     m_crDstW;          // Width  of dest chroma planes.
230     int                     m_crDstH;          // Height of dest chroma planes.
231     int                     m_crSrcHSubSample; // Binary log of horizontal subsampling factor between Y and Cr planes in src  image.
232     int                     m_crSrcVSubSample; // Binary log of vertical   subsampling factor between Y and Cr planes in src  image.
233     int                     m_crDstHSubSample; // Binary log of horizontal subsampling factor between Y and Cr planes in dest image.
234     int                     m_crDstVSubSample; // Binary log of vertical   subsampling factor between Y and Cr planes in dest image.
235     ScalerSlice*            m_slices[m_numSlice];
236     ScalerFilter*           m_ScalerFilters[m_numFilter];
237 private:
238     int getLocalPos(int crSubSample, int pos);
239     void getMinBufferSize(int *out_lum_size, int *out_cr_size);
240     int initScalerSlice();
241 public:
242     ScalerFilterManager();
~ScalerFilterManager()243     ~ScalerFilterManager() {
244         for (int i = 0; i < m_numSlice; i++)
245             if (m_slices[i]) { m_slices[i]->destroy(); delete m_slices[i]; m_slices[i] = NULL; }
246         for (int i = 0; i < m_numFilter; i++)
247             if (m_ScalerFilters[i]) { delete m_ScalerFilters[i]; m_ScalerFilters[i] = NULL; }
248     }
249     int init(int algorithmFlags, VideoDesc* srcVideoDesc, VideoDesc* dstVideoDesc);
250     int scale_pic(void** src, void** dst, int* srcStride, int* dstStride);
251 };
252 }
253 
254 #endif //ifndef X265_SCALER_H
255