Browse code

swscale/arm: add ff_nv{12,21}_to_{argb,rgba,abgr,bgra}_neon_16

Matthieu Bouron authored on 2015/12/07 21:56:25
Showing 2 changed files
... ...
@@ -63,8 +63,8 @@ static int rgbx_to_nv12_neon_16_wrapper(SwsContext *context, const uint8_t *src[
63 63
 }
64 64
 #endif
65 65
 
66
-#define DECLARE_FF_NVX_TO_RGBX_FUNCS(ifmt, ofmt)                                            \
67
-int ff_##ifmt##_to_##ofmt##_neon(int w, int h,                                              \
66
+#define DECLARE_FF_NVX_TO_RGBX_FUNCS(ifmt, ofmt, precision)                                 \
67
+int ff_##ifmt##_to_##ofmt##_neon_##precision(int w, int h,                                  \
68 68
                                  uint8_t *dst, int linesize,                                \
69 69
                                  const uint8_t *srcY, int linesizeY,                        \
70 70
                                  const uint8_t *srcC, int linesizeC,                        \
... ...
@@ -72,59 +72,64 @@ int ff_##ifmt##_to_##ofmt##_neon(int w, int h,
72 72
                                  int y_offset,                                              \
73 73
                                  int y_coeff);                                              \
74 74
                                                                                             \
75
-static int ifmt##_to_##ofmt##_neon_wrapper(SwsContext *c, const uint8_t *src[],             \
75
+static int ifmt##_to_##ofmt##_neon_wrapper_##precision(SwsContext *c, const uint8_t *src[], \
76 76
                                            int srcStride[], int srcSliceY, int srcSliceH,   \
77 77
                                            uint8_t *dst[], int dstStride[]) {               \
78 78
     const int16_t yuv2rgb_table[] = {                                                       \
79
-        c->yuv2rgb_v2r_coeff,                                                               \
80
-        c->yuv2rgb_u2g_coeff,                                                               \
81
-        c->yuv2rgb_v2g_coeff,                                                               \
82
-        c->yuv2rgb_u2b_coeff,                                                               \
79
+        c->yuv2rgb_v2r_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
80
+        c->yuv2rgb_u2g_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
81
+        c->yuv2rgb_v2g_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
82
+        c->yuv2rgb_u2b_coeff / ((precision) == 16 ? 1 << 7 : 1),                            \
83 83
     };                                                                                      \
84 84
                                                                                             \
85
-    ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH,                                        \
85
+    ff_##ifmt##_to_##ofmt##_neon_##precision(c->srcW, srcSliceH,                            \
86 86
                                  dst[0] +  srcSliceY      * dstStride[0], dstStride[0],     \
87 87
                                  src[0] +  srcSliceY      * srcStride[0], srcStride[0],     \
88 88
                                  src[1] + (srcSliceY / 2) * srcStride[1], srcStride[1],     \
89 89
                                  yuv2rgb_table,                                             \
90 90
                                  c->yuv2rgb_y_offset >> 9,                                  \
91
-                                 c->yuv2rgb_y_coeff);                                       \
91
+                                 c->yuv2rgb_y_coeff / ((precision) == 16 ? 1 << 7 : 1));    \
92 92
                                                                                             \
93 93
     return 0;                                                                               \
94
-}
94
+}                                                                                           \
95
+
96
+#define DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx, precision)                                    \
97
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, argb, precision)                                          \
98
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, rgba, precision)                                          \
99
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, abgr, precision)                                          \
100
+DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, bgra, precision)                                          \
95 101
 
96
-#define DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx)                                               \
97
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, argb)                                                     \
98
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, rgba)                                                     \
99
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, abgr)                                                     \
100
-DECLARE_FF_NVX_TO_RGBX_FUNCS(nvx, bgra)                                                     \
102
+#define DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nvx)                                 \
103
+DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx, 16)                                                   \
104
+DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nvx, 32)                                                   \
101 105
 
102
-DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv12)
103
-DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21)
106
+DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nv12)
107
+DECLARE_FF_NVX_TO_ALL_RGBX_ALL_PRECISION_FUNCS(nv21)
104 108
 
105 109
 /* We need a 16 pixel width alignment. This constraint can easily be removed
106 110
  * for input reading but for the output which is 4-bytes per pixel (RGBA) the
107 111
  * assembly might be writing as much as 4*15=60 extra bytes at the end of the
108 112
  * line, which won't fit the 32-bytes buffer alignment. */
