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