1 /* display.c, X11 interface */
3 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
6 * Disclaimer of Warranty
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.
16 * This disclaimer of warranty extends to the user of these programs and user's
17 * customers, employees, agents, transferees, successors, and assigns.
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
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
32 /* the Xlib interface is closely modeled after
33 * mpeg_play 2.0 by the Berkeley Plateau Research Group
40 #include <X11/Xutil.h>
45 /* private prototypes */
46 static void Display_Image _ANSI_ARGS_((XImage *Ximage_Ptr, unsigned char *Dithered_Image));
47 static void Dither_Frame _ANSI_ARGS_((unsigned char *src[]));
48 static void Dither_Top_Field _ANSI_ARGS_((unsigned char *src[], unsigned char *dst));
49 static void Dither_Bottom_Field _ANSI_ARGS_((unsigned char *src[], unsigned char *dst));
50 static void Dither_Top_Field420 _ANSI_ARGS_((unsigned char *src[],
52 static void Dither_Bottom_Field420 _ANSI_ARGS_((unsigned char *src[],
56 static unsigned char *Dithered_Image, *Dithered_Image2;
58 static unsigned char Y_Table[256+16];
59 static unsigned char Cb_Table[128+16];
60 static unsigned char Cr_Table[128+16];
62 /* X11 related variables */
63 static Display *Display_Ptr;
64 static Window Window_Instance;
65 static GC GC_Instance;
66 static XImage *Ximage_Ptr, *Ximage_Ptr2;
67 static unsigned char Pixel[256];
73 #include <X11/extensions/XShm.h>
75 static int HandleXError _ANSI_ARGS_((Display *dpy, XErrorEvent *event));
76 static void InstallXErrorHandler _ANSI_ARGS_((void));
77 static void DeInstallXErrorHandler _ANSI_ARGS_((void));
79 static int Shmem_Flag;
80 static XShmSegmentInfo Shminfo1, Shminfo2;
81 static int gXErrorFlag;
82 static int CompletionType = -1;
84 static int HandleXError(Dpy, Event)
93 static void InstallXErrorHandler()
95 XSetErrorHandler(HandleXError);
99 static void DeInstallXErrorHandler()
101 XSetErrorHandler(NULL);
107 /* connect to server, create and map window,
108 * allocate colors and (shared) memory
110 void Initialize_Display_Process(name)
113 int crv, cbu, cgu, cgv;
114 int Y, Cb, Cr, R, G, B;
122 char *hello = "MPEG-2 Display";
126 unsigned long tmp_pixel;
127 XWindowAttributes xwa;
129 Display_Ptr = XOpenDisplay(name);
131 if (Display_Ptr == NULL)
132 Error("Can not open display\n");
134 screen = DefaultScreen(Display_Ptr);
138 hint.width = horizontal_size;
139 hint.height = vertical_size;
140 hint.flags = PPosition | PSize;
142 /* Get some colors */
144 bg = WhitePixel (Display_Ptr, screen);
145 fg = BlackPixel (Display_Ptr, screen);
147 /* Make the window */
149 if (!XMatchVisualInfo(Display_Ptr, screen, 8, PseudoColor, &vinfo))
151 if (!XMatchVisualInfo(Display_Ptr, screen, 8, GrayScale, &vinfo))
152 Error("requires 8 bit display\n");
155 Window_Instance = XCreateSimpleWindow (Display_Ptr, DefaultRootWindow (Display_Ptr),
156 hint.x, hint.y, hint.width, hint.height, 4, fg, bg);
158 XSelectInput(Display_Ptr, Window_Instance, StructureNotifyMask);
160 /* Tell other applications about this window */
162 XSetStandardProperties (Display_Ptr, Window_Instance, hello, hello, None, NULL, 0, &hint);
166 XMapWindow(Display_Ptr, Window_Instance);
171 XNextEvent(Display_Ptr, &xev);
173 while (xev.type != MapNotify || xev.xmap.event != Window_Instance);
175 XSelectInput(Display_Ptr, Window_Instance, NoEventMask);
177 /* matrix coefficients */
178 crv = Inverse_Table_6_9[matrix_coefficients][0];
179 cbu = Inverse_Table_6_9[matrix_coefficients][1];
180 cgu = Inverse_Table_6_9[matrix_coefficients][2];
181 cgv = Inverse_Table_6_9[matrix_coefficients][3];
183 /* allocate colors */
185 GC_Instance = DefaultGC(Display_Ptr, screen);
186 cmap = DefaultColormap(Display_Ptr, screen);
190 * i is the (internal) 8 bit color number, it consists of separate
191 * bit fields for Y, U and V: i = (yyyyuuvv), we don't use yyyy=0000
192 * and yyyy=1111, this leaves 32 colors for other applications
194 * the allocated colors correspond to the following Y, U and V values:
195 * Y: 24, 40, 56, 72, 88, 104, 120, 136, 152, 168, 184, 200, 216, 232
196 * U,V: -48, -16, 16, 48
198 * U and V values span only about half the color space; this gives
199 * usually much better quality, although highly saturated colors can
200 * not be displayed properly
202 * translation to R,G,B is implicitly done by the color look-up table
204 for (i=16; i<240; i++)
206 /* color space conversion */
207 Y = 16*((i>>4)&15) + 8;
208 Cb = 32*((i>>2)&3) - 48;
211 Y = 76309 * (Y - 16); /* (255/219)*65536 */
213 R = Clip[(Y + crv*Cr + 32768)>>16];
214 G = Clip[(Y - cgu*Cb - cgv*Cr + 32768)>>16];
215 B = Clip[(Y + cbu*Cb + 32786)>>16];
217 /* X11 colors are 16 bit */
219 xcolor.green = G << 8;
220 xcolor.blue = B << 8;
222 if (XAllocColor(Display_Ptr, cmap, &xcolor) != 0)
223 Pixel[i] = xcolor.pixel;
226 /* allocation failed, have to use a private colormap */
229 Error("Couldn't allocate private colormap");
234 fprintf(stderr, "Using private colormap (%d colors were available).\n",
240 tmp_pixel = Pixel[i]; /* because XFreeColors expects unsigned long */
241 XFreeColors(Display_Ptr, cmap, &tmp_pixel, 1, 0);
244 /* i is now 15, this restarts the outer loop */
246 /* create private colormap */
248 XGetWindowAttributes(Display_Ptr, Window_Instance, &xwa);
249 cmap = XCreateColormap(Display_Ptr, Window_Instance, xwa.visual, AllocNone);
250 XSetWindowColormap(Display_Ptr, Window_Instance, cmap);
255 if (XShmQueryExtension(Display_Ptr))
261 fprintf(stderr, "Shared memory not supported\nReverting to normal Xlib\n");
265 CompletionType = XShmGetEventBase(Display_Ptr) + ShmCompletion;
267 InstallXErrorHandler();
272 Ximage_Ptr = XShmCreateImage(Display_Ptr, None, 8, ZPixmap, NULL,
274 Coded_Picture_Width, Coded_Picture_Height);
276 if (!progressive_sequence)
277 Ximage_Ptr2 = XShmCreateImage(Display_Ptr, None, 8, ZPixmap, NULL,
279 Coded_Picture_Width, Coded_Picture_Height);
281 /* If no go, then revert to normal Xlib calls. */
283 if (Ximage_Ptr==NULL || (!progressive_sequence && Ximage_Ptr2==NULL))
285 if (Ximage_Ptr!=NULL)
286 XDestroyImage(Ximage_Ptr);
287 if (!progressive_sequence && Ximage_Ptr2!=NULL)
288 XDestroyImage(Ximage_Ptr2);
290 fprintf(stderr, "Shared memory error, disabling (Ximage error)\n");
294 /* Success here, continue. */
296 Shminfo1.shmid = shmget(IPC_PRIVATE,
297 Ximage_Ptr->bytes_per_line * Ximage_Ptr->height,
299 if (!progressive_sequence)
300 Shminfo2.shmid = shmget(IPC_PRIVATE,
301 Ximage_Ptr2->bytes_per_line * Ximage_Ptr2->height,
304 if (Shminfo1.shmid<0 || (!progressive_sequence && Shminfo2.shmid<0))
306 XDestroyImage(Ximage_Ptr);
307 if (!progressive_sequence)
308 XDestroyImage(Ximage_Ptr2);
310 fprintf(stderr, "Shared memory error, disabling (seg id error)\n");
314 Shminfo1.shmaddr = (char *) shmat(Shminfo1.shmid, 0, 0);
315 Shminfo2.shmaddr = (char *) shmat(Shminfo2.shmid, 0, 0);
317 if (Shminfo1.shmaddr==((char *) -1) ||
318 (!progressive_sequence && Shminfo2.shmaddr==((char *) -1)))
320 XDestroyImage(Ximage_Ptr);
321 if (Shminfo1.shmaddr!=((char *) -1))
322 shmdt(Shminfo1.shmaddr);
323 if (!progressive_sequence)
325 XDestroyImage(Ximage_Ptr2);
326 if (Shminfo2.shmaddr!=((char *) -1))
327 shmdt(Shminfo2.shmaddr);
331 fprintf(stderr, "Shared memory error, disabling (address error)\n");
336 Ximage_Ptr->data = Shminfo1.shmaddr;
337 Dithered_Image = (unsigned char *)Ximage_Ptr->data;
338 Shminfo1.readOnly = False;
339 XShmAttach(Display_Ptr, &Shminfo1);
340 if (!progressive_sequence)
342 Ximage_Ptr2->data = Shminfo2.shmaddr;
343 Dithered_Image2 = (unsigned char *)Ximage_Ptr2->data;
344 Shminfo2.readOnly = False;
345 XShmAttach(Display_Ptr, &Shminfo2);
348 XSync(Display_Ptr, False);
352 /* Ultimate failure here. */
353 XDestroyImage(Ximage_Ptr);
354 shmdt(Shminfo1.shmaddr);
355 if (!progressive_sequence)
357 XDestroyImage(Ximage_Ptr2);
358 shmdt(Shminfo2.shmaddr);
361 fprintf(stderr, "Shared memory error, disabling.\n");
367 shmctl(Shminfo1.shmid, IPC_RMID, 0);
368 if (!progressive_sequence)
369 shmctl(Shminfo2.shmid, IPC_RMID, 0);
374 fprintf(stderr, "Sharing memory.\n");
383 Ximage_Ptr = XCreateImage(Display_Ptr,None,8,ZPixmap,0,&dummy,
384 Coded_Picture_Width,Coded_Picture_Height,8,0);
386 if (!(Dithered_Image = (unsigned char *)malloc(Coded_Picture_Width*
387 Coded_Picture_Height)))
388 Error("malloc failed");
390 if (!progressive_sequence)
392 Ximage_Ptr2 = XCreateImage(Display_Ptr,None,8,ZPixmap,0,&dummy,
393 Coded_Picture_Width,Coded_Picture_Height,8,0);
395 if (!(Dithered_Image2 = (unsigned char *)malloc(Coded_Picture_Width*
396 Coded_Picture_Height)))
397 Error("malloc failed");
403 DeInstallXErrorHandler();
407 void Terminate_Display_Process()
412 XShmDetach(Display_Ptr, &Shminfo1);
413 XDestroyImage(Ximage_Ptr);
414 shmdt(Shminfo1.shmaddr);
415 if (!progressive_sequence)
417 XShmDetach(Display_Ptr, &Shminfo2);
418 XDestroyImage(Ximage_Ptr2);
419 shmdt(Shminfo2.shmaddr);
425 static void Display_Image(Ximage_Ptr,Dithered_Image)
427 unsigned char *Dithered_Image;
429 /* display dithered image */
433 XShmPutImage(Display_Ptr, Window_Instance, GC_Instance, Ximage_Ptr,
434 0, 0, 0, 0, Ximage_Ptr->width, Ximage_Ptr->height, True);
441 XNextEvent(Display_Ptr, &xev);
442 if (xev.type == CompletionType)
449 Ximage_Ptr->data = (char *) Dithered_Image;
450 XPutImage(Display_Ptr, Window_Instance, GC_Instance, Ximage_Ptr, 0, 0, 0, 0, Ximage_Ptr->width, Ximage_Ptr->height);
454 void Display_Second_Field()
456 Display_Image(Ximage_Ptr2,Dithered_Image2);
459 /* 4x4 ordered dither
468 void Initialize_Dither_Matrix()
472 for (i=-8; i<256+8; i++)
482 for (i=0; i<128+16; i++)
495 unsigned char *src[];
497 /* should this test only the display flag, not progressive_sequence ? --CF */
498 /* CHANGE 95/05/13: progressive_sequence -> progressive_frame */
500 if( progressive_frame || Display_Progressive_Flag)
504 if ((picture_structure==FRAME_PICTURE && top_field_first) || picture_structure==BOTTOM_FIELD)
506 /* top field first */
507 if (chroma_format==CHROMA420 && hiQdither)
509 Dither_Top_Field420(src,Dithered_Image);
510 Dither_Bottom_Field420(src,Dithered_Image2);
514 Dither_Top_Field(src,Dithered_Image);
515 Dither_Bottom_Field(src,Dithered_Image2);
520 /* bottom field first */
521 if (chroma_format==CHROMA420 && hiQdither)
523 Dither_Bottom_Field420(src,Dithered_Image);
524 Dither_Top_Field420(src,Dithered_Image2);
528 Dither_Bottom_Field(src,Dithered_Image);
529 Dither_Top_Field(src,Dithered_Image2);
534 Display_Image(Ximage_Ptr,Dithered_Image);
537 static void Dither_Frame(src)
538 unsigned char *src[];
542 unsigned char *py,*pu,*pv,*dst;
547 dst = Dithered_Image;
549 for (j=0; j<Coded_Picture_Height; j+=4)
552 for (i=0; i<Coded_Picture_Width; i+=4)
557 *dst++ = Pixel[Y_Table[y]|Cb_Table[u]|Cr_Table[v]];
559 if (chroma_format==CHROMA444)
564 *dst++ = Pixel[Y_Table[y+8]|Cb_Table[u+8]|Cr_Table[v+8]];
568 *dst++ = Pixel[Y_Table[y+2]|Cb_Table[u+2]|Cr_Table[v+2]];
570 if (chroma_format==CHROMA444)
575 *dst++ = Pixel[Y_Table[y+10]|Cb_Table[u+10]|Cr_Table[v+10]];
578 if (chroma_format==CHROMA420)
585 for (i=0; i<Coded_Picture_Width; i+=4)
590 *dst++ = Pixel[Y_Table[y+12]|Cb_Table[u+12]|Cr_Table[v+12]];
592 if (chroma_format==CHROMA444)
597 *dst++ = Pixel[Y_Table[y+4]|Cb_Table[u+4]|Cr_Table[v+4]];
601 *dst++ = Pixel[Y_Table[y+14]|Cb_Table[u+14]|Cr_Table[v+14]];
603 if (chroma_format==CHROMA444)
608 *dst++ = Pixel[Y_Table[y+6]|Cb_Table[u+6]|Cr_Table[v+6]];
612 for (i=0; i<Coded_Picture_Width; i+=4)
617 *dst++ = Pixel[Y_Table[y+3]|Cb_Table[u+3]|Cr_Table[v+3]];
619 if (chroma_format==CHROMA444)
624 *dst++ = Pixel[Y_Table[y+11]|Cb_Table[u+11]|Cr_Table[v+11]];
628 *dst++ = Pixel[Y_Table[y+1]|Cb_Table[u+1]|Cr_Table[v+1]];
630 if (chroma_format==CHROMA444)
635 *dst++ = Pixel[Y_Table[y+9]|Cb_Table[u+9]|Cr_Table[v+9]];
638 if (chroma_format==CHROMA420)
645 for (i=0; i<Coded_Picture_Width; i+=4)
650 *dst++ = Pixel[Y_Table[y+15]|Cb_Table[u+15]|Cr_Table[v+15]];
652 if (chroma_format==CHROMA444)
657 *dst++ = Pixel[Y_Table[y+7]|Cb_Table[u+7]|Cr_Table[v+7]];
661 *dst++ = Pixel[Y_Table[y+13]|Cb_Table[u+13]|Cr_Table[v+13]];
663 if (chroma_format==CHROMA444)
668 *dst++ = Pixel[Y_Table[y+5]|Cb_Table[u+5]|Cr_Table[v+5]];
674 static void Dither_Top_Field(src,dst)
675 unsigned char *src[];
680 unsigned char *py,*Y2_ptr,*pu,*pv,*dst2;
683 Y2_ptr = src[0] + (Coded_Picture_Width<<1);
686 dst2 = dst + Coded_Picture_Width;
688 for (j=0; j<Coded_Picture_Height; j+=4)
690 /* line j + 0, j + 1 */
691 for (i=0; i<Coded_Picture_Width; i+=4)
697 *dst++ = Pixel[Y_Table[y]|Cb_Table[u]|Cr_Table[v]];
698 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+12]|Cb_Table[u+12]|Cr_Table[v+12]];
702 if (chroma_format==CHROMA444)
707 *dst++ = Pixel[Y_Table[y+8]|Cb_Table[u+8]|Cr_Table[v+8]];
708 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+4]|Cb_Table[u+4]|Cr_Table[v+4]];
714 *dst++ = Pixel[Y_Table[y+2]|Cb_Table[u+2]|Cr_Table[v+2]];
715 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+14]|Cb_Table[u+14]|Cr_Table[v+14]];
719 if (chroma_format==CHROMA444)
724 *dst++ = Pixel[Y_Table[y+10]|Cb_Table[u+10]|Cr_Table[v+10]];
725 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+6]|Cb_Table[u+6]|Cr_Table[v+6]];
728 py += Coded_Picture_Width;
730 if (j!=(Coded_Picture_Height-4))
731 Y2_ptr += Coded_Picture_Width;
733 Y2_ptr -= Coded_Picture_Width;
735 dst += Coded_Picture_Width;
736 dst2 += Coded_Picture_Width;
738 if (chroma_format==CHROMA420)
749 /* line j + 2, j + 3 */
750 for (i=0; i<Coded_Picture_Width; i+=4)
756 *dst++ = Pixel[Y_Table[y+3]|Cb_Table[u+3]|Cr_Table[v+3]];
757 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+15]|Cb_Table[u+15]|Cr_Table[v+15]];
761 if (chroma_format==CHROMA444)
766 *dst++ = Pixel[Y_Table[y+11]|Cb_Table[u+11]|Cr_Table[v+11]];
767 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+7]|Cb_Table[u+7]|Cr_Table[v+7]];
773 *dst++ = Pixel[Y_Table[y+1]|Cb_Table[u+1]|Cr_Table[v+1]];
774 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+13]|Cb_Table[u+13]|Cr_Table[v+13]];
778 if (chroma_format==CHROMA444)
783 *dst++ = Pixel[Y_Table[y+9]|Cb_Table[u+9]|Cr_Table[v+9]];
784 *dst2++ = Pixel[Y_Table[((y+Y2)>>1)+5]|Cb_Table[u+5]|Cr_Table[v+5]];
787 py += Coded_Picture_Width;
788 Y2_ptr += Coded_Picture_Width;
789 dst += Coded_Picture_Width;
790 dst2 += Coded_Picture_Width;
796 static void Dither_Bottom_Field(src,dst)
797 unsigned char *src[];
802 unsigned char *py,*Y2_ptr,*pu,*pv,*dst2;
804 py = src[0] + Coded_Picture_Width;
806 pu = src[1] + Chroma_Width;
807 pv = src[2] + Chroma_Width;
808 dst2 = dst + Coded_Picture_Width;
810 for (j=0; j<Coded_Picture_Height; j+=4)
812 /* line j + 0, j + 1 */
813 for (i=0; i<Coded_Picture_Width; i+=4)
819 *dst++ = Pixel[Y_Table[((y+Y2)>>1)]|Cb_Table[u]|Cr_Table[v]];
820 *dst2++ = Pixel[Y_Table[Y2+12]|Cb_Table[u+12]|Cr_Table[v+12]];
824 if (chroma_format==CHROMA444)
829 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+8]|Cb_Table[u+8]|Cr_Table[v+8]];
830 *dst2++ = Pixel[Y_Table[Y2+4]|Cb_Table[u+4]|Cr_Table[v+4]];
836 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+2]|Cb_Table[u+2]|Cr_Table[v+2]];
837 *dst2++ = Pixel[Y_Table[Y2+14]|Cb_Table[u+14]|Cr_Table[v+14]];
841 if (chroma_format==CHROMA444)
846 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+10]|Cb_Table[u+10]|Cr_Table[v+10]];
847 *dst2++ = Pixel[Y_Table[Y2+6]|Cb_Table[u+6]|Cr_Table[v+6]];
851 py -= Coded_Picture_Width;
853 py += Coded_Picture_Width;
855 Y2_ptr += Coded_Picture_Width;
856 dst += Coded_Picture_Width;
857 dst2 += Coded_Picture_Width;
859 if (chroma_format==CHROMA420)
870 /* line j + 2. j + 3 */
871 for (i=0; i<Coded_Picture_Width; i+=4)
877 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+3]|Cb_Table[u+3]|Cr_Table[v+3]];
878 *dst2++ = Pixel[Y_Table[Y2+15]|Cb_Table[u+15]|Cr_Table[v+15]];
882 if (chroma_format==CHROMA444)
887 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+11]|Cb_Table[u+11]|Cr_Table[v+11]];
888 *dst2++ = Pixel[Y_Table[Y2+7]|Cb_Table[u+7]|Cr_Table[v+7]];
894 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+1]|Cb_Table[u+1]|Cr_Table[v+1]];
895 *dst2++ = Pixel[Y_Table[Y2+13]|Cb_Table[u+13]|Cr_Table[v+13]];
899 if (chroma_format==CHROMA444)
904 *dst++ = Pixel[Y_Table[((y+Y2)>>1)+9]|Cb_Table[u+9]|Cr_Table[v+9]];
905 *dst2++ = Pixel[Y_Table[Y2+5]|Cb_Table[u+5]|Cr_Table[v+5]];
908 py += Coded_Picture_Width;
909 Y2_ptr += Coded_Picture_Width;
910 dst += Coded_Picture_Width;
911 dst2 += Coded_Picture_Width;
917 static void Dither_Top_Field420(src,dst)
918 unsigned char *src[];
922 int Y1,Cb1,Cr1,Y2,Cb2,Cr2;
923 unsigned char *Y1_ptr,*Cb1_ptr,*Cr1_ptr,*Y2_ptr,*Cb2_ptr,*Cr2_ptr,*dst2;
929 Y2_ptr = Y1_ptr + (Coded_Picture_Width<<1);
930 Cb2_ptr = Cb1_ptr + (Chroma_Width<<1);
931 Cr2_ptr = Cr1_ptr + (Chroma_Width<<1);
933 dst2 = dst + Coded_Picture_Width;
935 for (j=0; j<Coded_Picture_Height; j+=4)
937 /* line j + 0, j + 1 */
938 for (i=0; i<Coded_Picture_Width; i+=4)
942 Cb1 = *Cb1_ptr++ >> 1;
943 Cr1 = *Cr1_ptr++ >> 1;
944 Cb2 = *Cb2_ptr++ >> 1;
945 Cr2 = *Cr2_ptr++ >> 1;
946 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)]|Cb_Table[Cb1]|Cr_Table[Cr1]];
947 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+12]|Cb_Table[((3*Cb1+Cb2)>>2)+12]
948 |Cr_Table[((3*Cr1+Cr2)>>2)+12]];
952 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+8]|Cb_Table[Cb1+8]|Cr_Table[Cr1+8]];
953 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+4]|Cb_Table[((3*Cb1+Cb2)>>2)+4]
954 |Cr_Table[((3*Cr1+Cr2)>>2)+4]];
958 Cb1 = *Cb1_ptr++ >> 1;
959 Cr1 = *Cr1_ptr++ >> 1;
960 Cb2 = *Cb2_ptr++ >> 1;
961 Cr2 = *Cr2_ptr++ >> 1;
962 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+2]|Cb_Table[Cb1+2]|Cr_Table[Cr1+2]];
963 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+14]|Cb_Table[((3*Cb1+Cb2)>>2)+14]
964 |Cr_Table[((3*Cr1+Cr2)>>2)+14]];
968 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+10]|Cb_Table[Cb1+10]|Cr_Table[Cr1+10]];
969 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+6]|Cb_Table[((3*Cb1+Cb2)>>2)+6]
970 |Cr_Table[((3*Cr1+Cr2)>>2)+6]];
973 Y1_ptr += Coded_Picture_Width;
975 if (j!=(Coded_Picture_Height-4))
976 Y2_ptr += Coded_Picture_Width;
978 Y2_ptr -= Coded_Picture_Width;
980 Cb1_ptr -= Chroma_Width;
981 Cr1_ptr -= Chroma_Width;
982 Cb2_ptr -= Chroma_Width;
983 Cr2_ptr -= Chroma_Width;
985 dst += Coded_Picture_Width;
986 dst2 += Coded_Picture_Width;
988 /* line j + 2, j + 3 */
989 for (i=0; i<Coded_Picture_Width; i+=4)
993 Cb1 = *Cb1_ptr++ >> 1;
994 Cr1 = *Cr1_ptr++ >> 1;
995 Cb2 = *Cb2_ptr++ >> 1;
996 Cr2 = *Cr2_ptr++ >> 1;
997 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+3]|Cb_Table[((Cb1+Cb2)>>1)+3]
998 |Cr_Table[((Cr1+Cr2)>>1)+3]];
999 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+15]|Cb_Table[((Cb1+3*Cb2)>>2)+15]
1000 |Cr_Table[((Cr1+3*Cr2)>>2)+15]];
1004 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+11]|Cb_Table[((Cb1+Cb2)>>1)+11]
1005 |Cr_Table[((Cr1+Cr2)>>1)+11]];
1006 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+7]|Cb_Table[((Cb1+3*Cb2)>>2)+7]
1007 |Cr_Table[((Cr1+3*Cr2)>>2)+7]];
1011 Cb1 = *Cb1_ptr++ >> 1;
1012 Cr1 = *Cr1_ptr++ >> 1;
1013 Cb2 = *Cb2_ptr++ >> 1;
1014 Cr2 = *Cr2_ptr++ >> 1;
1015 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+1]|Cb_Table[((Cb1+Cb2)>>1)+1]
1016 |Cr_Table[((Cr1+Cr2)>>1)+1]];
1017 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+13]|Cb_Table[((Cb1+3*Cb2)>>2)+13]
1018 |Cr_Table[((Cr1+3*Cr2)>>2)+13]];
1022 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+9]|Cb_Table[((Cb1+Cb2)>>1)+9]
1023 |Cr_Table[((Cr1+Cr2)>>1)+9]];
1024 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+5]|Cb_Table[((Cb1+3*Cb2)>>2)+5]
1025 |Cr_Table[((Cr1+3*Cr2)>>2)+5]];
1028 Y1_ptr += Coded_Picture_Width;
1029 Y2_ptr += Coded_Picture_Width;
1030 Cb1_ptr += Chroma_Width;
1031 Cr1_ptr += Chroma_Width;
1032 if (j!=(Coded_Picture_Height-8))
1034 Cb2_ptr += Chroma_Width;
1035 Cr2_ptr += Chroma_Width;
1039 Cb2_ptr -= Chroma_Width;
1040 Cr2_ptr -= Chroma_Width;
1042 dst += Coded_Picture_Width;
1043 dst2+= Coded_Picture_Width;
1047 static void Dither_Bottom_Field420(src,dst)
1048 unsigned char *src[];
1052 int Y1,Cb1,Cr1,Y2,Cb2,Cr2;
1053 unsigned char *Y1_ptr,*Cb1_ptr,*Cr1_ptr,*Y2_ptr,*Cb2_ptr,*Cr2_ptr,*dst2;
1055 Y2_ptr = Y1_ptr = src[0] + Coded_Picture_Width;
1056 Cb2_ptr = Cb1_ptr = src[1] + Chroma_Width;
1057 Cr2_ptr = Cr1_ptr = src[2] + Chroma_Width;
1061 for (j=0; j<Coded_Picture_Height; j+=4)
1063 /* line j + 0, j + 1 */
1064 for (i=0; i<Coded_Picture_Width; i+=4)
1068 Cb1 = *Cb1_ptr++ >> 1;
1069 Cr1 = *Cr1_ptr++ >> 1;
1070 Cb2 = *Cb2_ptr++ >> 1;
1071 Cr2 = *Cr2_ptr++ >> 1;
1072 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+15]|Cb_Table[((3*Cb1+Cb2)>>2)+15]
1073 |Cr_Table[((3*Cr1+Cr2)>>2)+15]];
1074 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)]|Cb_Table[((Cb1+Cb2)>>1)]
1075 |Cr_Table[((Cr1+Cr2)>>1)]];
1079 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+7]|Cb_Table[((3*Cb1+Cb2)>>2)+7]
1080 |Cr_Table[((3*Cr1+Cr2)>>2)+7]];
1081 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+8]|Cb_Table[((Cb1+Cb2)>>1)+8]
1082 |Cr_Table[((Cr1+Cr2)>>1)+8]];
1086 Cb1 = *Cb1_ptr++ >> 1;
1087 Cr1 = *Cr1_ptr++ >> 1;
1088 Cb2 = *Cb2_ptr++ >> 1;
1089 Cr2 = *Cr2_ptr++ >> 1;
1090 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+13]|Cb_Table[((3*Cb1+Cb2)>>2)+13]
1091 |Cr_Table[((3*Cr1+Cr2)>>2)+13]];
1092 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+2]|Cb_Table[((Cb1+Cb2)>>1)+2]
1093 |Cr_Table[((Cr1+Cr2)>>1)+2]];
1097 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+5]|Cb_Table[((3*Cb1+Cb2)>>2)+5]
1098 |Cr_Table[((3*Cr1+Cr2)>>2)+5]];
1099 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+10]|Cb_Table[((Cb1+Cb2)>>1)+10]
1100 |Cr_Table[((Cr1+Cr2)>>1)+10]];
1104 Y1_ptr += Coded_Picture_Width;
1106 Y1_ptr -= Coded_Picture_Width;
1108 Y2_ptr += Coded_Picture_Width;
1110 Cb1_ptr -= Chroma_Width;
1111 Cr1_ptr -= Chroma_Width;
1112 Cb2_ptr -= Chroma_Width;
1113 Cr2_ptr -= Chroma_Width;
1116 dst += Coded_Picture_Width;
1118 dst2 += Coded_Picture_Width;
1120 /* line j + 2, j + 3 */
1121 for (i=0; i<Coded_Picture_Width; i+=4)
1125 Cb1 = *Cb1_ptr++ >> 1;
1126 Cr1 = *Cr1_ptr++ >> 1;
1127 Cb2 = *Cb2_ptr++ >> 1;
1128 Cr2 = *Cr2_ptr++ >> 1;
1129 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+12]|Cb_Table[((Cb1+3*Cb2)>>2)+12]
1130 |Cr_Table[((Cr1+3*Cr2)>>2)+12]];
1131 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+3]|Cb_Table[Cb2+3]
1136 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+4]|Cb_Table[((Cb1+3*Cb2)>>2)+4]
1137 |Cr_Table[((Cr1+3*Cr2)>>2)+4]];
1138 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+11]|Cb_Table[Cb2+11]
1143 Cb1 = *Cb1_ptr++ >> 1;
1144 Cr1 = *Cr1_ptr++ >> 1;
1145 Cb2 = *Cb2_ptr++ >> 1;
1146 Cr2 = *Cr2_ptr++ >> 1;
1147 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+14]|Cb_Table[((Cb1+3*Cb2)>>2)+14]
1148 |Cr_Table[((Cr1+3*Cr2)>>2)+14]];
1149 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+1]|Cb_Table[Cb2+1]
1154 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+6]|Cb_Table[((Cb1+3*Cb2)>>2)+6]
1155 |Cr_Table[((Cr1+3*Cr2)>>2)+6]];
1156 *dst2++ = Pixel[Y_Table[((Y1+3*Y2)>>2)+9]|Cb_Table[Cb2+9]
1160 Y1_ptr += Coded_Picture_Width;
1161 Y2_ptr += Coded_Picture_Width;
1165 Cb1_ptr += Chroma_Width;
1166 Cr1_ptr += Chroma_Width;
1170 Cb1_ptr -= Chroma_Width;
1171 Cr1_ptr -= Chroma_Width;
1174 Cb2_ptr += Chroma_Width;
1175 Cr2_ptr += Chroma_Width;
1177 dst += Coded_Picture_Width;
1178 dst2+= Coded_Picture_Width;
1181 Y2_ptr -= (Coded_Picture_Width<<1);
1182 Cb2_ptr -= (Chroma_Width<<1);
1183 Cr2_ptr -= (Chroma_Width<<1);
1185 /* dither last line */
1186 for (i=0; i<Coded_Picture_Width; i+=4)
1190 Cb1 = *Cb1_ptr++ >> 1;
1191 Cr1 = *Cr1_ptr++ >> 1;
1192 Cb2 = *Cb2_ptr++ >> 1;
1193 Cr2 = *Cr2_ptr++ >> 1;
1194 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+15]|Cb_Table[((3*Cb1+Cb2)>>2)+15]
1195 |Cr_Table[((3*Cr1+Cr2)>>2)+15]];
1199 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+7]|Cb_Table[((3*Cb1+Cb2)>>2)+7]
1200 |Cr_Table[((3*Cr1+Cr2)>>2)+7]];
1204 Cb1 = *Cb1_ptr++ >> 1;
1205 Cr1 = *Cr1_ptr++ >> 1;
1206 Cb2 = *Cb2_ptr++ >> 1;
1207 Cr2 = *Cr2_ptr++ >> 1;
1208 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+13]|Cb_Table[((3*Cb1+Cb2)>>2)+13]
1209 |Cr_Table[((3*Cr1+Cr2)>>2)+13]];
1213 *dst++ = Pixel[Y_Table[((3*Y1+Y2)>>2)+5]|Cb_Table[((3*Cb1+Cb2)>>2)+5]
1214 |Cr_Table[((3*Cr1+Cr2)>>2)+5]];