109
-#define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT) do {                                \
113
+#define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT, accurate_rnd) do {                  \
110 114
     if (c->srcFormat == AV_PIX_FMT_##IFMT                                                   \
111 115
         && c->dstFormat == AV_PIX_FMT_##OFMT                                                \
112 116
         && !(c->srcH & 1)                                                                   \
113 117
         && !(c->srcW & 15)) {                                                               \
114
-        c->swscale = ifmt##_to_##ofmt##_neon_wrapper;                                       \
118
+        c->swscale = (accurate_rnd) ? ifmt##_to_##ofmt##_neon_wrapper_32 :                  \
119
+                                      ifmt##_to_##ofmt##_neon_wrapper_16 ;                  \
115 120
     }                                                                                       \
116 121
 } while (0)
117 122
 
118
-#define SET_FF_NVX_TO_ALL_RGBX_FUNC(nvx, NVX) do {                                          \
119
-    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, argb, ARGB);                                          \
120
-    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, rgba, RGBA);                                          \
121
-    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, abgr, ABGR);                                          \
122
-    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, bgra, BGRA);                                          \
123
+#define SET_FF_NVX_TO_ALL_RGBX_FUNC(nvx, NVX, accurate_rnd) do {                            \
124
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, argb, ARGB, accurate_rnd);                            \
125
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, rgba, RGBA, accurate_rnd);                            \
126
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, abgr, ABGR, accurate_rnd);                            \
127
+    SET_FF_NVX_TO_RGBX_FUNC(nvx, NVX, bgra, BGRA, accurate_rnd);                            \
123 128
 } while (0)
124 129
 
