Browse code

avfilter/vf_rotate: add >8 bit depth support

Signed-off-by: Paul B Mahol <onemda@gmail.com>

Paul B Mahol authored on 2016/06/25 03:16:22
Showing 2 changed files
... ...
@@ -60,7 +60,7 @@ enum var_name {
60 60
     VAR_VARS_NB
61 61
 };
62 62
 
63
-typedef struct {
63
+typedef struct RotContext {
64 64
     const AVClass *class;
65 65
     double angle;
66 66
     char *angle_expr_str;   ///< expression for the angle
... ...
@@ -77,6 +77,9 @@ typedef struct {
77 77
     double var_values[VAR_VARS_NB];
78 78
     FFDrawContext draw;
79 79
     FFDrawColor color;
80
+    uint8_t *(*interpolate_bilinear)(uint8_t *dst_color,
81
+                                    const uint8_t *src, int src_linesize, int src_linestep,
82
+                                    int x, int y, int max_x, int max_y);
80 83
 } RotContext;
81 84
 
82 85
 typedef struct ThreadData {
... ...
@@ -142,6 +145,14 @@ static int query_formats(AVFilterContext *ctx)
142 142
         AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUVJ444P,
143 143
         AV_PIX_FMT_YUV420P,  AV_PIX_FMT_YUVJ420P,
144 144
         AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA420P,
145
+        AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE,
146
+        AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUVA444P10LE,
147
+        AV_PIX_FMT_YUV420P12LE,
148
+        AV_PIX_FMT_YUV444P12LE,
149
+        AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE,
150
+        AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE,
151
+        AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUVA444P9LE,
152
+        AV_PIX_FMT_YUV420P9LE, AV_PIX_FMT_YUVA420P9LE,
145 153
         AV_PIX_FMT_NONE
146 154
     };
147 155
 
... ...
@@ -187,6 +198,93 @@ static const char * const func1_names[] = {
187 187
     NULL
188 188
 };
189 189
 
190
+#define FIXP (1<<16)
191
+#define FIXP2 (1<<20)
192
+#define INT_PI 3294199 //(M_PI * FIXP2)
193
+
194
+/**
195
+ * Compute the sin of a using integer values.
196
+ * Input is scaled by FIXP2 and output values are scaled by FIXP.
197
+ */
198
+static int64_t int_sin(int64_t a)
199
+{
200
+    int64_t a2, res = 0;
201
+    int i;
202
+    if (a < 0) a = INT_PI-a; // 0..inf
203
+    a %= 2 * INT_PI;         // 0..2PI
204
+
205
+    if (a >= INT_PI*3/2) a -= 2*INT_PI;  // -PI/2 .. 3PI/2
206
+    if (a >= INT_PI/2  ) a = INT_PI - a; // -PI/2 ..  PI/2
207
+
208
+    /* compute sin using Taylor series approximated to the fifth term */
209
+    a2 = (a*a)/(FIXP2);
210
+    for (i = 2; i < 11; i += 2) {
211
+        res += a;
212
+        a = -a*a2 / (FIXP2*i*(i+1));
213
+    }
214
+    return (res + 8)>>4;
215
+}
216
+
217
+/**
218
+ * Interpolate the color in src at position x and y using bilinear
219
+ * interpolation.
220
+ */
221
+static uint8_t *interpolate_bilinear8(uint8_t *dst_color,
222
+                                      const uint8_t *src, int src_linesize, int src_linestep,
223
+                                      int x, int y, int max_x, int max_y)
224
+{
225
+    int int_x = av_clip(x>>16, 0, max_x);
226
+    int int_y = av_clip(y>>16, 0, max_y);
227
+    int frac_x = x&0xFFFF;
228
+    int frac_y = y&0xFFFF;
229
+    int i;
230
+    int int_x1 = FFMIN(int_x+1, max_x);
231
+    int int_y1 = FFMIN(int_y+1, max_y);
232
+
233
+    for (i = 0; i < src_linestep; i++) {
234
+        int s00 = src[src_linestep * int_x  + i + src_linesize * int_y ];
235
+        int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ];
236
+        int s10 = src[src_linestep * int_x  + i + src_linesize * int_y1];
237
+        int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1];
238
+        int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01);
239
+        int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11);
240
+
241
+        dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32;
242
+    }
243
+
244
+    return dst_color;
245
+}
246
+
247
+/**
248
+ * Interpolate the color in src at position x and y using bilinear
249
+ * interpolation.
250
+ */
251
+static uint8_t *interpolate_bilinear16(uint8_t *dst_color,
252
+                                       const uint8_t *src, int src_linesize, int src_linestep,
253
+                                       int x, int y, int max_x, int max_y)
254
+{
255
+    int int_x = av_clip(x>>16, 0, max_x);
256
+    int int_y = av_clip(y>>16, 0, max_y);
257
+    int frac_x = x&0xFFFF;
258
+    int frac_y = y&0xFFFF;
259
+    int i;
260
+    int int_x1 = FFMIN(int_x+1, max_x);
261
+    int int_y1 = FFMIN(int_y+1, max_y);
262
+
263
+    for (i = 0; i < src_linestep; i+=2) {
264
+        int s00 = AV_RL16(&src[src_linestep * int_x  + i + src_linesize * int_y ]);
265
+        int s01 = AV_RL16(&src[src_linestep * int_x1 + i + src_linesize * int_y ]);
266
+        int s10 = AV_RL16(&src[src_linestep * int_x  + i + src_linesize * int_y1]);
267
+        int s11 = AV_RL16(&src[src_linestep * int_x1 + i + src_linesize * int_y1]);
268
+        int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01);
269
+        int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11);
270
+
271
+        AV_WL16(&dst_color[i], ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32);
272
+    }
273
+
274
+    return dst_color;
275
+}
276
+
190 277
 static int config_props(AVFilterLink *outlink)
