1 /* display.c, X11 interface */
2
3 /*
4 * All modifications (mpeg2decode -> mpeg2play) are
5 * Copyright (C) 1994, Stefan Eckart. All Rights Reserved.
6 */
7
8 /* Copyright (C) 1994, MPEG Software Simulation Group. All Rights Reserved. */
9
10 /*
11 * Disclaimer of Warranty
12 *
13 * These software programs are available to the user without any license fee or
14 * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims
15 * any and all warranties, whether express, implied, or statuary, including any
16 * implied warranties or merchantability or of fitness for a particular
17 * purpose. In no event shall the copyright-holder be liable for any
18 * incidental, punitive, or consequential damages of any kind whatsoever
19 * arising from the use of these programs.
20 *
21 * This disclaimer of warranty extends to the user of these programs and user's
22 * customers, employees, agents, transferees, successors, and assigns.
23 *
24 * The MPEG Software Simulation Group does not represent or warrant that the
25 * programs furnished hereunder are free of infringement of any third-party
26 * patents.
27 *
28 * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
29 * are subject to royalty fees to patent holders. Many of these patents are
30 * general enough such that they are unavoidable regardless of implementation
31 * design.
32 *
33 */
34
35 /* the Xlib interface is closely modeled after
36 * mpeg_play 2.0 by the Berkeley Plateau Research Group
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41
42 #include <X11/Xlib.h>
43 #include <X11/Xutil.h>
44 #include <Xm/Xm.h>
45
46 #include "config.h"
47 #include "global.h"
48
49 /* private prototypes */
50 static void display_image _ANSI_ARGS_((XImage *ximage, unsigned char *dithered_image));
51 static void ditherframe _ANSI_ARGS_((unsigned char *src[]));
52 static void dithertop _ANSI_ARGS_((unsigned char *src[], unsigned char *dst));
53 static void ditherbot _ANSI_ARGS_((unsigned char *src[], unsigned char *dst));
54 static void ditherframe444 _ANSI_ARGS_((unsigned char *src[]));
55 static void dithertop444 _ANSI_ARGS_((unsigned char *src[], unsigned char *dst));
56 static void ditherbot444 _ANSI_ARGS_((unsigned char *src[], unsigned char *dst));
57
58 /* local data */
59 static unsigned char *dithered_image, *dithered_image2;
60
61 static unsigned char ytab[16*(256+16)];
62 static unsigned char uvtab[256*269+270];
63
64 /* X11 related variables */
65 static Display *display;
66 /* static Window window; */
67 /* extern Window window; */
68 extern Widget toplevel, picW;
69 static GC gc;
70 static XImage *ximage, *ximage2;
71 static unsigned char pixel[256];
72
73 #ifdef SH_MEM
74
75 #include <sys/ipc.h>
76 #include <sys/shm.h>
77 #include <X11/extensions/XShm.h>
78
79 static int HandleXError _ANSI_ARGS_((Display *dpy, XErrorEvent *event));
80 static void InstallXErrorHandler _ANSI_ARGS_((void));
81 static void DeInstallXErrorHandler _ANSI_ARGS_((void));
82
83 static int shmem_flag;
84 static XShmSegmentInfo shminfo1, shminfo2;
85 static int gXErrorFlag;
86 static int CompletionType = -1;
87
HandleXError(dpy,event)88 static int HandleXError(dpy, event)
89 Display *dpy;
90 XErrorEvent *event;
91 {
92 gXErrorFlag = 1;
93
94 return 0;
95 }
96
InstallXErrorHandler()97 static void InstallXErrorHandler()
98 {
99 XSetErrorHandler(HandleXError);
100 XFlush(display);
101 }
102
DeInstallXErrorHandler()103 static void DeInstallXErrorHandler()
104 {
105 XSetErrorHandler(NULL);
106 XFlush(display);
107 }
108
109 #endif
110
111 /* connect to server, create and map window,
112 * allocate colors and (shared) memory
113 */
init_display(name)114 void init_display(name)
115 char *name;
116 {
117 int crv, cbu, cgu, cgv;
118 int y, u, v, r, g, b;
119 int i;
120 char dummy;
121 int screen;
122 Colormap cmap;
123 int private;
124 XColor xcolor;
125 unsigned int fg, bg;
126 char *hello = "MPEG-2 Display";
127 XSizeHints hint;
128 XVisualInfo vinfo;
129 XEvent xev;
130 unsigned long tmp_pixel;
131 XWindowAttributes xwa;
132
133 display = XOpenDisplay(name);
134
135 if (display == NULL)
136 error("Can not open display\n");
137
138 screen = DefaultScreen(display);
139
140 /*
141 hint.x = 200;
142 hint.y = 200;
143 hint.width = horizontal_size;
144 hint.height = vertical_size;
145 hint.flags = PPosition | PSize;
146
147 /* Get some colors */
148
149 fg = WhitePixel (display, screen);
150 bg = BlackPixel (display, screen);
151
152 /* Make the window */
153
154 if (!XMatchVisualInfo(display, screen, 8, PseudoColor, &vinfo))
155 {
156 if (!XMatchVisualInfo(display, screen, 8, GrayScale, &vinfo))
157 error("requires 8 bit display\n");
158 }
159
160 /*
161 window = XCreateSimpleWindow (display, DefaultRootWindow (display),
162 hint.x, hint.y, hint.width, hint.height, 4, fg, bg);
163 XSelectInput(display, window, StructureNotifyMask);
164
165 /* Tell other applications about this window */
166
167 /*
168 XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint);
169
170 /* Map window. */
171
172 /*
173 XMapWindow(display, window);
174
175 /* Wait for map. */
176 /*
177 do
178 {
179 XNextEvent(display, &xev);
180 }
181 while (xev.type != MapNotify || xev.xmap.event != window);
182
183 XSelectInput(display, window, NoEventMask);
184 */
185
186 /* matrix coefficients */
187 crv = convmat[matrix_coefficients][0];
188 cbu = convmat[matrix_coefficients][1];
189 cgu = convmat[matrix_coefficients][2];
190 cgv = convmat[matrix_coefficients][3];
191
192 /* allocate colors */
193 /* gc = DefaultGC(display, screen); */
194 gc = XCreateGC(display, DefaultRootWindow(display), 0, 0);
195
196 cmap = DefaultColormap(display, screen);
197 private = 0;
198
199 /* color allocation:
200 * i is the (internal) 8 bit color number, it consists of separate
201 * bit fields for Y, U and V: i = (yyyyuuvv), we don't use yyyy=0000
202 * yyyy=0001 and yyyy=1111, this leaves 48 colors for other applications
203 *
204 * the allocated colors correspond to the following Y, U and V values:
205 * Y: 40, 56, 72, 88, 104, 120, 136, 152, 168, 184, 200, 216, 232
206 * U,V: -48, -16, 16, 48
207 *
208 * U and V values span only about half the color space; this gives
209 * usually much better quality, although highly saturated colors can
210 * not be displayed properly
211 *
212 * translation to R,G,B is implicitly done by the color look-up table
213 */
214
215 xcolor.flags = DoRed | DoGreen | DoBlue;
216
217 for (i=32; i<240; i++)
218 {
219 /* color space conversion */
220 y = 16*((i>>4)&15) + 8;
221 u = 32*((i>>2)&3) - 48;
222 v = 32*(i&3) - 48;
223
224 y = 76309 * (y - 16); /* (255/219)*65536 */
225
226 r = clp[(y + crv*v + 32768)>>16];
227 g = clp[(y - cgu*u -cgv*v + 32768)>>16];
228 b = clp[(y + cbu*u + 32786)>>16];
229
230 /* X11 colors are 16 bit */
231 xcolor.red = r << 8;
232 xcolor.green = g << 8;
233 xcolor.blue = b << 8;
234
235 if (XAllocColor(display, cmap, &xcolor) != 0)
236 pixel[i] = xcolor.pixel;
237 else
238 {
239 /* allocation failed, have to use a private colormap */
240
241 if (private)
242 error("Couldn't allocate private colormap");
243
244 private = 1;
245
246 if (!quiet)
247 fprintf(stderr, "Using private colormap (%d colors were available).\n",
248 i-32);
249
250 /* Free colors. */
251 while (--i >= 32)
252 {
253 tmp_pixel = pixel[i]; /* because XFreeColors expects unsigned long */
254 XFreeColors(display, cmap, &tmp_pixel, 1, 0);
255 }
256
257 /* i is now 31, this restarts the outer loop */
258
259 /* create private colormap */
260
261 /*
262 XGetWindowAttributes(display, window, &xwa);
263 cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
264 XSetWindowColormap(display, window, cmap);
265 */
266 cmap = XCreateColormap(display, DefaultRootWindow(display),
267 DefaultVisual(display, screen), AllocNone);
268 xcolor.red = 0;
269 xcolor.blue = 0;
270 xcolor.green = 0;
271 XAllocColor(display, cmap, &xcolor);
272 xcolor.red = 0xffff;
273 xcolor.blue = 0xffff;
274 xcolor.green = 0xffff;
275 XAllocColor(display, cmap, &xcolor);
276
277 XtVaSetValues(toplevel, XmNcolormap, cmap, NULL);
278 }
279 }
280
281 #ifdef SH_MEM
282 if (XShmQueryExtension(display))
283 shmem_flag = 1;
284 else
285 {
286 shmem_flag = 0;
287 if (!quiet)
288 fprintf(stderr, "Shared memory not supported\nReverting to normal Xlib\n");
289 }
290
291 if (shmem_flag)
292 CompletionType = XShmGetEventBase(display) + ShmCompletion;
293
294 InstallXErrorHandler();
295
296 if (shmem_flag)
297 {
298
299 ximage = XShmCreateImage(display, None, 8, ZPixmap, NULL,
300 &shminfo1,
301 coded_picture_width, coded_picture_height);
302
303 if (!prog_seq)
304 ximage2 = XShmCreateImage(display, None, 8, ZPixmap, NULL,
305 &shminfo2,
306 coded_picture_width, coded_picture_height);
307
308 /* If no go, then revert to normal Xlib calls. */
309
310 if (ximage==NULL || (!prog_seq && ximage2==NULL))
311 {
312 if (ximage!=NULL)
313 XDestroyImage(ximage);
314 if (!prog_seq && ximage2!=NULL)
315 XDestroyImage(ximage2);
316 if (!quiet)
317 fprintf(stderr, "Shared memory error, disabling (Ximage error)\n");
318 goto shmemerror;
319 }
320
321 /* Success here, continue. */
322
323 shminfo1.shmid = shmget(IPC_PRIVATE,
324 ximage->bytes_per_line * ximage->height,
325 IPC_CREAT | 0777);
326 if (!prog_seq)
327 shminfo2.shmid = shmget(IPC_PRIVATE,
328 ximage2->bytes_per_line * ximage2->height,
329 IPC_CREAT | 0777);
330
331 if (shminfo1.shmid<0 || (!prog_seq && shminfo2.shmid<0))
332 {
333 XDestroyImage(ximage);
334 if (!prog_seq)
335 XDestroyImage(ximage2);
336 if (!quiet)
337 fprintf(stderr, "Shared memory error, disabling (seg id error)\n");
338 goto shmemerror;
339 }
340
341 shminfo1.shmaddr = (char *) shmat(shminfo1.shmid, 0, 0);
342 shminfo2.shmaddr = (char *) shmat(shminfo2.shmid, 0, 0);
343
344 if (shminfo1.shmaddr==((char *) -1) ||
345 (!prog_seq && shminfo2.shmaddr==((char *) -1)))
346 {
347 XDestroyImage(ximage);
348 if (shminfo1.shmaddr!=((char *) -1))
349 shmdt(shminfo1.shmaddr);
350 if (!prog_seq)
351 {
352 XDestroyImage(ximage2);
353 if (shminfo2.shmaddr!=((char *) -1))
354 shmdt(shminfo2.shmaddr);
355 }
356 if (!quiet)
357 {
358 fprintf(stderr, "Shared memory error, disabling (address error)\n");
359 }
360 goto shmemerror;
361 }
362
363 ximage->data = shminfo1.shmaddr;
364 dithered_image = (unsigned char *)ximage->data;
365 shminfo1.readOnly = False;
366 XShmAttach(display, &shminfo1);
367 if (!prog_seq)
368 {
369 ximage2->data = shminfo2.shmaddr;
370 dithered_image2 = (unsigned char *)ximage2->data;
371 shminfo2.readOnly = False;
372 XShmAttach(display, &shminfo2);
373 }
374
375 XSync(display, False);
376
377 if (gXErrorFlag)
378 {
379 /* Ultimate failure here. */
380 XDestroyImage(ximage);
381 shmdt(shminfo1.shmaddr);
382 if (!prog_seq)
383 {
384 XDestroyImage(ximage2);
385 shmdt(shminfo2.shmaddr);
386 }
387 if (!quiet)
388 fprintf(stderr, "Shared memory error, disabling.\n");
389 gXErrorFlag = 0;
390 goto shmemerror;
391 }
392 else
393 {
394 shmctl(shminfo1.shmid, IPC_RMID, 0);
395 if (!prog_seq)
396 shmctl(shminfo2.shmid, IPC_RMID, 0);
397 }
398
399 if (!quiet)
400 {
401 fprintf(stderr, "Sharing memory.\n");
402 }
403 }
404 else
405 {
406 shmemerror:
407 shmem_flag = 0;
408 #endif
409
410
411
412 ximage = XCreateImage(display,None,8,ZPixmap,0,&dummy,
413 coded_picture_width,coded_picture_height,8,0);
414
415 if (!(dithered_image = (unsigned char *)malloc(coded_picture_width*
416 coded_picture_height)))
417 error("malloc failed");
418
419 if (!prog_seq)
420 {
421 ximage2 = XCreateImage(display,None,8,ZPixmap,0,&dummy,
422 coded_picture_width,coded_picture_height,8,0);
423
424 if (!(dithered_image2 = (unsigned char *)malloc(coded_picture_width*
425 coded_picture_height)))
426 error("malloc failed");
427 }
428
429 #ifdef SH_MEM
430 }
431
432 DeInstallXErrorHandler();
433 #endif
434 }
435
exit_display()436 void exit_display()
437 {
438 #ifdef SH_MEM
439 if (shmem_flag)
440 {
441 XShmDetach(display, &shminfo1);
442 XDestroyImage(ximage);
443 shmdt(shminfo1.shmaddr);
444 if (!prog_seq)
445 {
446 XShmDetach(display, &shminfo2);
447 XDestroyImage(ximage2);
448 shmdt(shminfo2.shmaddr);
449 }
450 }
451 #endif
452 }
453
display_image(ximage,dithered_image)454 static void display_image(ximage,dithered_image)
455 XImage *ximage;
456 unsigned char *dithered_image;
457 {
458 /* display dithered image */
459 #ifdef SH_MEM
460 if (shmem_flag)
461 {
462 /* XShmPutImage(display, window, gc, ximage,
463 0, 0, 0, 0, ximage->width, ximage->height, True);
464 */
465 XShmPutImage(display, XtWindow(picW), gc, ximage, 0, 0,
466 (horizontal_size < 320)?(320-horizontal_size)/2:0,
467 (vertical_size < 200)?(200-vertical_size)/2:0,
468 horizontal_size, vertical_size, True);
469 XFlush(display);
470
471 while (1)
472 {
473 XEvent xev;
474
475 XNextEvent(display, &xev);
476 if (xev.type == CompletionType)
477 break;
478 }
479 }
480 else
481 #endif
482 {
483 ximage->data = (char *) dithered_image;
484 /*
485 XPutImage(display, window, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
486 */
487 XPutImage(display, XtWindow(picW), gc, ximage, 0, 0,
488 (horizontal_size < 320)?(320-horizontal_size)/2:0,
489 (vertical_size < 200)?(200-vertical_size)/2:0,
490 horizontal_size, vertical_size);
491 }
492 }
493
Redraw(Widget wid,XtPointer client_data,XtPointer call_data)494 void Redraw(Widget wid, XtPointer client_data, XtPointer call_data)
495 {
496 if (pict_struct==FRAME_PICTURE || secondfield)
497 display_image(ximage,dithered_image);
498 else
499 display_second_field();
500 }
501
display_second_field()502 void display_second_field()
503 {
504 display_image(ximage2,dithered_image2);
505 }
506
507 /* 4x4 ordered dither
508 *
509 * threshold pattern:
510 * 0 8 2 10
511 * 12 4 14 6
512 * 3 11 1 9
513 * 15 7 13 5
514 */
515
init_dither()516 void init_dither()
517 {
518 int i, j, v;
519 unsigned char ctab[256+32];
520
521 for (i=0; i<256+16; i++)
522 {
523 v = (i-8)>>4;
524 if (v<2)
525 v = 2;
526 else if (v>14)
527 v = 14;
528 for (j=0; j<16; j++)
529 ytab[16*i+j] = pixel[(v<<4)+j];
530 }
531
532 for (i=0; i<256+32; i++)
533 {
534 v = (i+48-128)>>5;
535 if (v<0)
536 v = 0;
537 else if (v>3)
538 v = 3;
539 ctab[i] = v;
540 }
541
542 for (i=0; i<255+15; i++)
543 for (j=0; j<255+15; j++)
544 uvtab[256*i+j]=(ctab[i+16]<<6)|(ctab[j+16]<<4)|(ctab[i]<<2)|ctab[j];
545 }
546
dither(src)547 void dither(src)
548 unsigned char *src[];
549 {
550 if (prog_seq)
551 {
552 if (chroma_format!=CHROMA444)
553 ditherframe(src);
554 else
555 ditherframe444(src);
556 }
557 else
558 {
559 if ((pict_struct==FRAME_PICTURE && topfirst) || pict_struct==BOTTOM_FIELD)
560 {
561 /* top field first */
562 if (chroma_format!=CHROMA444)
563 {
564 dithertop(src,dithered_image);
565 ditherbot(src,dithered_image2);
566 }
567 else
568 {
569 dithertop444(src,dithered_image);
570 ditherbot444(src,dithered_image2);
571 }
572 }
573 else
574 {
575 /* bottom field first */
576 if (chroma_format!=CHROMA444)
577 {
578 ditherbot(src,dithered_image);
579 dithertop(src,dithered_image2);
580 }
581 else
582 {
583 ditherbot444(src,dithered_image);
584 dithertop444(src,dithered_image2);
585 }
586 }
587 }
588
589 display_image(ximage,dithered_image);
590 }
591
592 /* only for 4:2:0 and 4:2:2! */
593
ditherframe(src)594 static void ditherframe(src)
595 unsigned char *src[];
596 {
597 int i,j;
598 unsigned int uv;
599 unsigned char *py,*pu,*pv,*dst;
600
601 py = src[0];
602 pu = src[1];
603 pv = src[2];
604 dst = dithered_image;
605
606 for (j=0; j<coded_picture_height; j+=4)
607 {
608 /* line j + 0 */
609 for (i=0; i<coded_picture_width; i+=8)
610 {
611 uv = uvtab[(*pu++<<8)|*pv++];
612 *dst++ = ytab[((*py++)<<4)|(uv&15)];
613 *dst++ = ytab[((*py++ +8)<<4)|(uv>>4)];
614 uv = uvtab[((*pu++<<8)|*pv++)+1028];
615 *dst++ = ytab[((*py++ +2)<<4)|(uv&15)];
616 *dst++ = ytab[((*py++ +10)<<4)|(uv>>4)];
617 uv = uvtab[(*pu++<<8)|*pv++];
618 *dst++ = ytab[((*py++)<<4)|(uv&15)];
619 *dst++ = ytab[((*py++ +8)<<4)|(uv>>4)];
620 uv = uvtab[((*pu++<<8)|*pv++)+1028];
621 *dst++ = ytab[((*py++ +2)<<4)|(uv&15)];
622 *dst++ = ytab[((*py++ +10)<<4)|(uv>>4)];
623 }
624
625 if (chroma_format==CHROMA420)
626 {
627 pu -= chrom_width;
628 pv -= chrom_width;
629 }
630
631 /* line j + 1 */
632 for (i=0; i<coded_picture_width; i+=8)
633 {
634 uv = uvtab[((*pu++<<8)|*pv++)+2056];
635 *dst++ = ytab[((*py++ +12)<<4)|(uv>>4)];
636 *dst++ = ytab[((*py++ +4)<<4)|(uv&15)];
637 uv = uvtab[((*pu++<<8)|*pv++)+3084];
638 *dst++ = ytab[((*py++ +14)<<4)|(uv>>4)];
639 *dst++ = ytab[((*py++ +6)<<4)|(uv&15)];
640 uv = uvtab[((*pu++<<8)|*pv++)+2056];
641 *dst++ = ytab[((*py++ +12)<<4)|(uv>>4)];
642 *dst++ = ytab[((*py++ +4)<<4)|(uv&15)];
643 uv = uvtab[((*pu++<<8)|*pv++)+3084];
644 *dst++ = ytab[((*py++ +14)<<4)|(uv>>4)];
645 *dst++ = ytab[((*py++ +6)<<4)|(uv&15)];
646 }
647
648 /* line j + 2 */
649 for (i=0; i<coded_picture_width; i+=8)
650 {
651 uv = uvtab[((*pu++<<8)|*pv++)+1542];
652 *dst++ = ytab[((*py++ +3)<<4)|(uv&15)];
653 *dst++ = ytab[((*py++ +11)<<4)|(uv>>4)];
654 uv = uvtab[((*pu++<<8)|*pv++)+514];
655 *dst++ = ytab[((*py++ +1)<<4)|(uv&15)];
656 *dst++ = ytab[((*py++ +9)<<4)|(uv>>4)];
657 uv = uvtab[((*pu++<<8)|*pv++)+1542];
658 *dst++ = ytab[((*py++ +3)<<4)|(uv&15)];
659 *dst++ = ytab[((*py++ +11)<<4)|(uv>>4)];
660 uv = uvtab[((*pu++<<8)|*pv++)+514];
661 *dst++ = ytab[((*py++ +1)<<4)|(uv&15)];
662 *dst++ = ytab[((*py++ +9)<<4)|(uv>>4)];
663 }
664
665 if (chroma_format==CHROMA420)
666 {
667 pu -= chrom_width;
668 pv -= chrom_width;
669 }
670
671 /* line j + 3 */
672 for (i=0; i<coded_picture_width; i+=8)
673 {
674 uv = uvtab[((*pu++<<8)|*pv++)+3598];
675 *dst++ = ytab[((*py++ +15)<<4)|(uv>>4)];
676 *dst++ = ytab[((*py++ +7)<<4)|(uv&15)];
677 uv = uvtab[((*pu++<<8)|*pv++)+2570];
678 *dst++ = ytab[((*py++ +13)<<4)|(uv>>4)];
679 *dst++ = ytab[((*py++ +5)<<4)|(uv&15)];
680 uv = uvtab[((*pu++<<8)|*pv++)+3598];
681 *dst++ = ytab[((*py++ +15)<<4)|(uv>>4)];
682 *dst++ = ytab[((*py++ +7)<<4)|(uv&15)];
683 uv = uvtab[((*pu++<<8)|*pv++)+2570];
684 *dst++ = ytab[((*py++ +13)<<4)|(uv>>4)];
685 *dst++ = ytab[((*py++ +5)<<4)|(uv&15)];
686 }
687 }
688 }
689
dithertop(src,dst)690 static void dithertop(src,dst)
691 unsigned char *src[];
692 unsigned char *dst;
693 {
694 int i,j;
695 unsigned int y,uv1,uv2;
696 unsigned char *py,*py2,*pu,*pv,*dst2;
697
698 py = src[0];
699 py2 = src[0] + (coded_picture_width<<1);
700 pu = src[1];
701 pv = src[2];
702 dst2 = dst + coded_picture_width;
703
704 for (j=0; j<coded_picture_height; j+=4)
705 {
706 /* line j + 0, j + 1 */
707 for (i=0; i<coded_picture_width; i+=4)
708 {
709 y = *py++;
710 uv2 = (*pu++<<8)|*pv++;
711 uv1 = uvtab[uv2];
712 uv2 = uvtab[uv2+2056];
713 *dst++ = ytab[((y)<<4)|(uv1&15)];
714 *dst2++ = ytab[((((y + *py2++)>>1)+12)<<4)|(uv2>>4)];
715
716 y = *py++;
717 *dst++ = ytab[((y+8)<<4)|(uv1>>4)];
718 *dst2++ = ytab[((((y + *py2++)>>1)+4)<<4)|(uv2&15)];
719
720 y = *py++;
721 uv2 = (*pu++<<8)|*pv++;
722 uv1 = uvtab[uv2+1028];
723 uv2 = uvtab[uv2+3072];
724 *dst++ = ytab[((y+2)<<4)|(uv1&15)];
725 *dst2++ = ytab[((((y + *py2++)>>1)+14)<<4)|(uv2>>4)];
726
727 y = *py++;
728 *dst++ = ytab[((y+10)<<4)|(uv1>>4)];
729 *dst2++ = ytab[((((y + *py2++)>>1)+6)<<4)|(uv2&15)];
730 }
731
732 py += coded_picture_width;
733
734 if (j!=(coded_picture_height-4))
735 py2 += coded_picture_width;
736 else
737 py2 -= coded_picture_width;
738
739 dst += coded_picture_width;
740 dst2 += coded_picture_width;
741
742 if (chroma_format==CHROMA420)
743 {
744 pu -= chrom_width;
745 pv -= chrom_width;
746 }
747 else
748 {
749 pu += chrom_width;
750 pv += chrom_width;
751 }
752
753 /* line j + 2, j + 3 */
754 for (i=0; i<coded_picture_width; i+=4)
755 {
756 y = *py++;
757 uv2 = (*pu++<<8)|*pv++;
758 uv1 = uvtab[uv2+1542];
759 uv2 = uvtab[uv2+3598];
760 *dst++ = ytab[((y+3)<<4)|(uv1&15)];
761 *dst2++ = ytab[((((y + *py2++)>>1)+15)<<4)|(uv2>>4)];
762
763 y = *py++;
764 *dst++ = ytab[((y+11)<<4)|(uv1>>4)];
765 *dst2++ = ytab[((((y + *py2++)>>1)+7)<<4)|(uv2&15)];
766
767 y = *py++;
768 uv2 = (*pu++<<8)|*pv++;
769 uv1 = uvtab[uv2+514];
770 uv2 = uvtab[uv2+2570];
771 *dst++ = ytab[((y+1)<<4)|(uv1&15)];
772 *dst2++ = ytab[((((y + *py2++)>>1)+13)<<4)|(uv2>>4)];
773
774 y = *py++;
775 *dst++ = ytab[((y+9)<<4)|(uv1>>4)];
776 *dst2++ = ytab[((((y + *py2++)>>1)+5)<<4)|(uv2&15)];
777 }
778
779 py += coded_picture_width;
780 py2 += coded_picture_width;
781 dst += coded_picture_width;
782 dst2 += coded_picture_width;
783 pu += chrom_width;
784 pv += chrom_width;
785 }
786 }
787
ditherbot(src,dst)788 static void ditherbot(src,dst)
789 unsigned char *src[];
790 unsigned char *dst;
791 {
792 int i,j;
793 unsigned int y2,uv1,uv2;
794 unsigned char *py,*py2,*pu,*pv,*dst2;
795
796 py = src[0] + coded_picture_width;
797 py2 = py;
798 pu = src[1] + chrom_width;
799 pv = src[2] + chrom_width;
800 dst2 = dst + coded_picture_width;
801
802 for (j=0; j<coded_picture_height; j+=4)
803 {
804 /* line j + 0, j + 1 */
805 for (i=0; i<coded_picture_width; i+=4)
806 {
807 y2 = *py2++;
808 uv2 = (*pu++<<8)|*pv++;
809 uv1 = uvtab[uv2];
810 uv2 = uvtab[uv2+2056];
811 *dst++ = ytab[((((*py++ + y2)>>1))<<4)|(uv1&15)];
812 *dst2++ = ytab[((y2+12)<<4)|(uv2>>4)];
813
814 y2 = *py2++;
815 *dst++ = ytab[((((*py++ + y2)>>1)+8)<<4)|(uv1>>4)];
816 *dst2++ = ytab[((y2+4)<<4)|(uv2&15)];
817
818 y2 = *py2++;
819 uv2 = (*pu++<<8)|*pv++;
820 uv1 = uvtab[uv2+1028];
821 uv2 = uvtab[uv2+3072];
822 *dst++ = ytab[((((*py++ + y2)>>1)+2)<<4)|(uv1&15)];
823 *dst2++ = ytab[((y2+14)<<4)|(uv2>>4)];
824
825 y2 = *py2++;
826 *dst++ = ytab[((((*py++ + y2)>>1)+10)<<4)|(uv1>>4)];
827 *dst2++ = ytab[((y2+6)<<4)|(uv2&15)];
828 }
829
830 if (j==0)
831 py -= coded_picture_width;
832 else
833 py += coded_picture_width;
834
835 py2 += coded_picture_width;
836 dst += coded_picture_width;
837 dst2 += coded_picture_width;
838
839 if (chroma_format==CHROMA420)
840 {
841 pu -= chrom_width;
842 pv -= chrom_width;
843 }
844 else
845 {
846 pu += chrom_width;
847 pv += chrom_width;
848 }
849
850 /* line j + 2, j + 3 */
851 for (i=0; i<coded_picture_width; i+=4)
852 {
853 y2 = *py2++;
854 uv2 = (*pu++<<8)|*pv++;
855 uv1 = uvtab[uv2+1542];
856 uv2 = uvtab[uv2+3598];
857 *dst++ = ytab[((((*py++ + y2)>>1)+3)<<4)|(uv1&15)];
858 *dst2++ = ytab[((y2+15)<<4)|(uv2>>4)];
859
860 y2 = *py2++;
861 *dst++ = ytab[((((*py++ + y2)>>1)+11)<<4)|(uv1>>4)];
862 *dst2++ = ytab[((y2+7)<<4)|(uv2&15)];
863
864 y2 = *py2++;
865 uv2 = (*pu++<<8)|*pv++;
866 uv1 = uvtab[uv2+514];
867 uv2 = uvtab[uv2+2570];
868 *dst++ = ytab[((((*py++ + y2)>>1)+1)<<4)|(uv1&15)];
869 *dst2++ = ytab[((y2+13)<<4)|(uv2>>4)];
870
871 y2 = *py2++;
872 *dst++ = ytab[((((*py++ + y2)>>1)+9)<<4)|(uv1>>4)];
873 *dst2++ = ytab[((y2+5)<<4)|(uv2&15)];
874 }
875
876 py += coded_picture_width;
877 py2 += coded_picture_width;
878 dst += coded_picture_width;
879 dst2 += coded_picture_width;
880 pu += chrom_width;
881 pv += chrom_width;
882 }
883 }
884
885 /* only for 4:4:4 */
886
ditherframe444(src)887 static void ditherframe444(src)
888 unsigned char *src[];
889 {
890 int i,j;
891 unsigned char *py,*pu,*pv,*dst;
892
893 py = src[0];
894 pu = src[1];
895 pv = src[2];
896 dst = dithered_image;
897
898 for (j=0; j<coded_picture_height; j+=4)
899 {
900 /* line j + 0 */
901 for (i=0; i<coded_picture_width; i+=8)
902 {
903 *dst++ = ytab[((*py++)<<4)|(uvtab[(*pu++<<8)|*pv++]&15)];
904 *dst++ = ytab[((*py++ +8)<<4)|(uvtab[(*pu++<<8)|*pv++]>>4)];
905 *dst++ = ytab[((*py++ +2)<<4)|(uvtab[((*pu++<<8)|*pv++)+1028]&15)];
906 *dst++ = ytab[((*py++ +10)<<4)|(uvtab[((*pu++<<8)|*pv++)+1028]>>4)];
907 *dst++ = ytab[((*py++)<<4)|(uvtab[(*pu++<<8)|*pv++]&15)];
908 *dst++ = ytab[((*py++ +8)<<4)|(uvtab[(*pu++<<8)|*pv++]>>4)];
909 *dst++ = ytab[((*py++ +2)<<4)|(uvtab[((*pu++<<8)|*pv++)+1028]&15)];
910 *dst++ = ytab[((*py++ +10)<<4)|(uvtab[((*pu++<<8)|*pv++)+1028]>>4)];
911 }
912
913 /* line j + 1 */
914 for (i=0; i<coded_picture_width; i+=8)
915 {
916 *dst++ = ytab[((*py++ +12)<<4)|(uvtab[((*pu++<<8)|*pv++)+2056]>>4)];
917 *dst++ = ytab[((*py++ +4)<<4)|(uvtab[((*pu++<<8)|*pv++)+2056]&15)];
918 *dst++ = ytab[((*py++ +14)<<4)|(uvtab[((*pu++<<8)|*pv++)+3084]>>4)];
919 *dst++ = ytab[((*py++ +6)<<4)|(uvtab[((*pu++<<8)|*pv++)+3084]&15)];
920 *dst++ = ytab[((*py++ +12)<<4)|(uvtab[((*pu++<<8)|*pv++)+2056]>>4)];
921 *dst++ = ytab[((*py++ +4)<<4)|(uvtab[((*pu++<<8)|*pv++)+2056]&15)];
922 *dst++ = ytab[((*py++ +14)<<4)|(uvtab[((*pu++<<8)|*pv++)+3084]>>4)];
923 *dst++ = ytab[((*py++ +6)<<4)|(uvtab[((*pu++<<8)|*pv++)+3084]&15)];
924 }
925
926 /* line j + 2 */
927 for (i=0; i<coded_picture_width; i+=8)
928 {
929 *dst++ = ytab[((*py++ +3)<<4)|(uvtab[((*pu++<<8)|*pv++)+1542]&15)];
930 *dst++ = ytab[((*py++ +11)<<4)|(uvtab[((*pu++<<8)|*pv++)+1542]>>4)];
931 *dst++ = ytab[((*py++ +1)<<4)|(uvtab[((*pu++<<8)|*pv++)+514]&15)];
932 *dst++ = ytab[((*py++ +9)<<4)|(uvtab[((*pu++<<8)|*pv++)+514]>>4)];
933 *dst++ = ytab[((*py++ +3)<<4)|(uvtab[((*pu++<<8)|*pv++)+1542]&15)];
934 *dst++ = ytab[((*py++ +11)<<4)|(uvtab[((*pu++<<8)|*pv++)+1542]>>4)];
935 *dst++ = ytab[((*py++ +1)<<4)|(uvtab[((*pu++<<8)|*pv++)+514]&15)];
936 *dst++ = ytab[((*py++ +9)<<4)|(uvtab[((*pu++<<8)|*pv++)+514]>>4)];
937 }
938
939 /* line j + 3 */
940 for (i=0; i<coded_picture_width; i+=8)
941 {
942 *dst++ = ytab[((*py++ +15)<<4)|(uvtab[((*pu++<<8)|*pv++)+3598]>>4)];
943 *dst++ = ytab[((*py++ +7)<<4)|(uvtab[((*pu++<<8)|*pv++)+3598]&15)];
944 *dst++ = ytab[((*py++ +13)<<4)|(uvtab[((*pu++<<8)|*pv++)+2570]>>4)];
945 *dst++ = ytab[((*py++ +5)<<4)|(uvtab[((*pu++<<8)|*pv++)+2570]&15)];
946 *dst++ = ytab[((*py++ +15)<<4)|(uvtab[((*pu++<<8)|*pv++)+3598]>>4)];
947 *dst++ = ytab[((*py++ +7)<<4)|(uvtab[((*pu++<<8)|*pv++)+3598]&15)];
948 *dst++ = ytab[((*py++ +13)<<4)|(uvtab[((*pu++<<8)|*pv++)+2570]>>4)];
949 *dst++ = ytab[((*py++ +5)<<4)|(uvtab[((*pu++<<8)|*pv++)+2570]&15)];
950 }
951 }
952 }
953
dithertop444(src,dst)954 static void dithertop444(src,dst)
955 unsigned char *src[];
956 unsigned char *dst;
957 {
958 int i,j;
959 unsigned int y,uv;
960 unsigned char *py,*py2,*pu,*pv,*dst2;
961
962 py = src[0];
963 py2 = src[0] + (coded_picture_width<<1);
964 pu = src[1];
965 pv = src[2];
966 dst2 = dst + coded_picture_width;
967
968 for (j=0; j<coded_picture_height; j+=4)
969 {
970 /* line j + 0, j + 1 */
971 for (i=0; i<coded_picture_width; i+=4)
972 {
973 y = *py++;
974 uv = (*pu++<<8)|*pv++;
975 *dst++ = ytab[((y)<<4)|(uvtab[uv]&15)];
976 *dst2++ = ytab[((((y + *py2++)>>1)+12)<<4)|(uvtab[uv+2056]>>4)];
977
978 y = *py++;
979 uv = (*pu++<<8)|*pv++;
980 *dst++ = ytab[((y+8)<<4)|(uvtab[uv]>>4)];
981 *dst2++ = ytab[((((y + *py2++)>>1)+4)<<4)|(uvtab[uv+2056]&15)];
982
983 y = *py++;
984 uv = (*pu++<<8)|*pv++;
985 *dst++ = ytab[((y+2)<<4)|(uvtab[uv+1028]&15)];
986 *dst2++ = ytab[((((y + *py2++)>>1)+14)<<4)|(uvtab[uv+3072]>>4)];
987
988 y = *py++;
989 uv = (*pu++<<8)|*pv++;
990 *dst++ = ytab[((y+10)<<4)|(uvtab[uv+1028]>>4)];
991 *dst2++ = ytab[((((y + *py2++)>>1)+6)<<4)|(uvtab[uv+3072]&15)];
992 }
993
994 py += coded_picture_width;
995
996 if (j!=(coded_picture_height-4))
997 py2 += coded_picture_width;
998 else
999 py2 -= coded_picture_width;
1000
1001 dst += coded_picture_width;
1002 dst2 += coded_picture_width;
1003
1004 pu += chrom_width;
1005 pv += chrom_width;
1006
1007 /* line j + 2, j + 3 */
1008 for (i=0; i<coded_picture_width; i+=4)
1009 {
1010 y = *py++;
1011 uv = (*pu++<<8)|*pv++;
1012 *dst++ = ytab[((y+3)<<4)|(uvtab[uv+1542]&15)];
1013 *dst2++ = ytab[((((y + *py2++)>>1)+15)<<4)|(uvtab[uv+3598]>>4)];
1014
1015 y = *py++;
1016 uv = (*pu++<<8)|*pv++;
1017 *dst++ = ytab[((y+11)<<4)|(uvtab[uv+1542]>>4)];
1018 *dst2++ = ytab[((((y + *py2++)>>1)+7)<<4)|(uvtab[uv+3598]&15)];
1019
1020 y = *py++;
1021 uv = (*pu++<<8)|*pv++;
1022 *dst++ = ytab[((y+1)<<4)|(uvtab[uv+514]&15)];
1023 *dst2++ = ytab[((((y + *py2++)>>1)+13)<<4)|(uvtab[uv+2570]>>4)];
1024
1025 y = *py++;
1026 uv = (*pu++<<8)|*pv++;
1027 *dst++ = ytab[((y+9)<<4)|(uvtab[uv+514]>>4)];
1028 *dst2++ = ytab[((((y + *py2++)>>1)+5)<<4)|(uvtab[uv+2570]&15)];
1029 }
1030
1031 py += coded_picture_width;
1032 py2 += coded_picture_width;
1033 dst += coded_picture_width;
1034 dst2 += coded_picture_width;
1035 pu += chrom_width;
1036 pv += chrom_width;
1037 }
1038 }
1039
ditherbot444(src,dst)1040 static void ditherbot444(src,dst)
1041 unsigned char *src[];
1042 unsigned char *dst;
1043 {
1044 int i,j;
1045 unsigned int y2,uv;
1046 unsigned char *py,*py2,*pu,*pv,*dst2;
1047
1048 py = src[0] + coded_picture_width;
1049 py2 = py;
1050 pu = src[1] + chrom_width;
1051 pv = src[2] + chrom_width;
1052 dst2 = dst + coded_picture_width;
1053
1054 for (j=0; j<coded_picture_height; j+=4)
1055 {
1056 /* line j + 0, j + 1 */
1057 for (i=0; i<coded_picture_width; i+=4)
1058 {
1059 y2 = *py2++;
1060 uv = (*pu++<<8)|*pv++;
1061 *dst++ = ytab[((((*py++ + y2)>>1))<<4)|(uvtab[uv]&15)];
1062 *dst2++ = ytab[((y2+12)<<4)|(uvtab[uv+2056]>>4)];
1063
1064 y2 = *py2++;
1065 uv = (*pu++<<8)|*pv++;
1066 *dst++ = ytab[((((*py++ + y2)>>1)+8)<<4)|(uvtab[uv]>>4)];
1067 *dst2++ = ytab[((y2+4)<<4)|(uvtab[uv+2056]&15)];
1068
1069 y2 = *py2++;
1070 uv = (*pu++<<8)|*pv++;
1071 *dst++ = ytab[((((*py++ + y2)>>1)+2)<<4)|(uvtab[uv+1028]&15)];
1072 *dst2++ = ytab[((y2+14)<<4)|(uvtab[uv+3072]>>4)];
1073
1074 y2 = *py2++;
1075 uv = (*pu++<<8)|*pv++;
1076 *dst++ = ytab[((((*py++ + y2)>>1)+10)<<4)|(uvtab[uv+1028]>>4)];
1077 *dst2++ = ytab[((y2+6)<<4)|(uvtab[uv+3072]&15)];
1078 }
1079
1080 if (j==0)
1081 py -= coded_picture_width;
1082 else
1083 py += coded_picture_width;
1084
1085 py2 += coded_picture_width;
1086 dst += coded_picture_width;
1087 dst2 += coded_picture_width;
1088
1089 pu += chrom_width;
1090 pv += chrom_width;
1091
1092 /* line j + 2, j + 3 */
1093 for (i=0; i<coded_picture_width; i+=4)
1094 {
1095 y2 = *py2++;
1096 uv = (*pu++<<8)|*pv++;
1097 *dst++ = ytab[((((*py++ + y2)>>1)+3)<<4)|(uvtab[uv+1542]&15)];
1098 *dst2++ = ytab[((y2+15)<<4)|(uvtab[uv+3598]>>4)];
1099
1100 y2 = *py2++;
1101 uv = (*pu++<<8)|*pv++;
1102 *dst++ = ytab[((((*py++ + y2)>>1)+11)<<4)|(uvtab[uv+1542]>>4)];
1103 *dst2++ = ytab[((y2+7)<<4)|(uvtab[uv+3598]&15)];
1104
1105 y2 = *py2++;
1106 uv = (*pu++<<8)|*pv++;
1107 *dst++ = ytab[((((*py++ + y2)>>1)+1)<<4)|(uvtab[uv+514]&15)];
1108 *dst2++ = ytab[((y2+13)<<4)|(uvtab[uv+2570]>>4)];
1109
1110 y2 = *py2++;
1111 uv = (*pu++<<8)|*pv++;
1112 *dst++ = ytab[((((*py++ + y2)>>1)+9)<<4)|(uvtab[uv+514]>>4)];
1113 *dst2++ = ytab[((y2+5)<<4)|(uvtab[uv+2570]&15)];
1114 }
1115
1116 py += coded_picture_width;
1117 py2 += coded_picture_width;
1118 dst += coded_picture_width;
1119 dst2 += coded_picture_width;
1120 pu += chrom_width;
1121 pv += chrom_width;
1122 }
1123 }
1124
1125