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