191 278
 {
192 279
     AVFilterContext *ctx = outlink->src;
... ...
@@ -203,6 +301,11 @@ static int config_props(AVFilterLink *outlink)
203 203
     rot->hsub = pixdesc->log2_chroma_w;
204 204
     rot->vsub = pixdesc->log2_chroma_h;
205 205
 
206
+    if (pixdesc->comp[0].depth == 8)
207
+        rot->interpolate_bilinear = interpolate_bilinear8;
208
+    else
209
+        rot->interpolate_bilinear = interpolate_bilinear16;
210
+
206 211
     rot->var_values[VAR_IN_W] = rot->var_values[VAR_IW] = inlink->w;
207 212
     rot->var_values[VAR_IN_H] = rot->var_values[VAR_IH] = inlink->h;
208 213
     rot->var_values[VAR_HSUB] = 1<<rot->hsub;
... ...
@@ -255,63 +358,6 @@ static int config_props(AVFilterLink *outlink)
255 255
     return 0;
256 256
 }
257 257
 
258
-#define FIXP (1<<16)
259
-#define FIXP2 (1<<20)
260
-#define INT_PI 3294199 //(M_PI * FIXP2)
261
-
262
-/**
263
- * Compute the sin of a using integer values.
264
- * Input is scaled by FIXP2 and output values are scaled by FIXP.
265
- */
266
-static int64_t int_sin(int64_t a)
267
-{
268
-    int64_t a2, res = 0;
269
-    int i;
270
-    if (a < 0) a = INT_PI-a; // 0..inf
271
-    a %= 2 * INT_PI;         // 0..2PI
272
-
273
-    if (a >= INT_PI*3/2) a -= 2*INT_PI;  // -PI/2 .. 3PI/2
274
-    if (a >= INT_PI/2  ) a = INT_PI - a; // -PI/2 ..  PI/2
275
-
276
-    /* compute sin using Taylor series approximated to the fifth term */
277
-    a2 = (a*a)/(FIXP2);
278
-    for (i = 2; i < 11; i += 2) {
279
-        res += a;
280
-        a = -a*a2 / (FIXP2*i*(i+1));
281
-    }
282
-    return (res + 8)>>4;
283
-}
284
-
285
-/**
286
- * Interpolate the color in src at position x and y using bilinear
287
- * interpolation.
288
- */
289
-static uint8_t *interpolate_bilinear(uint8_t *dst_color,
290
-                                     const uint8_t *src, int src_linesize, int src_linestep,
291
-                                     int x, int y, int max_x, int max_y)
292
-{
293
-    int int_x = av_clip(x>>16, 0, max_x);
294
-    int int_y = av_clip(y>>16, 0, max_y);
295
-    int frac_x = x&0xFFFF;
296
-    int frac_y = y&0xFFFF;
297
-    int i;
298
-    int int_x1 = FFMIN(int_x+1, max_x);
299
-    int int_y1 = FFMIN(int_y+1, max_y);
300
-
301
-    for (i = 0; i < src_linestep; i++) {
302
-        int s00 = src[src_linestep * int_x  + i + src_linesize * int_y ];
303
-        int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ];
304
-        int s10 = src[src_linestep * int_x  + i + src_linesize * int_y1];
305
-        int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1];
306
-        int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01);
307
-        int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11);
308
-
309
-        dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32;
310
-    }
311
-
312
-    return dst_color;
313
-}
314
-
315 258
 static av_always_inline void copy_elem(uint8_t *pout, const uint8_t *pin, int elem_size)
