AJA NTV2 SDK  17.5.0.1242
NTV2 SDK 17.5.0.1242
ntv2resample.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2resample.h"
9 
10 inline RGBAlphaPixel CubicInterPolate( RGBAlphaPixel *Input, LWord Index);
11 inline Word CubicInterPolateWord( Word *Input, Fixed_ Index);
12 inline Word CubicInterPolateAudioWord( Word *Input, Fixed_ Index);
13 
14 // Cubic Coefficient Table for resampling
15 static unsigned int CubicCoef[129] = {
16  0x00000000 , /* 0 */
17  0xFFFFFFE1 , /* 1 */
18  0xFFFFFF88 , /* 2 */
19  0xFFFFFEFB , /* 3 */
20  0xFFFFFE40 , /* 4 */
21  0xFFFFFD5D , /* 5 */
22  0xFFFFFC58 , /* 6 */
23  0xFFFFFB37 , /* 7 */
24  0xFFFFFA00 , /* 8 */
25  0xFFFFF8B9 , /* 9 */
26  0xFFFFF768 , /* 10 */
27  0xFFFFF613 , /* 11 */
28  0xFFFFF4C0 , /* 12 */
29  0xFFFFF375 , /* 13 */
30  0xFFFFF238 , /* 14 */
31  0xFFFFF10F , /* 15 */
32  0xFFFFF000 , /* 16 */
33  0xFFFFEF11 , /* 17 */
34  0xFFFFEE48 , /* 18 */
35  0xFFFFEDAB , /* 19 */
36  0xFFFFED40 , /* 20 */
37  0xFFFFED0D , /* 21 */
38  0xFFFFED18 , /* 22 */
39  0xFFFFED67 , /* 23 */
40  0xFFFFEE00 , /* 24 */
41  0xFFFFEEE9 , /* 25 */
42  0xFFFFF028 , /* 26 */
43  0xFFFFF1C3 , /* 27 */
44  0xFFFFF3C0 , /* 28 */
45  0xFFFFF625 , /* 29 */
46  0xFFFFF8F8 , /* 30 */
47  0xFFFFFC3F , /* 31 */
48  0x00000000 , /* 32 */
49  0x0000047D , /* 33 */
50  0x000009E8 , /* 34 */
51  0x0000102F , /* 35 */
52  0x00001740 , /* 36 */
53  0x00001F09 , /* 37 */
54  0x00002778 , /* 38 */
55  0x0000307B , /* 39 */
56  0x00003A00 , /* 40 */
57  0x000043F5 , /* 41 */
58  0x00004E48 , /* 42 */
59  0x000058E7 , /* 43 */
60  0x000063C0 , /* 44 */
61  0x00006EC1 , /* 45 */
62  0x000079D8 , /* 46 */
63  0x000084F3 , /* 47 */
64  0x00009000 , /* 48 */
65  0x00009AED , /* 49 */
66  0x0000A5A8 , /* 50 */
67  0x0000B01F , /* 51 */
68  0x0000BA40 , /* 52 */
69  0x0000C3F9 , /* 53 */
70  0x0000CD38 , /* 54 */
71  0x0000D5EB , /* 55 */
72  0x0000DE00 , /* 56 */
73  0x0000E565 , /* 57 */
74  0x0000EC08 , /* 58 */
75  0x0000F1D7 , /* 59 */
76  0x0000F6C0 , /* 60 */
77  0x0000FAB1 , /* 61 */
78  0x0000FD98 , /* 62 */
79  0x0000FF63 , /* 63 */
80  0x00010000 , /* 64 */
81  0x0000FF63 , /* 65 */
82  0x0000FD98 , /* 66 */
83  0x0000FAB1 , /* 67 */
84  0x0000F6C0 , /* 68 */
85  0x0000F1D7 , /* 69 */
86  0x0000EC08 , /* 70 */
87  0x0000E565 , /* 71 */
88  0x0000DE00 , /* 72 */
89  0x0000D5EB , /* 73 */
90  0x0000CD38 , /* 74 */
91  0x0000C3F9 , /* 75 */
92  0x0000BA40 , /* 76 */
93  0x0000B01F , /* 77 */
94  0x0000A5A8 , /* 78 */
95  0x00009AED , /* 79 */
96  0x00009000 , /* 80 */
97  0x000084F3 , /* 81 */
98  0x000079D8 , /* 82 */
99  0x00006EC1 , /* 83 */
100  0x000063C0 , /* 84 */
101  0x000058E7 , /* 85 */
102  0x00004E48 , /* 86 */
103  0x000043F5 , /* 87 */
104  0x00003A00 , /* 88 */
105  0x0000307B , /* 89 */
106  0x00002778 , /* 90 */
107  0x00001F09 , /* 91 */
108  0x00001740 , /* 92 */
109  0x0000102F , /* 93 */
110  0x000009E8 , /* 94 */
111  0x0000047D , /* 95 */
112  0x00000000 , /* 96 */
113  0xFFFFFC3F , /* 97 */
114  0xFFFFF8F8 , /* 98 */
115  0xFFFFF625 , /* 99 */
116  0xFFFFF3C0 , /* 100 */
117  0xFFFFF1C3 , /* 101 */
118  0xFFFFF028 , /* 102 */
119  0xFFFFEEE9 , /* 103 */
120  0xFFFFEE00 , /* 104 */
121  0xFFFFED67 , /* 105 */
122  0xFFFFED18 , /* 106 */
123  0xFFFFED0D , /* 107 */
124  0xFFFFED40 , /* 108 */
125  0xFFFFEDAB , /* 109 */
126  0xFFFFEE48 , /* 110 */
127  0xFFFFEF11 , /* 111 */
128  0xFFFFF000 , /* 112 */
129  0xFFFFF10F , /* 113 */
130  0xFFFFF238 , /* 114 */
131  0xFFFFF375 , /* 115 */
132  0xFFFFF4C0 , /* 116 */
133  0xFFFFF613 , /* 117 */
134  0xFFFFF768 , /* 118 */
135  0xFFFFF8B9 , /* 119 */
136  0xFFFFFA00 , /* 120 */
137  0xFFFFFB37 , /* 121 */
138  0xFFFFFC58 , /* 122 */
139  0xFFFFFD5D , /* 123 */
140  0xFFFFFE40 , /* 124 */
141  0xFFFFFEFB , /* 125 */
142  0xFFFFFF88 , /* 126 */
143  0xFFFFFFE1 , /* 127 */
144  0x00000000 , /* 128 */
145 };
146 
147 
148 
149 // ReSampleLine
150 // RGBAlphaPixel Version
151 // NOTE: Input buffer needs to have extra sample at start and 2 at end.
153  RGBAlphaPixel *Output,
154  UWord startPixel,
155  UWord endPixel,
156  LWord numInputPixels,
157  LWord numOutputPixels)
158 
159 {
160  LWord count,inputIndex,reSampleStartPixel,reSampleEndPixel;
161  Fixed_ accum = 0;
162  Fixed_ increment,coefIndex;
163 
164  Input[-1] = Input[0];
165  Input[numInputPixels] = Input[numInputPixels+1] = Input[numInputPixels-1];
166 
167  increment = (numInputPixels<<16)/numOutputPixels;
168  reSampleStartPixel = (startPixel*numOutputPixels)/numInputPixels;
169  reSampleEndPixel = (endPixel*numOutputPixels)/numInputPixels;
170  for ( count = reSampleStartPixel; count < reSampleEndPixel; count++ )
171  {
172  accum = (increment*count);
173  inputIndex = FixedTrunc(accum);
174  coefIndex = (accum>>11) & 0x1F;
175  Output[count] = CubicInterPolate(&Input[inputIndex],coefIndex);
176  }
177 
178 }
179 
180 
181 // ReSampleLine
182 // Word Version
183 // NOTE: Input buffer needs to have extra sample at start and 2 at end.
184 void ReSampleLine(Word *Input,
185  Word *Output,
186  UWord startPixel,
187  UWord endPixel,
188  LWord numInputPixels,
189  LWord numOutputPixels)
190 
191 {
192  LWord count,inputIndex,reSampleStartPixel,reSampleEndPixel;
193  Fixed_ accum = 0;
194  Fixed_ increment,coefIndex;
195 
196  Input[-1] = Input[0];
197  Input[numInputPixels] = Input[numInputPixels+1] = Input[numInputPixels-1];
198 
199  increment = (numInputPixels<<16)/numOutputPixels;
200  reSampleStartPixel = (startPixel*numOutputPixels)/numInputPixels;
201  reSampleEndPixel = (endPixel*numOutputPixels)/numInputPixels;
202  for ( count = reSampleStartPixel; count < reSampleEndPixel; count++ )
203  {
204  accum = (increment*count);
205  inputIndex = FixedTrunc(accum);
206  coefIndex = (accum>>11) & 0x1F;
207  Output[count] = (Word)CubicInterPolateWord((Word *)&Input[inputIndex],coefIndex);
208  }
209 
210 }
211 #define MIN_YCBCR_10BIT 4
212 #define MAX_YCBCR_10BIT 1019
213 #define ClipYCbCr_10BIT(X) ((X) > MAX_YCBCR_10BIT ? (MAX_YCBCR_10BIT) : ((X) < MIN_YCBCR_10BIT ? (MIN_YCBCR_10BIT) : (X)))
214 
215 // ReSampleLine
216 // Word Version
218  Word *Output,
219  LWord numInputPixels,
220  LWord numOutputPixels)
221 
222 {
223  LWord count,inputIndex,reSampleStartPixel,reSampleEndPixel;
224  Fixed_ accum = 0;
225  Fixed_ increment,coefIndex;
226 
227  Word* yBuffer = new Word[numInputPixels+4];
228  Word* cbBuffer = new Word[numInputPixels/2+4];
229  Word* crBuffer = new Word[numInputPixels/2+4];
230 
231  // First Extract Y
232  for ( count = 0; count < numInputPixels; count++ )
233  {
234  if ( count & 0x1)
235  {
236  crBuffer[count/2+1] = Input[count*2];
237  }
238  else
239  {
240  cbBuffer[count/2+1] = Input[count*2];
241 
242  }
243  yBuffer[count+1] = Input[count*2+1];
244  }
245 
246  yBuffer[0] = yBuffer[1];
247  yBuffer[numInputPixels+1] = yBuffer[numInputPixels+2] = yBuffer[numInputPixels];
248 
249  increment = (numInputPixels<<16)/numOutputPixels;
250  reSampleStartPixel = 0;
251  reSampleEndPixel = numOutputPixels;
252  for ( count = reSampleStartPixel; count < reSampleEndPixel; count++ )
253  {
254  accum = (increment*count);
255  inputIndex = FixedTrunc(accum);
256  coefIndex = (accum>>11) & 0x1F;
257  Output[count*2+1] = (Word)CubicInterPolateWord((Word *)&yBuffer[inputIndex+1],coefIndex);
258  }
259 
260  reSampleStartPixel = 0;
261  reSampleEndPixel = numOutputPixels/2;
262  cbBuffer[0] = cbBuffer[1];
263  cbBuffer[numInputPixels/2+1] = cbBuffer[numInputPixels/2+2] = cbBuffer[numInputPixels/2];
264  crBuffer[0] = crBuffer[1];
265  crBuffer[numInputPixels/2+1] = crBuffer[numInputPixels/2+2] = crBuffer[numInputPixels/2];
266 
267  for ( count = reSampleStartPixel; count < reSampleEndPixel; count++ )
268  {
269  accum = (increment*count);
270  inputIndex = FixedTrunc(accum);
271  coefIndex = (accum>>11) & 0x1F;
272  Output[count*4] = (Word)CubicInterPolateWord((Word *)&cbBuffer[inputIndex+1],coefIndex);
273  Output[count*4+2] = (Word)CubicInterPolateWord((Word *)&crBuffer[inputIndex+1],coefIndex);
274  }
275 
276  delete [] yBuffer;
277  delete [] cbBuffer;
278  delete [] crBuffer;
279 }
280 
281 
282 void ReSampleAudio(Word *Input,
283  Word *Output,
284  UWord startPixel,
285  UWord endPixel,
286  LWord numInputPixels,
287  LWord numOutputPixels,
288  Word channelInterleaveMulitplier)
289 {
290  LWord count,inputIndex,reSampleStartPixel,reSampleEndPixel;
291  Fixed_ accum = 0;
292  Fixed_ increment,coefIndex;
293 
294  increment = (numInputPixels<<16)/numOutputPixels;
295  reSampleStartPixel = (startPixel*numOutputPixels)/numInputPixels;
296  reSampleEndPixel = (endPixel*numOutputPixels)/numInputPixels;
297  for ( count = reSampleStartPixel; count < reSampleEndPixel; count++ )
298  {
299  accum = (increment*count);
300  inputIndex = FixedTrunc(accum);
301  coefIndex = (accum>>11) & 0x1F;
302  Output[count*channelInterleaveMulitplier] = (Word)CubicInterPolateAudioWord((Word *)&Input[inputIndex],coefIndex);
303  }
304 
305 
306 }
307 inline Word CubicInterPolateWord( Word *Input, Fixed_ Index)
308 {
309  LWord InterPolatedValue;
310 
311  InterPolatedValue = FixedTrunc(Input[-1]*CubicCoef[32-Index] +
312  Input[0]*CubicCoef[64-Index] +
313  Input[1]*CubicCoef[96-Index] +
314  Input[2]*CubicCoef[128-Index]);
315 
316  // return (Word)(InterPolatedValue&0x3FF);
317  return (Word)ClipYCbCr_10BIT(InterPolatedValue);
318 }
319 
321 {
322  LWord InterPolatedValue;
323 
324  InterPolatedValue = FixedTrunc(Input[-1]*CubicCoef[32-Index] +
325  Input[0]*CubicCoef[64-Index] +
326  Input[1]*CubicCoef[96-Index] +
327  Input[2]*CubicCoef[128-Index]);
328 
329  if ( InterPolatedValue > 32767 )
330  InterPolatedValue = 32767;
331  if ( InterPolatedValue < -32767 )
332  InterPolatedValue = -32767;
333 
334  return (Word)(InterPolatedValue&0xFFFF);
335 }
336 
338 {
339 
340  RGBAlphaPixel InterPolatedValue;
341  LWord temp;
342 
343 
344  temp = FixedTrunc(Input[-1].Red*CubicCoef[32-Index] +
345  Input[0].Red*CubicCoef[64-Index] +
346  Input[1].Red*CubicCoef[96-Index] +
347  Input[2].Red*CubicCoef[128-Index]);
348 
349  InterPolatedValue.Red = (UByte)((temp < 0 ) ? 0 : (temp > 255 ) ? 255 : temp);
350 
351  temp= FixedTrunc(Input[-1].Green*CubicCoef[32-Index] +
352  Input[0].Green*CubicCoef[64-Index] +
353  Input[1].Green*CubicCoef[96-Index] +
354  Input[2].Green*CubicCoef[128-Index]);
355  InterPolatedValue.Green = (UByte)((temp < 0 ) ? 0 : (temp > 255 ) ? 255 : temp);
356 
357 
358  temp = FixedTrunc(Input[-1].Blue*CubicCoef[32-Index] +
359  Input[0].Blue*CubicCoef[64-Index] +
360  Input[1].Blue*CubicCoef[96-Index] +
361  Input[2].Blue*CubicCoef[128-Index]);
362 
363  InterPolatedValue.Blue = (UByte)((temp < 0 ) ? 0 : (temp > 255 ) ? 255 : temp);
364 
365  temp = FixedTrunc(Input[-1].Alpha*CubicCoef[32-Index] +
366  Input[0].Alpha*CubicCoef[64-Index] +
367  Input[1].Alpha*CubicCoef[96-Index] +
368  Input[2].Alpha*CubicCoef[128-Index]);
369 
370  InterPolatedValue.Alpha = (UByte)((temp < 0 ) ? 0 : (temp > 255 ) ? 255 : temp);
371 
372  return InterPolatedValue;
373 
374 }
375 
376 
377 
LWord
int32_t LWord
Definition: ajatypes.h:254
RGBAlphaPixel::Alpha
unsigned char Alpha
Definition: ntv2videodefines.h:141
RGBAlphaPixel::Red
unsigned char Red
Definition: ntv2videodefines.h:140
ReSampleAudio
void ReSampleAudio(Word *Input, Word *Output, UWord startPixel, UWord endPixel, LWord numInputPixels, LWord numOutputPixels, Word channelInterleaveMulitplier)
Definition: ntv2resample.cpp:282
RGBAlphaPixel::Green
unsigned char Green
Definition: ntv2videodefines.h:139
ReSampleYCbCrSampleLine
void ReSampleYCbCrSampleLine(Word *Input, Word *Output, LWord numInputPixels, LWord numOutputPixels)
Definition: ntv2resample.cpp:217
CubicInterPolate
RGBAlphaPixel CubicInterPolate(RGBAlphaPixel *Input, LWord Index)
Definition: ntv2resample.cpp:337
CubicCoef
static unsigned int CubicCoef[129]
Definition: ntv2resample.cpp:15
CubicInterPolateAudioWord
Word CubicInterPolateAudioWord(Word *Input, Fixed_ Index)
Definition: ntv2resample.cpp:320
ReSampleLine
void ReSampleLine(RGBAlphaPixel *Input, RGBAlphaPixel *Output, UWord startPixel, UWord endPixel, LWord numInputPixels, LWord numOutputPixels)
Definition: ntv2resample.cpp:152
UWord
uint16_t UWord
Definition: ajatypes.h:253
Word
int16_t Word
Definition: ajatypes.h:252
CubicInterPolateWord
Word CubicInterPolateWord(Word *Input, Fixed_ Index)
Definition: ntv2resample.cpp:307
FixedTrunc
int FixedTrunc(int inFix)
Definition: videoutilities.cpp:13
UByte
uint8_t UByte
Definition: ajatypes.h:250
RGBAlphaPixel::Blue
unsigned char Blue
Definition: ntv2videodefines.h:138
ClipYCbCr_10BIT
#define ClipYCbCr_10BIT(X)
Definition: ntv2resample.cpp:213
ntv2resample.h
Declares a number of pixel resampling functions.
RGBAlphaPixel
Definition: ntv2videodefines.h:137
Fixed_
int Fixed_
Definition: ajatypes.h:321