]> git.sesse.net Git - ffmpeg/blob - libswscale/bayer_template.c
x86/yuv2rgb: fix crashes when storing data on unaligned buffers
[ffmpeg] / libswscale / bayer_template.c
1 /*
2  * Bayer-to-RGB/YV12 template
3  * Copyright (c) 2011-2014 Peter Ross <pross@xvid.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 #if defined(BAYER_BGGR) || defined(BAYER_GBRG)
23 #define BAYER_R       0
24 #define BAYER_G       1
25 #define BAYER_B       2
26 #endif
27 #if defined(BAYER_RGGB) || defined(BAYER_GRBG)
28 #define BAYER_R       2
29 #define BAYER_G       1
30 #define BAYER_B       0
31 #endif
32
33 #if defined(BAYER_8)
34 #define BAYER_READ(x) (x)
35 #define BAYER_SIZEOF  1
36 #define BAYER_SHIFT   0
37 #endif
38 #if defined(BAYER_16LE)
39 #define BAYER_READ(x) AV_RL16(&(x))
40 #define BAYER_SIZEOF  2
41 #define BAYER_SHIFT   8
42 #endif
43 #if defined(BAYER_16BE)
44 #define BAYER_READ(x) AV_RB16(&(x))
45 #define BAYER_SIZEOF  2
46 #define BAYER_SHIFT   8
47 #endif
48
49 #define S(y, x) BAYER_READ(src[(y)*src_stride + BAYER_SIZEOF*(x)])
50 #define T(y, x) (unsigned int)S(y, x)
51 #define R(y, x) dst[(y)*dst_stride + (x)*3 + BAYER_R]
52 #define G(y, x) dst[(y)*dst_stride + (x)*3 + BAYER_G]
53 #define B(y, x) dst[(y)*dst_stride + (x)*3 + BAYER_B]
54
55 #if defined(BAYER_BGGR) || defined(BAYER_RGGB)
56 #define BAYER_TO_RGB24_COPY \
57     R(0, 0) = \
58     R(0, 1) = \
59     R(1, 1) = \
60     R(1, 0) = S(1, 1) >> BAYER_SHIFT; \
61     \
62     G(0, 1) = S(0, 1) >> BAYER_SHIFT; \
63     G(0, 0) = \
64     G(1, 1) = (T(0, 1) + T(1, 0)) >> (1 + BAYER_SHIFT); \
65     G(1, 0) = S(1, 0) >> BAYER_SHIFT; \
66     \
67     B(1, 1) = \
68     B(0, 0) = \
69     B(0, 1) = \
70     B(1, 0) = S(0, 0) >> BAYER_SHIFT;
71 #define BAYER_TO_RGB24_INTERPOLATE \
72     R(0, 0) = (T(-1, -1) + T(-1,  1) + T(1, -1) + T(1, 1)) >> (2 + BAYER_SHIFT); \
73     G(0, 0) = (T(-1,  0) + T( 0, -1) + T(0,  1) + T(1, 0)) >> (2 + BAYER_SHIFT); \
74     B(0, 0) =  S(0, 0) >> BAYER_SHIFT; \
75     \
76     R(0, 1) = (T(-1, 1) + T(1, 1)) >> (1 + BAYER_SHIFT); \
77     G(0, 1) =  S(0,  1) >> BAYER_SHIFT; \
78     B(0, 1) = (T(0,  0) + T(0, 2)) >> (1 + BAYER_SHIFT); \
79     \
80     R(1, 0) = (T(1, -1) + T(1, 1)) >> (1 + BAYER_SHIFT); \
81     G(1, 0) =  S(1,  0) >> BAYER_SHIFT; \
82     B(1, 0) = (T(0,  0) + T(2, 0)) >> (1 + BAYER_SHIFT); \
83     \
84     R(1, 1) =  S(1, 1) >> BAYER_SHIFT; \
85     G(1, 1) = (T(0, 1) + T(1, 0) + T(1, 2) + T(2, 1)) >> (2 + BAYER_SHIFT); \
86     B(1, 1) = (T(0, 0) + T(0, 2) + T(2, 0) + T(2, 2)) >> (2 + BAYER_SHIFT);
87 #else
88 #define BAYER_TO_RGB24_COPY \
89     R(0, 0) = \
90     R(0, 1) = \
91     R(1, 1) = \
92     R(1, 0) = S(1, 0) >> BAYER_SHIFT; \
93     \
94     G(0, 0) = S(0, 0) >> BAYER_SHIFT; \
95     G(1, 1) = S(1, 1) >> BAYER_SHIFT; \
96     G(0, 1) = \
97     G(1, 0) = (T(0, 0) + T(1, 1)) >> (1 + BAYER_SHIFT); \
98     \
99     B(1, 1) = \
100     B(0, 0) = \
101     B(0, 1) = \
102     B(1, 0) = S(0, 1) >> BAYER_SHIFT;
103 #define BAYER_TO_RGB24_INTERPOLATE \
104     R(0, 0) = (T(-1, 0) + T(1, 0)) >> (1 + BAYER_SHIFT); \
105     G(0, 0) =  S(0, 0) >> BAYER_SHIFT; \
106     B(0, 0) = (T(0, -1) + T(0, 1)) >> (1 + BAYER_SHIFT); \
107     \
108     R(0, 1) = (T(-1, 0) + T(-1, 2) + T(1, 0) + T(1, 2)) >> (2 + BAYER_SHIFT); \
109     G(0, 1) = (T(-1, 1) + T(0,  0) + T(0, 2) + T(1, 1)) >> (2 + BAYER_SHIFT); \
110     B(0, 1) =  S(0, 1) >> BAYER_SHIFT; \
111     \
112     R(1, 0) =  S(1, 0) >> BAYER_SHIFT; \
113     G(1, 0) = (T(0, 0)  + T(1, -1) + T(1,  1) + T(2, 0)) >> (2 + BAYER_SHIFT); \
114     B(1, 0) = (T(0, -1) + T(0,  1) + T(2, -1) + T(2, 1)) >> (2 + BAYER_SHIFT); \
115     \
116     R(1, 1) = (T(1, 0) + T(1, 2)) >> (1 + BAYER_SHIFT); \
117     G(1, 1) =  S(1, 1) >> BAYER_SHIFT; \
118     B(1, 1) = (T(0, 1) + T(2, 1)) >> (1 + BAYER_SHIFT);
119 #endif
120
121 /**
122  * invoke ff_rgb24toyv12 for 2x2 pixels
123  */
124 #define rgb24toyv12_2x2(src, dstY, dstU, dstV, luma_stride, src_stride, rgb2yuv) \
125     ff_rgb24toyv12(src, dstY, dstV, dstU, 2, 2, luma_stride, 0, src_stride, rgb2yuv)
126
127 static void BAYER_RENAME(rgb24_copy)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width)
128 {
129     int i;
130     for (i = 0 ; i < width; i+= 2) {
131         BAYER_TO_RGB24_COPY
132         src += 2 * BAYER_SIZEOF;
133         dst += 6;
134     }
135 }
136
137 static void BAYER_RENAME(rgb24_interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width)
138 {
139     int i;
140
141     BAYER_TO_RGB24_COPY
142     src += 2 * BAYER_SIZEOF;
143     dst += 6;
144
145     for (i = 2 ; i < width - 2; i+= 2) {
146         BAYER_TO_RGB24_INTERPOLATE
147         src += 2 * BAYER_SIZEOF;
148         dst += 6;
149     }
150
151     if (width > 2) {
152         BAYER_TO_RGB24_COPY
153     }
154 }
155
156 static void BAYER_RENAME(yv12_copy)(const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, int32_t *rgb2yuv)
157 {
158     uint8_t dst[12];
159     const int dst_stride = 6;
160     int i;
161     for (i = 0 ; i < width; i+= 2) {
162         BAYER_TO_RGB24_COPY
163         rgb24toyv12_2x2(dst, dstY, dstU, dstV, luma_stride, dst_stride, rgb2yuv);
164         src  += 2 * BAYER_SIZEOF;
165         dstY += 2;
166         dstU++;
167         dstV++;
168     }
169 }
170
171 static void BAYER_RENAME(yv12_interpolate)(const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, int32_t *rgb2yuv)
172 {
173     uint8_t dst[12];
174     const int dst_stride = 6;
175     int i;
176
177     BAYER_TO_RGB24_COPY
178     rgb24toyv12_2x2(dst, dstY, dstU, dstV, luma_stride, dst_stride, rgb2yuv);
179     src  += 2 * BAYER_SIZEOF;
180     dstY += 2;
181     dstU++;
182     dstV++;
183
184     for (i = 2 ; i < width - 2; i+= 2) {
185         BAYER_TO_RGB24_INTERPOLATE
186         rgb24toyv12_2x2(dst, dstY, dstU, dstV, luma_stride, dst_stride, rgb2yuv);
187         src  += 2 * BAYER_SIZEOF;
188         dstY += 2;
189         dstU++;
190         dstV++;
191     }
192
193     if (width > 2) {
194         BAYER_TO_RGB24_COPY
195         rgb24toyv12_2x2(dst, dstY, dstU, dstV, luma_stride, dst_stride, rgb2yuv);
196     }
197 }
198
199 #undef S
200 #undef T
201 #undef R
202 #undef G
203 #undef B
204 #undef BAYER_TO_RGB24_COPY
205 #undef BAYER_TO_RGB24_INTERPOLATE
206
207 #undef BAYER_RENAME
208
209 #undef BAYER_R
210 #undef BAYER_G
211 #undef BAYER_B
212 #undef BAYER_READ
213 #undef BAYER_SIZEOF
214 #undef BAYER_SHIFT
215
216 #if defined(BAYER_BGGR)
217 #undef BAYER_BGGR
218 #endif
219 #if defined(BAYER_RGGB)
220 #undef BAYER_RGGB
221 #endif
222 #if defined(BAYER_GBRG)
223 #undef BAYER_GBRG
224 #endif
225 #if defined(BAYER_GRBG)
226 #undef BAYER_GRBG
227 #endif
228 #if defined(BAYER_8)
229 #undef BAYER_8
230 #endif
231 #if defined(BAYER_16LE)
232 #undef BAYER_16LE
233 #endif
234 #if defined(BAYER_16BE)
235 #undef BAYER_16BE
236 #endif