316 259
 {
317 260
     int v;
... ...
@@ -421,9 +467,9 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
421 421
                 uint8_t inp_inv[4]; /* interpolated input value */
422 422
                 pout = out->data[plane] + j * out->linesize[plane] + i * rot->draw.pixelstep[plane];
423 423
                 if (rot->use_bilinear) {
424
-                    pin = interpolate_bilinear(inp_inv,
425
-                                               in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane],
426
-                                               x, y, inw-1, inh-1);
424
+                    pin = rot->interpolate_bilinear(inp_inv,
425
+                                                    in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane],
426
+                                                    x, y, inw-1, inh-1);
427 427
                 } else {
428 428
                     int x2 = av_clip(x1, 0, inw-1);
429 429
                     int y2 = av_clip(y1, 0, inh-1);
... ...
@@ -434,7 +480,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
434 434
                     *pout = *pin;
435 435
                     break;
436 436
                 case 2:
437
-                    *((uint16_t *)pout) = *((uint16_t *)pin);
437
+                    v = AV_RL16(pin);
438
+                    AV_WL16(pout, v);
438 439
                     break;
439 440
                 case 3:
440 441
                     v = AV_RB24(pin);
... ...
@@ -13,8 +13,22 @@ rgb24               f4438057d046e6d98ade4e45294b21be
13 13
 rgba                b6e1b441c365e03b5ffdf9b7b68d9a0c
14 14
 yuv410p             5d4d992a7728431aa4e0700f87fb7fd8
15 15
 yuv420p             a014c7eb7a8385d1dd092b7a583f1bff
16
+yuv420p10le         15c83294ef560d57f25d16ae6e0fc70c
17
+yuv420p12le         c19a477a07fcf88e37ab37b416d064c0
18
+yuv420p16le         dae8da9edd4255051e3e546ae7ed9bd3
19
+yuv420p9le          83a6d32c91c15a3bc334bb9abf920654
16 20
 yuv444p             8f90fb3a757878c545a8bfe5d19a9bab
21
+yuv444p10le         6d736fa464ff2de2b07e0a56af8444b7
22
+yuv444p12le         08a81b2ea9c7c8b447e40ef8f4a46a4a
23
+yuv444p16le         781c22317c02b3dd4225709000bdb847
24
+yuv444p9le          caef947b8aff5b52285385c6ae9b2439
17 25
 yuva420p            b227672e56215e184e702c02a771d7f3
26
+yuva420p10le        01e94ee605714396e69b013c11dda348
27
+yuva420p16le        b1930ab28ffe031c78ca28d3406311c8
28
+yuva420p9le         0e9c9803aaaddc9f38e419de587793c2
18 29
 yuva444p            459fad5abfd16db9bb6a52761dc74cc1
30
+yuva444p10le        92f820d3481b7ebcb48b98a73e7b4c90
31
+yuva444p16le        2ed56ea50fafda4d226c9b133755dad8
32
+yuva444p9le         4eeb5988df0740fea720da1e31bbb829
19 33
 yuvj420p            8f3d8f1b4577d11082d5ab8a901e048d
20 34
 yuvj444p            b161e6d5a941e2a4bb7bc56ef8af623f