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