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