Rev 1085 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1085 | pj | 1 | /* store.c, picture output routines */ |
2 | |||
3 | /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ |
||
4 | |||
5 | /* |
||
6 | * Disclaimer of Warranty |
||
7 | * |
||
8 | * These software programs are available to the user without any license fee or |
||
9 | * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims |
||
10 | * any and all warranties, whether express, implied, or statuary, including any |
||
11 | * implied warranties or merchantability or of fitness for a particular |
||
12 | * purpose. In no event shall the copyright-holder be liable for any |
||
13 | * incidental, punitive, or consequential damages of any kind whatsoever |
||
14 | * arising from the use of these programs. |
||
15 | * |
||
16 | * This disclaimer of warranty extends to the user of these programs and user's |
||
17 | * customers, employees, agents, transferees, successors, and assigns. |
||
18 | * |
||
19 | * The MPEG Software Simulation Group does not represent or warrant that the |
||
20 | * programs furnished hereunder are free of infringement of any third-party |
||
21 | * patents. |
||
22 | * |
||
23 | * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, |
||
24 | * are subject to royalty fees to patent holders. Many of these patents are |
||
25 | * general enough such that they are unavoidable regardless of implementation |
||
26 | * design. |
||
27 | * |
||
28 | */ |
||
29 | |||
30 | #include <stdio.h> |
||
31 | #include <stdlib.h> |
||
32 | #include <fcntl.h> |
||
33 | |||
34 | #include "config.h" |
||
35 | #include "global.h" |
||
36 | #include "semaphore.h" |
||
37 | #include "kernel/kern.h" |
||
38 | |||
39 | //#debug DEBUG_MAILBOX |
||
40 | |||
41 | static void conv422to444 _ANSI_ARGS_((unsigned char *src, unsigned char *dst)); |
||
42 | static void conv420to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst)); |
||
43 | |||
44 | __inline__ WORD down32to16(unsigned char r, unsigned char g, unsigned char b) |
||
45 | { |
||
46 | return ((b&0xf8)>>3)|((g&0xfc)<<3)|((r&0xf8)<<8); |
||
47 | } |
||
48 | |||
49 | #if 0 |
||
50 | void xWrite_Frame _ANSI_ARGS_((unsigned char *src[], int frame)) |
||
51 | { |
||
52 | int i, j; |
||
53 | int y, u, v, r, g, b; |
||
54 | // int rm=0,gm=0,bm=0; |
||
55 | int crv, cbu, cgu, cgv; |
||
56 | unsigned char *py, *pu, *pv; |
||
57 | int height, width; |
||
58 | |||
59 | struct framebuf_struct *f; |
||
60 | |||
61 | cprintf("%d ",frame); |
||
62 | |||
63 | width = Coded_Picture_Width ; |
||
64 | height= Coded_Picture_Height; |
||
65 | |||
66 | f = get_free_framebuf(); |
||
67 | |||
68 | dither(src); |
||
69 | f->f[i*width+j] = down32to16(r,g,b); |
||
70 | |||
71 | f->n = frame; |
||
72 | insert_frame(f); |
||
73 | } |
||
74 | #endif |
||
75 | |||
76 | void Write_Frame _ANSI_ARGS_((unsigned char *src[], int frame)) |
||
77 | { |
||
78 | int i, j; |
||
79 | int y, u, v, r, g, b; |
||
80 | // int rm=0,gm=0,bm=0; |
||
81 | int crv, cbu, cgu, cgv; |
||
82 | unsigned char *py, *pu, *pv; |
||
83 | int height, width, incr; |
||
84 | static unsigned char *u422, *v422, *u444, *v444; |
||
85 | |||
86 | struct framebuf_struct *f; |
||
87 | |||
88 | cprintf("%d ",frame); |
||
89 | |||
90 | incr = width = Coded_Picture_Width ; |
||
91 | height= Coded_Picture_Height; |
||
92 | |||
93 | if (chroma_format==CHROMA444) |
||
94 | { |
||
95 | u444 = src[1]; |
||
96 | v444 = src[2]; |
||
97 | } |
||
98 | else |
||
99 | { |
||
100 | if (!u444) |
||
101 | { |
||
102 | if (chroma_format==CHROMA420) |
||
103 | { |
||
104 | if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1) |
||
105 | *Coded_Picture_Height))) |
||
106 | Error("malloc failed"); |
||
107 | if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1) |
||
108 | *Coded_Picture_Height))) |
||
109 | Error("malloc failed"); |
||
110 | } |
||
111 | |||
112 | if (!(u444 = (unsigned char *)malloc(Coded_Picture_Width |
||
113 | *Coded_Picture_Height))) |
||
114 | Error("malloc failed"); |
||
115 | |||
116 | if (!(v444 = (unsigned char *)malloc(Coded_Picture_Width |
||
117 | *Coded_Picture_Height))) |
||
118 | Error("malloc failed"); |
||
119 | } |
||
120 | |||
121 | if (chroma_format==CHROMA420) |
||
122 | { |
||
123 | conv420to422(src[1],u422); |
||
124 | conv420to422(src[2],v422); |
||
125 | conv422to444(u422,u444); |
||
126 | conv422to444(v422,v444); |
||
127 | } |
||
128 | else |
||
129 | { |
||
130 | conv422to444(src[1],u444); |
||
131 | conv422to444(src[2],v444); |
||
132 | } |
||
133 | } |
||
134 | |||
135 | |||
136 | f = get_free_framebuf(); |
||
137 | |||
138 | /* matrix coefficients */ |
||
139 | crv = Inverse_Table_6_9[matrix_coefficients][0]; |
||
140 | cbu = Inverse_Table_6_9[matrix_coefficients][1]; |
||
141 | cgu = Inverse_Table_6_9[matrix_coefficients][2]; |
||
142 | cgv = Inverse_Table_6_9[matrix_coefficients][3]; |
||
143 | |||
144 | for (i=0; i<height; i++) |
||
145 | { |
||
146 | py = src[0] + incr*i; |
||
147 | pu = u444 + incr*i; |
||
148 | pv = v444 + incr*i; |
||
149 | |||
150 | for (j=0; j<width; j++) |
||
151 | { |
||
152 | u = *pu++ - 128; |
||
153 | v = *pv++ - 128; |
||
154 | y = 76309 * (*py++ - 16); /* (255/219)*65536 */ |
||
155 | |||
156 | r = Clip[(y + crv*v + 32768)>>16]; |
||
157 | g = Clip[(y - cgu*u - cgv*v + 32768)>>16]; |
||
158 | b = Clip[(y + cbu*u + 32786)>>16]; |
||
159 | |||
160 | // rm = max(rm,r);gm=max(gm,g);bm=max(bm,b); |
||
161 | // cprintf("(r%dg%db%d)",rm,gm,bm); |
||
162 | f->f[i*width+j] = down32to16(r,g,b); |
||
163 | // r=g=b=rand()%255; |
||
164 | // f->f[i*width+j] = down32to16(r,g,b); |
||
165 | } |
||
166 | } |
||
167 | |||
168 | f->n = frame; |
||
169 | insert_frame(f); |
||
170 | } |
||
171 | |||
172 | /* |
||
173 | void Display_Image(Dithered_Image) |
||
174 | unsigned char *Dithered_Image; |
||
175 | { |
||
176 | / * display dithered image */ |
||
177 | //} |
||
178 | |||
179 | |||
180 | /* horizontal 1:2 interpolation filter */ |
||
181 | static void conv422to444(src,dst) |
||
182 | unsigned char *src,*dst; |
||
183 | { |
||
184 | int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3; |
||
185 | |||
186 | w = Coded_Picture_Width>>1; |
||
187 | |||
188 | if (base.MPEG2_Flag) |
||
189 | { |
||
190 | for (j=0; j<Coded_Picture_Height; j++) |
||
191 | { |
||
192 | for (i=0; i<w; i++) |
||
193 | { |
||
194 | i2 = i<<1; |
||
195 | im2 = (i<2) ? 0 : i-2; |
||
196 | im1 = (i<1) ? 0 : i-1; |
||
197 | ip1 = (i<w-1) ? i+1 : w-1; |
||
198 | ip2 = (i<w-2) ? i+2 : w-1; |
||
199 | ip3 = (i<w-3) ? i+3 : w-1; |
||
200 | |||
201 | /* FIR filter coefficients (*256): 21 0 -52 0 159 256 159 0 -52 0 21 */ |
||
202 | /* even samples (0 0 256 0 0) */ |
||
203 | dst[i2] = src[i]; |
||
204 | |||
205 | /* odd samples (21 -52 159 159 -52 21) */ |
||
206 | dst[i2+1] = Clip[(int)(21*(src[im2]+src[ip3]) |
||
207 | -52*(src[im1]+src[ip2]) |
||
208 | +159*(src[i]+src[ip1])+128)>>8]; |
||
209 | } |
||
210 | src+= w; |
||
211 | dst+= Coded_Picture_Width; |
||
212 | } |
||
213 | } |
||
214 | else |
||
215 | { |
||
216 | for (j=0; j<Coded_Picture_Height; j++) |
||
217 | { |
||
218 | for (i=0; i<w; i++) |
||
219 | { |
||
220 | |||
221 | i2 = i<<1; |
||
222 | im3 = (i<3) ? 0 : i-3; |
||
223 | im2 = (i<2) ? 0 : i-2; |
||
224 | im1 = (i<1) ? 0 : i-1; |
||
225 | ip1 = (i<w-1) ? i+1 : w-1; |
||
226 | ip2 = (i<w-2) ? i+2 : w-1; |
||
227 | ip3 = (i<w-3) ? i+3 : w-1; |
||
228 | |||
229 | /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */ |
||
230 | dst[i2] = Clip[(int)( 5*src[im3] |
||
231 | -21*src[im2] |
||
232 | +70*src[im1] |
||
233 | +228*src[i] |
||
234 | -37*src[ip1] |
||
235 | +11*src[ip2]+128)>>8]; |
||
236 | |||
237 | dst[i2+1] = Clip[(int)( 5*src[ip3] |
||
238 | -21*src[ip2] |
||
239 | +70*src[ip1] |
||
240 | +228*src[i] |
||
241 | -37*src[im1] |
||
242 | +11*src[im2]+128)>>8]; |
||
243 | } |
||
244 | src+= w; |
||
245 | dst+= Coded_Picture_Width; |
||
246 | } |
||
247 | } |
||
248 | } |
||
249 | |||
250 | /* vertical 1:2 interpolation filter */ |
||
251 | static void conv420to422(src,dst) |
||
252 | unsigned char *src,*dst; |
||
253 | { |
||
254 | int w, h, i, j, j2; |
||
255 | int jm6, jm5, jm4, jm3, jm2, jm1, jp1, jp2, jp3, jp4, jp5, jp6, jp7; |
||
256 | |||
257 | w = Coded_Picture_Width>>1; |
||
258 | h = Coded_Picture_Height>>1; |
||
259 | |||
260 | if (progressive_frame) |
||
261 | { |
||
262 | /* intra frame */ |
||
263 | for (i=0; i<w; i++) |
||
264 | { |
||
265 | for (j=0; j<h; j++) |
||
266 | { |
||
267 | j2 = j<<1; |
||
268 | jm3 = (j<3) ? 0 : j-3; |
||
269 | jm2 = (j<2) ? 0 : j-2; |
||
270 | jm1 = (j<1) ? 0 : j-1; |
||
271 | jp1 = (j<h-1) ? j+1 : h-1; |
||
272 | jp2 = (j<h-2) ? j+2 : h-1; |
||
273 | jp3 = (j<h-3) ? j+3 : h-1; |
||
274 | |||
275 | /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */ |
||
276 | /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */ |
||
277 | dst[w*j2] = Clip[(int)( 3*src[w*jm3] |
||
278 | -16*src[w*jm2] |
||
279 | +67*src[w*jm1] |
||
280 | +227*src[w*j] |
||
281 | -32*src[w*jp1] |
||
282 | +7*src[w*jp2]+128)>>8]; |
||
283 | |||
284 | dst[w*(j2+1)] = Clip[(int)( 3*src[w*jp3] |
||
285 | -16*src[w*jp2] |
||
286 | +67*src[w*jp1] |
||
287 | +227*src[w*j] |
||
288 | -32*src[w*jm1] |
||
289 | +7*src[w*jm2]+128)>>8]; |
||
290 | } |
||
291 | src++; |
||
292 | dst++; |
||
293 | } |
||
294 | } |
||
295 | else |
||
296 | { |
||
297 | /* intra field */ |
||
298 | for (i=0; i<w; i++) |
||
299 | { |
||
300 | for (j=0; j<h; j+=2) |
||
301 | { |
||
302 | j2 = j<<1; |
||
303 | |||
304 | /* top field */ |
||
305 | jm6 = (j<6) ? 0 : j-6; |
||
306 | jm4 = (j<4) ? 0 : j-4; |
||
307 | jm2 = (j<2) ? 0 : j-2; |
||
308 | jp2 = (j<h-2) ? j+2 : h-2; |
||
309 | jp4 = (j<h-4) ? j+4 : h-2; |
||
310 | jp6 = (j<h-6) ? j+6 : h-2; |
||
311 | |||
312 | /* Polyphase FIR filter coefficients (*256): 2 -10 35 242 -18 5 */ |
||
313 | /* New polyphase FIR filter coefficients (*256): 1 -7 30 248 -21 5 */ |
||
314 | dst[w*j2] = Clip[(int)( 1*src[w*jm6] |
||
315 | -7*src[w*jm4] |
||
316 | +30*src[w*jm2] |
||
317 | +248*src[w*j] |
||
318 | -21*src[w*jp2] |
||
319 | +5*src[w*jp4]+128)>>8]; |
||
320 | |||
321 | /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */ |
||
322 | /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */ |
||
323 | dst[w*(j2+2)] = Clip[(int)( 7*src[w*jm4] |
||
324 | -35*src[w*jm2] |
||
325 | +194*src[w*j] |
||
326 | +110*src[w*jp2] |
||
327 | -24*src[w*jp4] |
||
328 | +4*src[w*jp6]+128)>>8]; |
||
329 | |||
330 | /* bottom field */ |
||
331 | jm5 = (j<5) ? 1 : j-5; |
||
332 | jm3 = (j<3) ? 1 : j-3; |
||
333 | jm1 = (j<1) ? 1 : j-1; |
||
334 | jp1 = (j<h-1) ? j+1 : h-1; |
||
335 | jp3 = (j<h-3) ? j+3 : h-1; |
||
336 | jp5 = (j<h-5) ? j+5 : h-1; |
||
337 | jp7 = (j<h-7) ? j+7 : h-1; |
||
338 | |||
339 | /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */ |
||
340 | /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */ |
||
341 | dst[w*(j2+1)] = Clip[(int)( 7*src[w*jp5] |
||
342 | -35*src[w*jp3] |
||
343 | +194*src[w*jp1] |
||
344 | +110*src[w*jm1] |
||
345 | -24*src[w*jm3] |
||
346 | +4*src[w*jm5]+128)>>8]; |
||
347 | |||
348 | dst[w*(j2+3)] = Clip[(int)( 1*src[w*jp7] |
||
349 | -7*src[w*jp5] |
||
350 | +30*src[w*jp3] |
||
351 | +248*src[w*jp1] |
||
352 | -21*src[w*jm1] |
||
353 | +5*src[w*jm3]+128)>>8]; |
||
354 | } |
||
355 | src++; |
||
356 | dst++; |
||
357 | } |
||
358 | } |
||
359 | } |
||
360 | |||
361 | |||
362 | |||
363 | |||
364 | |||
365 | // Frame buffer for displaying pictures |
||
366 | |||
367 | struct framebuf_struct *get_free_framebuf(); |
||
368 | void insert_frame(struct framebuf_struct *f); |
||
369 | struct framebuf_struct *remove_frame(); |
||
370 | |||
371 | int framebuf_sz; |
||
372 | |||
373 | // a queue of framebufs |
||
374 | struct framebuf_struct *framebuf_first; |
||
375 | struct framebuf_struct *framebuf_last; |
||
376 | |||
377 | // free framebuf list |
||
378 | struct framebuf_struct *framebuf_free; |
||
379 | |||
380 | // some semaphores |
||
381 | sem_t framebuf_sem; |
||
382 | sem_t framebuf_count; |
||
383 | sem_t framebuf_freecount; |
||
384 | |||
385 | void allocate_framebuf() |
||
386 | { |
||
387 | struct framebuf_struct *f; |
||
388 | |||
389 | f = (struct framebuf_struct *)malloc(sizeof(struct framebuf_struct)); |
||
390 | if (!f) { |
||
391 | cputs("Not enough memory!!!\n"); |
||
392 | sys_end(); |
||
393 | } |
||
394 | |||
395 | f->f = (WORD *)malloc(framebuf_sz); |
||
396 | if (!f->f) { |
||
397 | cputs("Not enough memory for buffer!!!\n"); |
||
398 | sys_end(); |
||
399 | } |
||
400 | |||
401 | f->next = framebuf_free; |
||
402 | framebuf_free = f; |
||
403 | cprintf("(Alloc %d %d)\n",f,f->f); |
||
404 | } |
||
405 | |||
406 | void Initialize_framebuf(int sz) |
||
407 | { |
||
408 | int i; |
||
409 | |||
410 | framebuf_first = NULL; |
||
411 | framebuf_last = NULL; |
||
412 | framebuf_free = NULL; |
||
413 | framebuf_sz = sz; |
||
414 | |||
415 | cprintf("Coded W=%d H=%d sz=%d\n",Coded_Picture_Width,Coded_Picture_Height,sz); |
||
416 | |||
417 | for (i=0; i<MAX_FRAMEBUF; i++) |
||
418 | allocate_framebuf(); |
||
419 | |||
420 | sem_init(&framebuf_sem,0,1); |
||
421 | sem_init(&framebuf_count,0,0); |
||
422 | sem_init(&framebuf_freecount,0,MAX_FRAMEBUF); |
||
423 | } |
||
424 | |||
425 | struct framebuf_struct *get_free_framebuf() |
||
426 | { |
||
427 | struct framebuf_struct *f; |
||
428 | |||
429 | #ifdef DEBUG_MAILBOX |
||
430 | cprintf("G"); |
||
431 | #endif |
||
432 | sem_wait(&framebuf_freecount); |
||
433 | sem_wait(&framebuf_sem); |
||
434 | |||
435 | //if (!framebuf_free) |
||
436 | // allocate_framebuf(); |
||
437 | |||
438 | f = framebuf_free; |
||
439 | |||
440 | framebuf_free = framebuf_free->next; |
||
441 | |||
442 | sem_post(&framebuf_sem); |
||
443 | |||
444 | return f; |
||
445 | } |
||
446 | |||
447 | void insert_frame(struct framebuf_struct *f) |
||
448 | { |
||
449 | struct framebuf_struct *p, *q; |
||
450 | int n; |
||
451 | |||
452 | #ifdef DEBUG_MAILBOX |
||
453 | cprintf("I"); |
||
454 | #endif |
||
455 | sem_wait(&framebuf_sem); |
||
456 | |||
457 | p = NULL; |
||
458 | q = framebuf_first; |
||
459 | n = f->n; |
||
460 | |||
461 | while ((q != NULL) && (n >= q->n)) { |
||
462 | p = q; |
||
463 | q = q->next; |
||
464 | } |
||
465 | |||
466 | if (p) |
||
467 | p->next = f; |
||
468 | else |
||
469 | framebuf_first = f; |
||
470 | |||
471 | if (q) |
||
472 | q->prev = f; |
||
473 | else |
||
474 | framebuf_last = f; |
||
475 | |||
476 | f->next = q; |
||
477 | f->prev = p; |
||
478 | |||
479 | sem_post(&framebuf_count); |
||
480 | sem_post(&framebuf_sem); |
||
481 | } |
||
482 | |||
483 | struct framebuf_struct *remove_frame() |
||
484 | { |
||
485 | struct framebuf_struct *f; |
||
486 | |||
487 | #ifdef DEBUG_MAILBOX |
||
488 | cprintf("R"); |
||
489 | #endif |
||
490 | sem_wait(&framebuf_count); |
||
491 | sem_wait(&framebuf_sem); |
||
492 | |||
493 | |||
494 | // remove the first frame |
||
495 | f = framebuf_first; |
||
496 | |||
497 | if (!f) |
||
498 | sys_abort(69); // should never happen |
||
499 | |||
500 | framebuf_first = framebuf_first->next; |
||
501 | |||
502 | if (framebuf_first) |
||
503 | framebuf_first->prev = NULL; |
||
504 | else |
||
505 | framebuf_last = NULL; |
||
506 | |||
507 | sem_post(&framebuf_sem); |
||
508 | |||
509 | return f; |
||
510 | } |
||
511 | |||
512 | void give_back_framebuf(struct framebuf_struct *f) |
||
513 | { |
||
514 | #ifdef DEBUG_MAILBOX |
||
515 | cprintf("B"); |
||
516 | #endif |
||
517 | sem_wait(&framebuf_sem); |
||
518 | |||
519 | f->next = framebuf_free; |
||
520 | framebuf_free = f; |
||
521 | |||
522 | sem_post(&framebuf_sem); |
||
523 | sem_post(&framebuf_freecount); |
||
524 | } |
||
525 | |||
526 | |||
527 | |||
528 | |||
529 |