xref: /haiku/src/add-ons/media/plugins/ffmpeg/gfx_conv_c.cpp (revision 4a55cc230cf7566cadcbb23b1928eefff8aea9a2)
1 #include "gfx_conv_c.h"
2 
3 #include <strings.h>
4 #include <stdio.h>
5 
6 
7 void
8 gfx_conv_null(AVFrame *in, AVFrame *out, int width, int height)
9 {
10 	memcpy(out->data[0], in->data[0], height * in->linesize[0]);
11 }
12 
13 
14 void
15 gfx_conv_yuv410p_ycbcr422_c(AVFrame *in, AVFrame *out, int width, int height)
16 {
17 	int i;
18 //	bool toggle=false;
19 	unsigned long *po_eol;
20 	unsigned long *p;
21 	unsigned long y1;
22 	unsigned long y2;
23 	unsigned short u;
24 	unsigned short v;
25 	unsigned long a;
26 	unsigned long b;
27 	unsigned long c;
28 	unsigned long d;
29 //	printf("[%ld, %ld, %ld] -> [%ld, %ld, %ld]\n", in->linesize[0],
30 //		in->linesize[1], in->linesize[2], out->linesize[0], out->linesize[1],
31 //		out->linesize[2]);
32 //	memcpy(out->data[0], in->data[0], height * in->linesize[0]);
33 	unsigned long *po = (unsigned long *)out->data[0];
34 	unsigned long *pi = (unsigned long *)in->data[0];
35 	unsigned short *pi2 = (unsigned short *)in->data[1];
36 	unsigned short *pi3 = (unsigned short *)in->data[2];
37 	for (i = 0; i < height; i++) {
38 		for (p = po,
39 			po_eol = (unsigned long *)(((char *)po) + out->linesize[0]);
40 			p < po_eol;) {
41 //			*(((long *)po) + j) = (long)(*(pi + j) + (*(pi2 + j) << 8)
42 //				+ (*(pi + j + 3) << 16) + (*(pi3 + j) << 24));
43 			y1 = *pi++;
44 			y2 = *pi++;
45 			u = *pi2;
46 			v = *pi3;
47 			a = (long)((y1 & 0x0FF) | ((u& 0x0FF) << 8) | ((y1 & 0x0FF00) << 8)
48 				| ((v & 0x0FF) << 24));
49 			b = (long)(((y1 & 0x0FF0000) >> 16) | ((u& 0x0FF) << 8)
50 				| ((y1 & 0x0FF000000) >> 8) | ((v & 0x0FF) << 24));
51 			c = (long)((y2 & 0x0FF) | (u & 0x0FF00) | ((y2 & 0x0FF00) << 8)
52 				| ((v & 0x0FF00) << 16));
53 			d = (long)(((y2 & 0x0FF0000) >> 16) | ((u& 0x0FF00))
54 				| ((y2 & 0x0FF000000) >> 8) | ((v & 0x0FF00) << 16));
55 //			if (toggle) {
56 				pi2++;
57 //			} else {
58 				pi3++;
59 //			}
60 //			toggle = !toggle;
61 
62 			*(p++) = a;
63 			*(p++) = b;
64 			*(p++) = c;
65 			*(p++) = d;
66 		}
67 		po = (unsigned long *)((char *)po + out->linesize[0]);
68 		pi = (unsigned long *)(in->data[0] + i * in->linesize[0]);
69 		pi2 = (unsigned short *)(in->data[1] + ((i + 2) / 4)
70 			* in->linesize[1]);
71 		pi3 = (unsigned short *)(in->data[2] + ((i + 3) / 4)
72 			* in->linesize[2]);
73 	}
74 }
75 
76 
77 void
78 gfx_conv_yuv411p_ycbcr422_c(AVFrame *in, AVFrame *out, int width, int height)
79 {
80 	// this one is for cyuv
81 	// TODO: (== yuv410p atm)
82 	gfx_conv_yuv410p_ycbcr422_c(in, out, width, height);
83 }
84 
85 
86 void
87 gfx_conv_yuv420p_ycbcr422_c(AVFrame *in, AVFrame *out, int width, int height)
88 {
89 	unsigned long *po_eol;
90 	unsigned long *p;
91 	unsigned long y1;
92 	unsigned long y2;
93 	unsigned long u;
94 	unsigned long v;
95 	unsigned long a;
96 	unsigned long b;
97 	unsigned long c;
98 	unsigned long d;
99 //	printf("[%ld, %ld, %ld] -> [%ld, %ld, %ld]\n", in->linesize[0],
100 //		in->linesize[1], in->linesize[2], out->linesize[0], out->linesize[1],
101 //		out->linesize[2]);
102 //	memcpy(out->data[0], in->data[0], height * in->linesize[0]);
103 	unsigned long *po = (unsigned long *)out->data[0];
104 	unsigned long *pi = (unsigned long *)in->data[0];
105 	unsigned long *pi2 = (unsigned long *)in->data[1];
106 	unsigned long *pi3 = (unsigned long *)in->data[2];
107 	for (int i = 0; i < height; i++) {
108 		for (p = po, po_eol = (unsigned long *)(((char *)po)+out->linesize[0]);
109 			p < po_eol;) {
110 //			*(((long *)po) + j) = (long)(*(pi + j) + (*(pi2 + j) << 8)
111 //				+ (*(pi + j + 3) << 16) + (*(pi3 + j) << 24));
112 			y1 = *pi++;
113 			y2 = *pi++;
114 			u = *pi2++;
115 			v = *pi3++;
116 			a = (long)((y1 & 0x0FF) | ((u & 0x0FF) << 8) | ((y1 & 0x0FF00) << 8)
117 				| ((v & 0x0FF) << 24));
118 			b = (long)(((y1 & 0x0FF0000) >> 16) | ((u & 0x0FF00))
119 				| ((y1 & 0x0FF000000) >> 8) | ((v & 0x0FF00) << 16));
120 			c = (long)((y2 & 0x0FF) | ((u & 0x0FF0000) >> 8)
121 				| ((y2 & 0x0FF00) << 8) | ((v & 0x0FF0000) << 8));
122 			d = (long)(((y2 & 0x0FF0000) >> 16) | ((u & 0x0FF000000) >> 16)
123 				| ((y2 & 0x0FF000000) >> 8) | ((v & 0x0FF000000)));
124 
125 			*(p++) = a;
126 			*(p++) = b;
127 			*(p++) = c;
128 			*(p++) = d;
129 		}
130 		po = (unsigned long *)((char *)po + out->linesize[0]);
131 		pi = (unsigned long *)(in->data[0] + i * in->linesize[0]);
132 		pi2 = (unsigned long *)(in->data[1] + ((i + 1) / 2) * in->linesize[1]);
133 		pi3 = (unsigned long *)(in->data[2] + (i / 2) * in->linesize[2]);
134 	}
135 }
136 
137 
138 #define CLIP(a) if (0xffffff00 & (uint32)a) { if (a < 0) a = 0; else a = 255; }
139 
140 static inline uint32
141 YUV10TORGBA8888(uint16 y, uint16 u, uint16 v)
142 {
143 	int32 c = y - 64;
144 	int32 d = u - 512;
145 	int32 e = v - 512;
146 
147 	int32 r = (298 * c + 409 * e + 512) >> 10;
148 	int32 g = (298 * c - 100 * d - 208 * e + 512) >> 10;
149 	int32 b = (298 * c + 516 * d + 512) >> 10;
150 
151 	CLIP(r);
152 	CLIP(g);
153 	CLIP(b);
154 
155 	return (uint32)((255 << 24) | (r << 16) | (g << 8) | b);
156 }
157 
158 
159 void
160 gfx_conv_yuv420p10le_rgb32_c(AVFrame *in, AVFrame *out, int width, int height)
161 {
162 	uint16 *yBase = (uint16 *)in->data[0];
163 	uint16 *uBase = (uint16 *)in->data[1];
164 	uint16 *vBase = (uint16 *)in->data[2];
165 
166 	uint32 *rgbBase = (uint32 *)out->data[0];
167 
168 	int uvIndex;
169 
170 	for (int32 i = 0; i < height; i++) {
171 		uvIndex = 0;
172 		for (int32 j=0; j < width; j += 2) {
173 			rgbBase[j] = YUV10TORGBA8888(yBase[j], uBase[uvIndex],
174 				vBase[uvIndex]);
175 			rgbBase[j + 1] = YUV10TORGBA8888(yBase[j + 1], uBase[uvIndex],
176 				vBase[uvIndex]);
177 			uvIndex++;
178 		}
179 
180 		// Advance pointers to next line
181 		yBase += in->linesize[0] / 2;
182 
183 		if ((i & 1) == 0) {
184 			// These are the same for 2 lines
185 			uBase += in->linesize[1] / 2;
186 			vBase += in->linesize[2] / 2;
187 		}
188 
189 		rgbBase += out->linesize[0] / 4;
190 	}
191 }
192 
193 
194 // http://en.wikipedia.org/wiki/YUV
195 static inline uint32
196 YUV444TORGBA8888(uint8 y, uint8 u, uint8 v)
197 {
198 	int32 c = y - 16;
199 	int32 d = u - 128;
200 	int32 e = v - 128;
201 
202 	int32 r = (298 * c + 409 * e + 128) >> 8;
203 	int32 g = (298 * c - 100 * d - 208 * e + 128) >> 8;
204 	int32 b = (298 * c + 516 * d + 128) >> 8;
205 
206 	CLIP(r);
207 	CLIP(g);
208 	CLIP(b);
209 
210 	return (uint32)((255 << 24) | (r << 16) | (g << 8) | b);
211 }
212 
213 
214 void
215 gfx_conv_yuv410p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height)
216 {
217 	uint8 *yBase = (uint8 *)in->data[0];
218 	uint8 *uBase = (uint8 *)in->data[1];
219 	uint8 *vBase = (uint8 *)in->data[2];
220 
221 	uint32 *rgbBase = (uint32 *)out->data[0];
222 
223 	int uvIndex;
224 
225 	for (int32 i = 0; i < height; i++) {
226 		uvIndex = 0;
227 		for (int32 j=0; j < width; j+=4) {
228 			rgbBase[j] = YUV444TORGBA8888(yBase[j], uBase[uvIndex],
229 				vBase[uvIndex]);
230 			rgbBase[j + 1] = YUV444TORGBA8888(yBase[j + 1], uBase[uvIndex],
231 				vBase[uvIndex]);
232 			rgbBase[j + 2] = YUV444TORGBA8888(yBase[j + 2], uBase[uvIndex],
233 				vBase[uvIndex]);
234 			rgbBase[j + 3] = YUV444TORGBA8888(yBase[j + 3], uBase[uvIndex],
235 				vBase[uvIndex]);
236 			uvIndex++;
237 		}
238 
239 		// Advance pointers to next line
240 		yBase += in->linesize[0];
241 
242 		if ((i & 3) == 0) {
243 			// These are the same for 4 lines
244 			uBase += in->linesize[1];
245 			vBase += in->linesize[2];
246 		}
247 
248 		rgbBase += out->linesize[0] / 4;
249 	}
250 }
251 
252 
253 void
254 gfx_conv_yuv411p_rgb32_c(AVFrame *in, AVFrame *out, int width, int height)
255 {
256 	gfx_conv_null(in, out, width, height);
257 }
258 
259 
260 void
261 gfx_conv_YCbCr422_RGB32_c(AVFrame *in, AVFrame *out, int width, int height)
262 {
263 	uint8 *yBase = (uint8 *)in->data[0];
264 	uint8 *uBase = (uint8 *)in->data[1];
265 	uint8 *vBase = (uint8 *)in->data[2];
266 
267 	uint32 *rgbBase = (uint32 *)out->data[0];
268 
269 	int uvIndex;
270 
271 	for (int32 i = 0; i < height; i++) {
272 
273 		uvIndex = 0;
274 
275 		for (int32 j = 0; j < width; j += 2) {
276 			rgbBase[j] = YUV444TORGBA8888(yBase[j], uBase[uvIndex],
277 				vBase[uvIndex]);
278 			rgbBase[j + 1] = YUV444TORGBA8888(yBase[j + 1], uBase[uvIndex],
279 				vBase[uvIndex]);
280 
281 			uvIndex++;
282 		}
283 
284 		yBase += in->linesize[0];
285 		uBase += in->linesize[1];
286 		vBase += in->linesize[2];
287 
288 		rgbBase += out->linesize[0] / 4;
289 	}
290 
291 	if (height & 1) {
292 		// XXX special case for last line if height not multiple of 2 goes here
293 		memset((height - 1) * out->linesize[0] + (uint8 *)out->data[0], 0,
294 			width * 4);
295 	}
296 
297 }
298 
299 
300 void
301 gfx_conv_GBRP_RGB32_c(AVFrame *in, AVFrame *out, int width, int height)
302 {
303 	uint8 *bBase = (uint8 *)in->data[0];
304 	uint8 *gBase = (uint8 *)in->data[1];
305 	uint8 *rBase = (uint8 *)in->data[2];
306 
307 	uint32 *rgbBase = (uint32 *)out->data[0];
308 
309 	for (int32 i = 0; i < height; i++) {
310 
311 		for (int32 j = 0; j < width; j ++) {
312 			rgbBase[j] = gBase[j] | (bBase[j] << 8) | (rBase[j] << 16);
313 		}
314 
315 		bBase += in->linesize[0];
316 		gBase += in->linesize[1];
317 		rBase += in->linesize[2];
318 
319 		rgbBase += out->linesize[0] / 4;
320 	}
321 }
322