1 /*
2  * rgb.c
3  * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
4  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
5  *
6  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
7  * See http://libmpeg2.sourceforge.net/ for updates.
8  *
9  * mpeg2dec is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * mpeg2dec is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "config.h"
25 #include "attributes.h"
26 
27 #include <inttypes.h>
28 
29 #include "mpeg2.h"
30 #include "mpeg2convert.h"
31 #include "convert_internal.h"
32 
33 static int matrix_coefficients = 6;
34 
35 static const int Inverse_Table_6_9[8][4] = {
36     {117504, 138453, 13954, 34903}, /* no sequence_display_extension */
37     {117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
38     {104597, 132201, 25675, 53279}, /* unspecified */
39     {104597, 132201, 25675, 53279}, /* reserved */
40     {104448, 132798, 24759, 53109}, /* FCC */
41     {104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
42     {104597, 132201, 25675, 53279}, /* SMPTE 170M */
43     {117579, 136230, 16907, 35559}  /* SMPTE 240M (1987) */
44 };
45 
46 static const uint8_t dither[] ATTR_ALIGN(32) = {
47      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
48      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
49      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
50      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
51     15, 36,  7, 18, 21, 50, 13, 31, 17, 39,  9, 21, 22, 53, 15, 35,
52     15, 36,  7, 18, 21, 50, 13, 31, 17, 39,  9, 21, 22, 53, 15, 35,
53     15, 36,  7, 18, 21, 50, 13, 31, 17, 39,  9, 21, 22, 53, 15, 35,
54     15, 36,  7, 18, 21, 50, 13, 31, 17, 39,  9, 21, 22, 53, 15, 35,
55      3,  9, 27, 63,  1,  4, 25, 59,  5, 12, 28, 67,  3,  7, 26, 62,
56      3,  9, 27, 63,  1,  4, 25, 59,  5, 12, 28, 67,  3,  7, 26, 62,
57      3,  9, 27, 63,  1,  4, 25, 59,  5, 12, 28, 67,  3,  7, 26, 62,
58      3,  9, 27, 63,  1,  4, 25, 59,  5, 12, 28, 67,  3,  7, 26, 62,
59     19, 45, 11, 27, 17, 41,  9, 22, 21, 49, 13, 30, 19, 44, 11, 26,
60     19, 45, 11, 27, 17, 41,  9, 22, 21, 49, 13, 30, 19, 44, 11, 26,
61     19, 45, 11, 27, 17, 41,  9, 22, 21, 49, 13, 30, 19, 44, 11, 26,
62     19, 45, 11, 27, 17, 41,  9, 22, 21, 49, 13, 30, 19, 44, 11, 26,
63      0,  2, 24, 57,  6, 15, 30, 70,  0,  1, 23, 55,  6, 14, 29, 69,
64      0,  2, 24, 57,  6, 15, 30, 70,  0,  1, 23, 55,  6, 14, 29, 69,
65      0,  2, 24, 57,  6, 15, 30, 70,  0,  1, 23, 55,  6, 14, 29, 69,
66      0,  2, 24, 57,  6, 15, 30, 70,  0,  1, 23, 55,  6, 14, 29, 69,
67     16, 38,  8, 20, 22, 52, 14, 34, 16, 37,  8, 19, 21, 51, 14, 33,
68     16, 38,  8, 20, 22, 52, 14, 34, 16, 37,  8, 19, 21, 51, 14, 33,
69     16, 38,  8, 20, 22, 52, 14, 34, 16, 37,  8, 19, 21, 51, 14, 33,
70     16, 38,  8, 20, 22, 52, 14, 34, 16, 37,  8, 19, 21, 51, 14, 33,
71      4, 11, 28, 66,  2,  6, 26, 61,  4, 10, 27, 65,  2,  5, 25, 60,
72      4, 11, 28, 66,  2,  6, 26, 61,  4, 10, 27, 65,  2,  5, 25, 60,
73      4, 11, 28, 66,  2,  6, 26, 61,  4, 10, 27, 65,  2,  5, 25, 60,
74      4, 11, 28, 66,  2,  6, 26, 61,  4, 10, 27, 65,  2,  5, 25, 60,
75     20, 47, 12, 29, 18, 43, 10, 25, 20, 46, 12, 28, 18, 42, 10, 23,
76     20, 47, 12, 29, 18, 43, 10, 25, 20, 46, 12, 28, 18, 42, 10, 23,
77     20, 47, 12, 29, 18, 43, 10, 25, 20, 46, 12, 28, 18, 42, 10, 23,
78     20, 47, 12, 29, 18, 43, 10, 25, 20, 46, 12, 28, 18, 42, 10, 23,
79      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
80      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
81      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
82      0,  0, 23, 54,  5, 13, 29, 68,  1,  3, 24, 58,  7, 17, 30, 71,
83     15, 36,  7, 18, 21, 50, 13, 31, 17, 39,  9, 21, 22, 53, 15, 35,
84     15, 36,  7, 18, 21, 50, 13, 31, 17, 39,  9, 21, 22, 53, 15, 35
85 };
86 
87 static const uint8_t dither_temporal[64] = {
88     0x00, 0x20, 0x21, 0x01, 0x40, 0x60, 0x61, 0x41,
89     0x42, 0x62, 0x63, 0x43, 0x02, 0x22, 0x23, 0x03,
90     0x80, 0xa0, 0xa1, 0x81, 0xc0, 0xe0, 0xe1, 0xc1,
91     0xc2, 0xe2, 0xe3, 0xc3, 0x82, 0xa2, 0xa3, 0x83,
92     0x84, 0xa4, 0xa5, 0x85, 0xc4, 0xe4, 0xe5, 0xc5,
93     0xc6, 0xe6, 0xe7, 0xc7, 0x86, 0xa6, 0xa7, 0x87,
94     0x04, 0x24, 0x25, 0x05, 0x44, 0x64, 0x65, 0x45,
95     0x46, 0x66, 0x67, 0x47, 0x06, 0x26, 0x27, 0x07
96 };
97 
98 typedef struct {
99     convert_rgb_t base;
100     void * table_rV[256];
101     void * table_gU[256];
102     int table_gV[256];
103     void * table_bU[256];
104 } convert_rgb_c_t;
105 
106 #define RGB(type,i)							\
107     U = pu[i];								\
108     V = pv[i];								\
109     r = (type *) id->table_rV[V];					\
110     g = (type *) (((uint8_t *)id->table_gU[U]) + id->table_gV[V]);	\
111     b = (type *) id->table_bU[U];
112 
113 #define DST(py,dst,i,j)			\
114     Y = py[i];				\
115     dst[i] = r[Y] + g[Y] + b[Y];
116 
117 #define DSTRGB(py,dst,i,j)					\
118     Y = py[i];							\
119     dst[3*i] = r[Y]; dst[3*i+1] = g[Y]; dst[3*i+2] = b[Y];
120 
121 #define DSTBGR(py,dst,i,j)					\
122     Y = py[i];							\
123     dst[3*i] = b[Y]; dst[3*i+1] = g[Y]; dst[3*i+2] = r[Y];
124 
125 #define DSTDITHER(py,dst,i,j)						  \
126     Y = py[i];								  \
127     dst[i] = r[Y+pd[2*i+96*j]] + g[Y-pd[2*i+96*j]] + b[Y+pd[2*i+1+96*j]];
128 
129 #define DO(x) x
130 #define SKIP(x)
131 
132 #define DECLARE_420(func,type,num,DST,DITHER)				\
133 static void func (void * _id, uint8_t * const * src,			\
134 		  unsigned int v_offset)				\
135 {									\
136     const convert_rgb_c_t * const id = (convert_rgb_c_t *) _id;		\
137     type * dst_1;							\
138     const uint8_t * py_1, * pu, * pv;					\
139     int i;								\
140     DITHER(uint8_t dithpos = id->base.dither_offset;)			\
141 									\
142     dst_1 = (type *)(id->base.rgb_ptr + id->base.rgb_slice * v_offset);	\
143     py_1 = src[0];	pu = src[1];	pv = src[2];			\
144 									\
145     i = 8;								\
146     do {								\
147 	const uint8_t * py_2;						\
148 	int j, U, V, Y;							\
149 	const type * r, * g, * b;					\
150 	type * dst_2;							\
151 	DITHER(const uint8_t * const pd = dither + 2 * dithpos;)	\
152 									\
153 	dst_2 = (type *)((char *)dst_1 + id->base.rgb_stride);		\
154 	py_2 = py_1 + id->base.y_stride;				\
155 	j = id->base.width;						\
156 	do {								\
157 	    RGB (type, 0)						\
158 	    DST (py_1, dst_1, 0, 0)					\
159 	    DST (py_1, dst_1, 1, 0)					\
160 	    DST (py_2, dst_2, 0, 1)					\
161 	    DST (py_2, dst_2, 1, 1)					\
162 									\
163 	    RGB (type, 1)						\
164 	    DST (py_2, dst_2, 2, 1)					\
165 	    DST (py_2, dst_2, 3, 1)					\
166 	    DST (py_1, dst_1, 2, 0)					\
167 	    DST (py_1, dst_1, 3, 0)					\
168 									\
169 	    RGB (type, 2)						\
170 	    DST (py_1, dst_1, 4, 0)					\
171 	    DST (py_1, dst_1, 5, 0)					\
172 	    DST (py_2, dst_2, 4, 1)					\
173 	    DST (py_2, dst_2, 5, 1)					\
174 									\
175 	    RGB (type, 3)						\
176 	    DST (py_2, dst_2, 6, 1)					\
177 	    DST (py_2, dst_2, 7, 1)					\
178 	    DST (py_1, dst_1, 6, 0)					\
179 	    DST (py_1, dst_1, 7, 0)					\
180 									\
181 	    pu += 4;							\
182 	    pv += 4;							\
183 	    py_1 += 8;							\
184 	    py_2 += 8;							\
185 	    dst_1 += 8 * num;						\
186 	    dst_2 += 8 * num;						\
187 	} while (--j);							\
188 	if (--i == id->base.field) {					\
189 	    dst_1 = (type *)(id->base.rgb_ptr +				\
190 			     id->base.rgb_slice * (v_offset + 1));	\
191 	    py_1 = src[0] + id->base.y_stride_frame;			\
192 	    pu = src[1] + id->base.uv_stride_frame;			\
193 	    pv = src[2] + id->base.uv_stride_frame;			\
194 	} else {							\
195 	    py_1 += id->base.y_increm;					\
196 	    pu += id->base.uv_increm;					\
197 	    pv += id->base.uv_increm;					\
198 	    dst_1 = (type *)((char *)dst_1 + id->base.rgb_increm);	\
199 	    DITHER(dithpos += id->base.dither_stride;)			\
200 	}								\
201     } while (i);							\
202 }
203 
204 DECLARE_420 (rgb_c_32_420, uint32_t, 1, DST, SKIP)
205 DECLARE_420 (rgb_c_24_rgb_420, uint8_t, 3, DSTRGB, SKIP)
206 DECLARE_420 (rgb_c_24_bgr_420, uint8_t, 3, DSTBGR, SKIP)
207 DECLARE_420 (rgb_c_16_420, uint16_t, 1, DST, SKIP)
208 DECLARE_420 (rgb_c_8_420, uint8_t, 1, DSTDITHER, DO)
209 
210 #define DECLARE_422(func,type,num,DST,DITHER)				\
211 static void func (void * _id, uint8_t * const * src,			\
212 		  unsigned int v_offset)				\
213 {									\
214     const convert_rgb_c_t * const id = (convert_rgb_c_t *) _id;		\
215     type * dst;								\
216     const uint8_t * py, * pu, * pv;					\
217     int i;								\
218     DITHER(uint8_t dithpos = id->base.dither_offset;)			\
219 									\
220     dst = (type *)(id->base.rgb_ptr + id->base.rgb_stride * v_offset);	\
221     py = src[0];	pu = src[1];	pv = src[2];			\
222 									\
223     i = 16;								\
224     do {								\
225 	int j, U, V, Y;							\
226 	const type * r, * g, * b;					\
227 	DITHER(const uint8_t * const pd = dither + 2 * dithpos;)	\
228 									\
229 	j = id->base.width;						\
230 	do {								\
231 	    RGB (type, 0)						\
232 	    DST (py, dst, 0, 0)						\
233 	    DST (py, dst, 1, 0)						\
234 									\
235 	    RGB (type, 1)						\
236 	    DST (py, dst, 2, 0)						\
237 	    DST (py, dst, 3, 0)						\
238 									\
239 	    RGB (type, 2)						\
240 	    DST (py, dst, 4, 0)						\
241 	    DST (py, dst, 5, 0)						\
242 									\
243 	    RGB (type, 3)						\
244 	    DST (py, dst, 6, 0)						\
245 	    DST (py, dst, 7, 0)						\
246 									\
247 	    pu += 4;							\
248 	    pv += 4;							\
249 	    py += 8;							\
250 	    dst += 8 * num;						\
251 	} while (--j);							\
252 	py += id->base.y_increm;					\
253 	pu += id->base.uv_increm;					\
254 	pv += id->base.uv_increm;					\
255 	dst = (type *)((char *)dst + id->base.rgb_increm);		\
256 	DITHER(dithpos += id->base.dither_stride;)			\
257     } while (--i);							\
258 }
259 
260 DECLARE_422 (rgb_c_32_422, uint32_t, 1, DST, SKIP)
261 DECLARE_422 (rgb_c_24_rgb_422, uint8_t, 3, DSTRGB, SKIP)
262 DECLARE_422 (rgb_c_24_bgr_422, uint8_t, 3, DSTBGR, SKIP)
263 DECLARE_422 (rgb_c_16_422, uint16_t, 1, DST, SKIP)
264 DECLARE_422 (rgb_c_8_422, uint8_t, 1, DSTDITHER, DO)
265 
266 #define DECLARE_444(func,type,num,DST,DITHER)				\
267 static void func (void * _id, uint8_t * const * src,			\
268 		  unsigned int v_offset)				\
269 {									\
270     const convert_rgb_c_t * const id = (convert_rgb_c_t *) _id;		\
271     type * dst;								\
272     const uint8_t * py, * pu, * pv;					\
273     int i;								\
274     DITHER(uint8_t dithpos = id->base.dither_offset;)			\
275 									\
276     dst = (type *)(id->base.rgb_ptr + id->base.rgb_stride * v_offset);	\
277     py = src[0];	pu = src[1];	pv = src[2];			\
278 									\
279     i = 16;								\
280     do {								\
281 	int j, U, V, Y;							\
282 	const type * r, * g, * b;					\
283 	DITHER(const uint8_t * const pd = dither + 2 * dithpos;)	\
284 									\
285 	j = id->base.width;						\
286 	do {								\
287 	    RGB (type, 0)						\
288 	    DST (py, dst, 0, 0)						\
289 	    RGB (type, 1)						\
290 	    DST (py, dst, 1, 0)						\
291 	    RGB (type, 2)						\
292 	    DST (py, dst, 2, 0)						\
293 	    RGB (type, 3)						\
294 	    DST (py, dst, 3, 0)						\
295 	    RGB (type, 4)						\
296 	    DST (py, dst, 4, 0)						\
297 	    RGB (type, 5)						\
298 	    DST (py, dst, 5, 0)						\
299 	    RGB (type, 6)						\
300 	    DST (py, dst, 6, 0)						\
301 	    RGB (type, 7)						\
302 	    DST (py, dst, 7, 0)						\
303 									\
304 	    pu += 8;							\
305 	    pv += 8;							\
306 	    py += 8;							\
307 	    dst += 8 * num;						\
308 	} while (--j);							\
309 	py += id->base.y_increm;				   	\
310 	pu += id->base.y_increm;				   	\
311 	pv += id->base.y_increm;				   	\
312 	dst = (type *)((char *)dst + id->base.rgb_increm);		\
313 	DITHER(dithpos += id->base.dither_stride;)			\
314     } while (--i);							\
315 }
316 
317 DECLARE_444 (rgb_c_32_444, uint32_t, 1, DST, SKIP)
318 DECLARE_444 (rgb_c_24_rgb_444, uint8_t, 3, DSTRGB, SKIP)
319 DECLARE_444 (rgb_c_24_bgr_444, uint8_t, 3, DSTBGR, SKIP)
320 DECLARE_444 (rgb_c_16_444, uint16_t, 1, DST, SKIP)
321 DECLARE_444 (rgb_c_8_444, uint8_t, 1, DSTDITHER, DO)
322 
rgb_start(void * _id,const mpeg2_fbuf_t * fbuf,const mpeg2_picture_t * picture,const mpeg2_gop_t * gop)323 static void rgb_start (void * _id, const mpeg2_fbuf_t * fbuf,
324 		       const mpeg2_picture_t * picture,
325 		       const mpeg2_gop_t * gop)
326 {
327     convert_rgb_t * id = (convert_rgb_t *) _id;
328     int uv_stride = id->uv_stride_frame;
329     id->y_stride = id->y_stride_frame;
330     id->rgb_ptr = fbuf->buf[0];
331     id->rgb_slice = id->rgb_stride = id->rgb_stride_frame;
332     id->dither_stride = 32;
333     id->dither_offset = dither_temporal[picture->temporal_reference & 63];
334     id->field = 0;
335     if ((picture->nb_fields == 1) ||
336 	(id->chroma420 && !(picture->flags & PIC_FLAG_PROGRESSIVE_FRAME))) {
337 	uv_stride <<= 1;
338 	id->y_stride <<= 1;
339 	id->rgb_stride <<= 1;
340 	id->dither_stride <<= 1;
341 	id->dither_offset += 16;
342 	if (picture->nb_fields == 1) {
343 	    id->rgb_slice <<= 1;
344 	    if (!(picture->flags & PIC_FLAG_TOP_FIELD_FIRST)) {
345 		id->rgb_ptr += id->rgb_stride_frame;
346 		id->dither_offset += 32;
347 	    }
348 	} else
349 	    id->field = 8 >> id->convert420;
350     }
351     id->y_increm = (id->y_stride << id->convert420) - id->y_stride_frame;
352     id->uv_increm = uv_stride - id->uv_stride_frame;
353     id->rgb_increm = (id->rgb_stride << id->convert420) - id->rgb_stride_min;
354     id->dither_stride <<= id->convert420;
355 }
356 
div_round(int dividend,int divisor)357 static inline int div_round (int dividend, int divisor)
358 {
359     if (dividend > 0)
360 	return (dividend + (divisor>>1)) / divisor;
361     else
362 	return -((-dividend + (divisor>>1)) / divisor);
363 }
364 
rgb_c_init(convert_rgb_c_t * id,mpeg2convert_rgb_order_t order,unsigned int bpp)365 static unsigned int rgb_c_init (convert_rgb_c_t * id,
366 				mpeg2convert_rgb_order_t order,
367 				unsigned int bpp)
368 {
369     int i;
370     uint8_t table_Y[1024];
371     uint32_t * table_32 = 0;
372     uint16_t * table_16 = 0;
373     uint8_t * table_8 = 0;
374     uint8_t * table_332 = 0;
375     int entry_size = 0;
376     void * table_r = 0;
377     void * table_g = 0;
378     void * table_b = 0;
379 
380     int crv = Inverse_Table_6_9[matrix_coefficients][0];
381     int cbu = Inverse_Table_6_9[matrix_coefficients][1];
382     int cgu = -Inverse_Table_6_9[matrix_coefficients][2];
383     int cgv = -Inverse_Table_6_9[matrix_coefficients][3];
384 
385     for (i = 0; i < 1024; i++) {
386 	int j;
387 
388 	j = (76309 * (i - 384 - 16) + 32768) >> 16;
389 	table_Y[i] = (j < 0) ? 0 : ((j > 255) ? 255 : j);
390     }
391 
392     switch (bpp) {
393     case 32:
394 	if (!id)
395 	    return (197 + 2*682 + 256 + 132) * sizeof (uint32_t);
396 	table_32 = (uint32_t *) (id + 1);
397 	entry_size = sizeof (uint32_t);
398 	table_r = table_32 + 197;
399 	table_b = table_32 + 197 + 685;
400 	table_g = table_32 + 197 + 2*682;
401 
402 	for (i = -197; i < 256+197; i++)
403 	    ((uint32_t *) table_r)[i] =
404 		table_Y[i+384] << ((order == MPEG2CONVERT_RGB) ? 16 : 0);
405 	for (i = -132; i < 256+132; i++)
406 	    ((uint32_t *) table_g)[i] = table_Y[i+384] << 8;
407 	for (i = -232; i < 256+232; i++)
408 	    ((uint32_t *) table_b)[i] =
409 		table_Y[i+384] << ((order == MPEG2CONVERT_RGB) ? 0 : 16);
410 	break;
411 
412     case 24:
413 	if (!id)
414 	    return (256 + 2*232) * sizeof (uint8_t);
415 	table_8 = (uint8_t *) (id + 1);
416 	entry_size = sizeof (uint8_t);
417 	table_r = table_g = table_b = table_8 + 232;
418 
419 	for (i = -232; i < 256+232; i++)
420 	    ((uint8_t * )table_b)[i] = table_Y[i+384];
421 	break;
422 
423     case 15:
424     case 16:
425 	if (!id)
426 	    return (197 + 2*682 + 256 + 132) * sizeof (uint16_t);
427 	table_16 = (uint16_t *) (id + 1);
428 	entry_size = sizeof (uint16_t);
429 	table_r = table_16 + 197;
430 	table_b = table_16 + 197 + 685;
431 	table_g = table_16 + 197 + 2*682;
432 
433 	for (i = -197; i < 256+197; i++) {
434 	    int j = table_Y[i+384] >> 3;
435 
436 	    if (order == MPEG2CONVERT_RGB)
437 		j <<= ((bpp==16) ? 11 : 10);
438 
439 	    ((uint16_t *)table_r)[i] = j;
440 	}
441 	for (i = -132; i < 256+132; i++) {
442 	    int j = table_Y[i+384] >> ((bpp==16) ? 2 : 3);
443 
444 	    ((uint16_t *)table_g)[i] = j << 5;
445 	}
446 	for (i = -232; i < 256+232; i++) {
447 	    int j = table_Y[i+384] >> 3;
448 
449 	    if (order == MPEG2CONVERT_BGR)
450 		j <<= ((bpp==16) ? 11 : 10);
451 
452 	    ((uint16_t *)table_b)[i] = j;
453 	}
454 	break;
455 
456     case 8:
457 	if (!id)
458 	    return (197 + 2*682 + 256 + 232 + 71) * sizeof (uint8_t);
459 	table_332 = (uint8_t *) (id + 1);
460 	entry_size = sizeof (uint8_t);
461 	table_r = table_332 + 197;
462 	table_g = table_332 + 197 + 682 + 30;
463 	table_b = table_332 + 197 + 2*682;
464 
465 	for (i = -197; i < 256+197+30; i++)
466 	    ((uint8_t *)table_r)[i] = ((table_Y[i+384] * 7 / 255) <<
467 				       (order == MPEG2CONVERT_RGB ? 5 : 0));
468 	for (i = -132; i < 256+132+30; i++)
469 	    ((uint8_t *)table_g)[i-30] = ((table_Y[i+384] * 7 / 255) <<
470 					  (order == MPEG2CONVERT_RGB ? 2 : 3));
471 	for (i = -232; i < 256+232+71; i++)
472 	    ((uint8_t *)table_b)[i] = ((table_Y[i+384] / 85) <<
473 				       (order == MPEG2CONVERT_RGB ? 0 : 6));
474 	break;
475     }
476 
477     for (i = 0; i < 256; i++) {
478 	id->table_rV[i] = (((uint8_t *)table_r) +
479 			   entry_size * div_round (crv * (i-128), 76309));
480 	id->table_gU[i] = (((uint8_t *)table_g) +
481 			   entry_size * div_round (cgu * (i-128), 76309));
482 	id->table_gV[i] = entry_size * div_round (cgv * (i-128), 76309);
483 	id->table_bU[i] = (((uint8_t *)table_b) +
484 			   entry_size * div_round (cbu * (i-128), 76309));
485     }
486 
487     return 0;
488 }
489 
rgb_internal(mpeg2convert_rgb_order_t order,unsigned int bpp,int stage,void * _id,const mpeg2_sequence_t * seq,int stride,uint32_t accel,void * arg,mpeg2_convert_init_t * result)490 static int rgb_internal (mpeg2convert_rgb_order_t order, unsigned int bpp,
491 			 int stage, void * _id, const mpeg2_sequence_t * seq,
492 			 int stride, uint32_t accel, void * arg,
493 			 mpeg2_convert_init_t * result)
494 {
495     convert_rgb_t * id = (convert_rgb_t *) _id;
496     mpeg2convert_copy_t * copy = (mpeg2convert_copy_t *) 0;
497     unsigned int id_size = sizeof (convert_rgb_t);
498     int chroma420 = (seq->chroma_height < seq->height);
499     int convert420 = 0;
500     int rgb_stride_min = ((bpp + 7) >> 3) * seq->width;
501 
502 #ifdef ARCH_X86
503     if (!copy && (accel & MPEG2_ACCEL_X86_MMXEXT)) {
504 	convert420 = 0;
505 	copy = mpeg2convert_rgb_mmxext (order, bpp, seq);
506     }
507     if (!copy && (accel & MPEG2_ACCEL_X86_MMX)) {
508 	convert420 = 0;
509 	copy = mpeg2convert_rgb_mmx (order, bpp, seq);
510     }
511 #endif
512 #ifdef ARCH_SPARC
513     if (!copy && (accel & MPEG2_ACCEL_SPARC_VIS)) {
514 	convert420 = chroma420;
515 	copy = mpeg2convert_rgb_vis (order, bpp, seq);
516     }
517 #endif
518     if (!copy) {
519 	int src, dest;
520 	static void (* rgb_c[3][5]) (void *, uint8_t * const *,
521 				     unsigned int) =
522 	    {{rgb_c_24_bgr_420, rgb_c_8_420, rgb_c_16_420,
523 	      rgb_c_24_rgb_420, rgb_c_32_420},
524 	     {rgb_c_24_bgr_422, rgb_c_8_422, rgb_c_16_422,
525 	      rgb_c_24_rgb_422, rgb_c_32_422},
526 	     {rgb_c_24_bgr_444, rgb_c_8_444, rgb_c_16_444,
527 	      rgb_c_24_rgb_444, rgb_c_32_444}};
528 
529 	convert420 = chroma420;
530 	id_size = (sizeof (convert_rgb_c_t) +
531 		   rgb_c_init ((convert_rgb_c_t *) id, order, bpp));
532 	src = ((seq->chroma_width == seq->width) +
533 	       (seq->chroma_height == seq->height));
534 	dest = ((bpp == 24 && order == MPEG2CONVERT_BGR) ? 0 : (bpp + 7) >> 3);
535 	copy = rgb_c[src][dest];
536     }
537 
538     result->id_size = id_size;
539 
540     if (stride < rgb_stride_min)
541 	stride = rgb_stride_min;
542 
543     if (stage == MPEG2_CONVERT_STRIDE)
544 	return stride;
545     else if (stage == MPEG2_CONVERT_START) {
546 	id->width = seq->width >> 3;
547 	id->y_stride_frame = seq->width;
548 	id->uv_stride_frame = seq->chroma_width;
549 	id->rgb_stride_frame = stride;
550 	id->rgb_stride_min = rgb_stride_min;
551 	id->chroma420 = chroma420;
552 	id->convert420 = convert420;
553 	result->buf_size[0] = stride * seq->height;
554 	result->buf_size[1] = result->buf_size[2] = 0;
555 	result->start = rgb_start;
556 	result->copy = copy;
557     }
558     return 0;
559 }
560 
561 #define DECLARE(func,order,bpp)						\
562 int func (int stage, void * id,						\
563 	  const mpeg2_sequence_t * sequence, int stride,		\
564 	  uint32_t accel, void * arg, mpeg2_convert_init_t * result)	\
565 {									\
566     return rgb_internal (order, bpp, stage, id, sequence, stride,	\
567 			 accel, arg, result);				\
568 }
569 
570 DECLARE (mpeg2convert_rgb32, MPEG2CONVERT_RGB, 32)
571 DECLARE (mpeg2convert_rgb24, MPEG2CONVERT_RGB, 24)
572 DECLARE (mpeg2convert_rgb16, MPEG2CONVERT_RGB, 16)
573 DECLARE (mpeg2convert_rgb15, MPEG2CONVERT_RGB, 15)
574 DECLARE (mpeg2convert_rgb8, MPEG2CONVERT_RGB, 8)
575 DECLARE (mpeg2convert_bgr32, MPEG2CONVERT_BGR, 32)
576 DECLARE (mpeg2convert_bgr24, MPEG2CONVERT_BGR, 24)
577 DECLARE (mpeg2convert_bgr16, MPEG2CONVERT_BGR, 16)
578 DECLARE (mpeg2convert_bgr15, MPEG2CONVERT_BGR, 15)
579 DECLARE (mpeg2convert_bgr8, MPEG2CONVERT_BGR, 8)
580 
mpeg2convert_rgb(mpeg2convert_rgb_order_t order,unsigned int bpp)581 mpeg2_convert_t * mpeg2convert_rgb (mpeg2convert_rgb_order_t order,
582 				    unsigned int bpp)
583 {
584     static mpeg2_convert_t * table[5][2] =
585 	{{mpeg2convert_rgb15, mpeg2convert_bgr15},
586 	 {mpeg2convert_rgb8, mpeg2convert_bgr8},
587 	 {mpeg2convert_rgb16, mpeg2convert_bgr16},
588 	 {mpeg2convert_rgb24, mpeg2convert_bgr24},
589 	 {mpeg2convert_rgb32, mpeg2convert_bgr32}};
590 
591     if (order == MPEG2CONVERT_RGB || order == MPEG2CONVERT_BGR) {
592 	if (bpp == 15)
593 	    return table[0][order == MPEG2CONVERT_BGR];
594 	else if (bpp >= 8 && bpp <= 32 && (bpp & 7) == 0)
595 	    return table[bpp >> 3][order == MPEG2CONVERT_BGR];
596     }
597     return (mpeg2_convert_t *) 0;
598 }
599