125 130
 static void get_unscaled_swscale_neon(SwsContext *c) {
126
-#if 0
127 131
     int accurate_rnd = c->flags & SWS_ACCURATE_RND;
132
+#if 0
128 133
     if (c->srcFormat == AV_PIX_FMT_RGBA
129 134
             && c->dstFormat == AV_PIX_FMT_NV12
130 135
             && (c->srcW >= 16)) {
... ...
@@ -133,8 +138,8 @@ static void get_unscaled_swscale_neon(SwsContext *c) {
133 133
     }
134 134
 #endif
135 135
 
136
-    SET_FF_NVX_TO_ALL_RGBX_FUNC(nv12, NV12);
137
-    SET_FF_NVX_TO_ALL_RGBX_FUNC(nv21, NV21);
136
+    SET_FF_NVX_TO_ALL_RGBX_FUNC(nv12, NV12, accurate_rnd);
137
+    SET_FF_NVX_TO_ALL_RGBX_FUNC(nv21, NV21, accurate_rnd);
138 138
 }
139 139
 
140 140
 void ff_get_unscaled_swscale_arm(SwsContext *c)
... ...
@@ -21,7 +21,35 @@
21 21
 
22 22
 #include "libavutil/arm/asm.S"
23 23
 
24
-.macro compute_premult half_u half_v
24
+
25
+.macro compute_premult_16 half_u1, half_u2, half_v1, half_v2
26
+    vmov                d2, \half_u1                                   @ copy left q14 to left q1
27
+    vmov                d3, \half_u1                                   @ copy left q14 to right q1
28
+    vmov                d4, \half_u2                                   @ copy right q14 to left q2
29
+    vmov                d5, \half_u2                                   @ copy right q14 to right q2
30
+
31
+    vmov                d6, \half_v1                                   @ copy left q15 to left q3
32
+    vmov                d7, \half_v1                                   @ copy left q15 to right q3
33
+    vmov                d8, \half_v2                                   @ copy right q15 to left q4
34
+    vmov                d9, \half_v2                                   @ copy right q15 to right q4
35
+
36
+    vzip.16             d2, d3                                         @ U1U1U2U2U3U3U4U4
37
+    vzip.16             d4, d5                                         @ U5U5U6U6U7U7U8U8
38
+
39
+    vzip.16             d6, d7                                         @ V1V1V2V2V3V3V4V4
40
+    vzip.16             d8, d9                                         @ V5V5V6V6V7V7V8V8
41
+
42
+    vmul.s16            q8,  q3, d1[0]                                 @  V * v2r             (left,  red)
43
+    vmul.s16            q9,  q4, d1[0]                                 @  V * v2r             (right, red)
44
+    vmul.s16            q10, q1, d1[1]                                 @  U * u2g
45
+    vmul.s16            q11, q2, d1[1]                                 @  U * u2g
46
+    vmla.s16            q10, q3, d1[2]                                 @  U * u2g + V * v2g   (left,  green)
47
+    vmla.s16            q11, q4, d1[2]                                 @  U * u2g + V * v2g   (right, green)
48
+    vmul.s16            q12, q1, d1[3]                                 @  U * u2b             (left,  blue)
49
+    vmul.s16            q13, q2, d1[3]                                 @  U * u2b             (right, blue)
50
+.endm
51
+
52
+.macro compute_premult_32 half_u half_v
25 53
     vmov                d2, \half_u                                    @ copy left q14 to left q1
26 54
     vmov                d3, \half_u                                    @ copy left q14 to right q1
27 55
     vmov                d4, \half_v                                    @ copy left q15 to left q2
... ...
@@ -40,7 +68,14 @@
40 40
     vmull.s16           q13, d3, d1[3]                                 @  U * u2b             (right, blue)
41 41
 .endm
42 42
 
43
-.macro compute_color dst_comp pre1 pre2
43
+.macro compute_color_16 dst_comp1 dst_comp2 pre1 pre2
44
+    vadd.s16            q1, q14, \pre1
45
+    vadd.s16            q2, q15, \pre2
46
+    vqrshrun.s16        \dst_comp1, q1, #6
47
+    vqrshrun.s16        \dst_comp2, q2, #6
48
+.endm
49
+
50
+.macro compute_color_32 dst_comp pre1 pre2
44 51
     vadd.s32            q3, q1, \pre1
45 52
     vadd.s32            q4, q2, \pre2
46 53
     vqrshrun.s32        d10, q3, #13
... ...
@@ -48,14 +83,56 @@
48 48
     vqmovn.u16          \dst_comp, q5                                  @ saturate 16bit -> 8bit
49 49
 .endm
50 50
 
51
-.macro compute_rgba r g b a
52
-    compute_color       \r, q8,  q9
53
-    compute_color       \g, q10, q11
54
-    compute_color       \b, q12, q13
51
+.macro compute_rgba_16 r1 r2 g1 g2 b1 b2 a1 a2
52
+    compute_color_16    \r1, \r2, q8,  q9
53
+    compute_color_16    \g1, \g2, q10, q11
54
+    compute_color_16    \b1, \b2, q12, q13
55
+    vmov.u8             \a1, #255
56
+    vmov.u8             \a2, #255
57
+.endm
58
+
59
+.macro compute_rgba_32 r g b a
60
+    compute_color_32    \r, q8,  q9
61
+    compute_color_32    \g, q10, q11
62
+    compute_color_32    \b, q12, q13
55 63
     vmov.u8             \a, #255
56 64
 .endm
57 65
 
58
-.macro compute_half_line dst half_y ofmt
66
+.macro compute_16px_16 dst y0 y1 ofmt
67
+    vmovl.u8            q14, \y0                                       @ 8px of y
68
+    vmovl.u8            q15, \y1                                       @ 8px of y
69
+
70
+    vdup.16             q5, r9                                         @ q5  = y_offset
71
+    vdup.16             q7, r10                                        @ q7  = y_coeff
72
+
73
+    vsub.s16            q14, q5
74
+    vsub.s16            q15, q5
75
+
76
+    vmul.s16            q14, q7                                        @ q14 = (srcY - y_offset) * y_coeff (left)
77
+    vmul.s16            q15, q7                                        @ q15 = (srcY - y_offset) * y_coeff (right)
78
+
79
+
80
+.ifc \ofmt,argb
81
+    compute_rgba_16     d7, d11, d8, d12, d9, d13, d6, d10
82
+.endif
83
+
84
+.ifc \ofmt,rgba
85
+    compute_rgba_16     d6, d10, d7, d11, d8, d12, d9, d13
86
+.endif
87
+
88
+.ifc \ofmt,abgr
89
+    compute_rgba_16     d9, d13, d8, d12, d7, d11, d6, d10
90
+.endif
91
+
92
+.ifc \ofmt,bgra
93
+    compute_rgba_16     d8, d12, d7, d11, d6, d10, d9, d13
94
+.endif
95
+    vst4.8              {q3, q4}, [\dst,:128]!
96
+    vst4.8              {q5, q6}, [\dst,:128]!
97
+
98
+.endm
99
+
100
+.macro compute_8px_32 dst half_y ofmt
59 101
     vmovl.u8            q7, \half_y                                    @ 8px of Y
60 102
     vdup.16             q5, r9
61 103
     vsub.s16            q7, q5
... ...
@@ -63,26 +140,51 @@
63 63
     vmull.s16           q2, d15, d0                                    @ q2 = (srcY - y_offset) * y_coeff (right)
64 64
 
65 65
 .ifc \ofmt,argb
66
-    compute_rgba        d13, d14, d15, d12
66
+    compute_rgba_32     d13, d14, d15, d12
67 67
 .endif
68 68
 
69 69
 .ifc \ofmt,rgba
70
-    compute_rgba        d12, d13, d14, d15
70
+    compute_rgba_32     d12, d13, d14, d15
71 71
 .endif
72 72
 
73 73
 .ifc \ofmt,abgr
74
-    compute_rgba        d15, d14, d13, d12
74
+    compute_rgba_32     d15, d14, d13, d12
75 75
 .endif
76 76
 
77 77
 .ifc \ofmt,bgra
78
-    compute_rgba        d14, d13, d12, d15
78
+    compute_rgba_32     d14, d13, d12, d15
79 79
 .endif
80 80
 
81 81
     vst4.8              {q6, q7}, [\dst,:128]!
82 82
 .endm
83 83
 
84
-.macro declare_func ifmt ofmt
85
-function ff_\ifmt\()_to_\ofmt\()_neon, export=1
84
+.macro process_16px_16 ofmt
85
+    compute_premult_16  d28, d29, d30, d31
86
+
87
+    vld1.8              {q7}, [r4]!                                    @ first line of luma
88
+    compute_16px_16     r2, d14, d15, \ofmt
89
+
90
+    vld1.8              {q7}, [r12]!                                   @ second line of luma
91
+    compute_16px_16     r11, d14, d15, \ofmt
92
+.endm
93
+
94
+.macro process_16px_32 ofmt
95
+    compute_premult_32  d28, d30
96
+
97
+    vld1.8              {q7}, [r4]!                                    @ first line of luma
98
+    vmov                d28, d15                                       @ save right of the first line of luma for later use
99
+    compute_8px_32      r2, d14, \ofmt
100
+
101
+    vld1.8              {q7}, [r12]!                                   @ second line of luma
102
+    vmov                d30, d15                                       @ save right of the second line of luma for later use
103
+    compute_8px_32      r11, d14, \ofmt
104
+
105
+    compute_premult_32  d29, d31
106
+    compute_8px_32      r2,  d28, \ofmt
107
+    compute_8px_32      r11, d30, \ofmt
108
+.endm
109
+
110
+.macro load_args
86 111
     push                {r4-r12, lr}
87 112
     vpush               {q4-q7}
88 113
     ldr                 r4, [sp, #104]                                 @ r4  = srcY
... ...
@@ -102,6 +204,11 @@ function ff_\ifmt\()_to_\ofmt\()_neon, export=1
102 102
     sub                 r3, r3, r8                                     @ r3 = linesize  * 2 - width * 4 (padding)
103 103
     sub                 r5, r5, r0                                     @ r5 = linesizeY * 2 - width     (paddingY)
104 104
     sub                 r7, r7, r0                                     @ r7 = linesizeC     - width     (paddingC)
105
+.endm
106
+
107
+.macro declare_func ifmt ofmt precision
108
+function ff_\ifmt\()_to_\ofmt\()_neon_\precision\(), export=1
109
+    load_args
105 110
 1:
106 111
     mov                 r8, r0                                         @ r8 = width
107 112
 2:
... ...
@@ -119,19 +226,13 @@ function ff_\ifmt\()_to_\ofmt\()_neon, export=1
119 119
     vsubl.u8            q15, d2, d10                                   @ q15 = V - 128
120 120
 .endif
121 121
 
122
-    compute_premult     d28, d30
123
-
124
-    vld1.8              {q7}, [r4]!                                    @ first line of luma
125
-    vmov                d28, d15                                       @ save right of the first line of luma for later use
126
-    compute_half_line   r2, d14, \ofmt
127
-
128
-    vld1.8              {q7}, [r12]!                                   @ second line of luma
129
-    vmov                d30, d15                                       @ save right of the second line of luma for later use
130
-    compute_half_line   r11, d14, \ofmt
122
+.ifc \precision,16
123
+    process_16px_16     \ofmt
124
+.endif
131 125
 
132
-    compute_premult     d29, d31
133
-    compute_half_line   r2,  d28, \ofmt
134
-    compute_half_line   r11, d30, \ofmt
126
+.ifc \precision,32
127
+    process_16px_32     \ofmt
128
+.endif
135 129
 
136 130
     subs                r8, r8, #16                                    @ width -= 16
137 131
     bgt                 2b
... ...
@@ -151,12 +252,14 @@ function ff_\ifmt\()_to_\ofmt\()_neon, export=1
151 151
 endfunc
152 152
 .endm
153 153
 
154
-.macro declare_rgb_funcs ifmt
155
-    declare_func \ifmt, argb
156
-    declare_func \ifmt, rgba
157
-    declare_func \ifmt, abgr
158
-    declare_func \ifmt, bgra
154
+.macro declare_rgb_funcs ifmt precision
155
+    declare_func \ifmt, argb, \precision
156
+    declare_func \ifmt, rgba, \precision
157
+    declare_func \ifmt, abgr, \precision
158
+    declare_func \ifmt, bgra, \precision
159 159
 .endm
160 160
 
161
-declare_rgb_funcs nv12
162
-declare_rgb_funcs nv21
161
+declare_rgb_funcs nv12, 16
162
+declare_rgb_funcs nv21, 16
163
+declare_rgb_funcs nv12, 32
164
+declare_rgb_funcs nv21, 32