/* display.c, X11 interface */ /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */ /* * Disclaimer of Warranty * * These software programs are available to the user without any license fee or * royalty on an "as is" basis. The MPEG Software Simulation Group disclaims * any and all warranties, whether express, implied, or statuary, including any * implied warranties or merchantability or of fitness for a particular * purpose. In no event shall the copyright-holder be liable for any * incidental, punitive, or consequential damages of any kind whatsoever * arising from the use of these programs. * * This disclaimer of warranty extends to the user of these programs and user's * customers, employees, agents, transferees, successors, and assigns. * * The MPEG Software Simulation Group does not represent or warrant that the * programs furnished hereunder are free of infringement of any third-party * patents. * * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware, * are subject to royalty fees to patent holders. Many of these patents are * general enough such that they are unavoidable regardless of implementation * design. * */ #ifdef DISPLAY /* the Xlib interface is closely modeled after * mpeg_play 2.0 by the Berkeley Plateau Research Group */ #include #include #include #include #include "config.h" #include "global.h" /* private prototypes */ static void Display_Image _ANSI_ARGS_((XImage * Ximage_Ptr, unsigned char *Dithered_Image)); static void Dither_Frame _ANSI_ARGS_((unsigned char *src[])); static void Dither_Top_Field _ANSI_ARGS_((unsigned char *src[], unsigned char *dst)); static void Dither_Bottom_Field _ANSI_ARGS_((unsigned char *src[], unsigned char *dst)); static void Dither_Top_Field420 _ANSI_ARGS_((unsigned char *src[], unsigned char *dst)); static void Dither_Bottom_Field420 _ANSI_ARGS_((unsigned char *src[], unsigned char *dst)); /* local data */ static unsigned char *Dithered_Image, *Dithered_Image2; static unsigned char Y_Table[256 + 16]; static unsigned char Cb_Table[128 + 16]; static unsigned char Cr_Table[128 + 16]; /* X11 related variables */ static Display *Display_Ptr; static Window Window_Instance; static GC GC_Instance; static XImage *Ximage_Ptr, *Ximage_Ptr2; static unsigned char Pixel[256]; #ifdef SH_MEM #include #include #include static int HandleXError _ANSI_ARGS_((Display * dpy, XErrorEvent * event)); static void InstallXErrorHandler _ANSI_ARGS_((void)); static void DeInstallXErrorHandler _ANSI_ARGS_((void)); static int Shmem_Flag; static XShmSegmentInfo Shminfo1, Shminfo2; static int gXErrorFlag; static int CompletionType = -1; static int HandleXError(Dpy, Event) Display *Dpy; XErrorEvent *Event; { gXErrorFlag = 1; return 0; } static void InstallXErrorHandler() { XSetErrorHandler(HandleXError); XFlush(Display_Ptr); } static void DeInstallXErrorHandler() { XSetErrorHandler(NULL); XFlush(Display_Ptr); } #endif /* connect to server, create and map window, * allocate colors and (shared) memory */ void Initialize_Display_Process(name) char *name; { int crv, cbu, cgu, cgv; int Y, Cb, Cr, R, G, B; int i; char dummy; int screen; Colormap cmap; int private; XColor xcolor; unsigned int fg, bg; char *hello = "MPEG-2 Display"; XSizeHints hint; XVisualInfo vinfo; XEvent xev; unsigned long tmp_pixel; XWindowAttributes xwa; Display_Ptr = XOpenDisplay(name); if (Display_Ptr == NULL) Error("Can not open display\n"); screen = DefaultScreen(Display_Ptr); hint.x = 200; hint.y = 200; hint.width = horizontal_size; hint.height = vertical_size; hint.flags = PPosition | PSize; /* Get some colors */ bg = WhitePixel(Display_Ptr, screen); fg = BlackPixel(Display_Ptr, screen); /* Make the window */ if (!XMatchVisualInfo(Display_Ptr, screen, 8, PseudoColor, &vinfo)) { if (!XMatchVisualInfo(Display_Ptr, screen, 8, GrayScale, &vinfo)) Error("requires 8 bit display\n"); } Window_Instance = XCreateSimpleWindow(Display_Ptr, DefaultRootWindow(Display_Ptr), hint.x, hint.y, hint.width, hint.height, 4, fg, bg); XSelectInput(Display_Ptr, Window_Instance, StructureNotifyMask); /* Tell other applications about this window */ XSetStandardProperties(Display_Ptr, Window_Instance, hello, hello, None, NULL, 0, &hint); /* Map window. */ XMapWindow(Display_Ptr, Window_Instance); /* Wait for map. */ do { XNextEvent(Display_Ptr, &xev); } while (xev.type != MapNotify || xev.xmap.event != Window_Instance); XSelectInput(Display_Ptr, Window_Instance, NoEventMask); /* matrix coefficients */ crv = Inverse_Table_6_9[matrix_coefficients][0]; cbu = Inverse_Table_6_9[matrix_coefficients][1]; cgu = Inverse_Table_6_9[matrix_coefficients][2]; cgv = Inverse_Table_6_9[matrix_coefficients][3]; /* allocate colors */ GC_Instance = DefaultGC(Display_Ptr, screen); cmap = DefaultColormap(Display_Ptr, screen); private = 0; /* color allocation: * i is the (internal) 8 bit color number, it consists of separate * bit fields for Y, U and V: i = (yyyyuuvv), we don't use yyyy=0000 * and yyyy=1111, this leaves 32 colors for other applications * * the allocated colors correspond to the following Y, U and V values: * Y: 24, 40, 56, 72, 88, 104, 120, 136, 152, 168, 184, 200, 216, 232 * U,V: -48, -16, 16, 48 * * U and V values span only about half the color space; this gives * usually much better quality, although highly saturated colors can * not be displayed properly * * translation to R,G,B is implicitly done by the color look-up table */ for (i = 16; i < 240; i++) { /* color space conversion */ Y = 16 * ((i >> 4) & 15) + 8; Cb = 32 * ((i >> 2) & 3) - 48; Cr = 32 * (i & 3) - 48; Y = 76309 * (Y - 16); /* (255/219)*65536 */ R = Clip[(Y + crv * Cr + 32768) >> 16]; G = Clip[(Y - cgu * Cb - cgv * Cr + 32768) >> 16]; B = Clip[(Y + cbu * Cb + 32786) >> 16]; /* X11 colors are 16 bit */ xcolor.red = R << 8; xcolor.green = G << 8; xcolor.blue = B << 8; if (XAllocColor(Display_Ptr, cmap, &xcolor) != 0) Pixel[i] = xcolor.pixel; else { /* allocation failed, have to use a private colormap */ if (private) Error("Couldn't allocate private colormap"); private = 1; if (!Quiet_Flag) fprintf(stderr, "Using private colormap (%d colors were available).\n", i - 16); /* Free colors. */ while (--i >= 16) { tmp_pixel = Pixel[i]; /* because XFreeColors expects unsigned long */ XFreeColors(Display_Ptr, cmap, &tmp_pixel, 1, 0); } /* i is now 15, this restarts the outer loop */ /* create private colormap */ XGetWindowAttributes(Display_Ptr, Window_Instance, &xwa); cmap = XCreateColormap(Display_Ptr, Window_Instance, xwa.visual, AllocNone); XSetWindowColormap(Display_Ptr, Window_Instance, cmap); } } #ifdef SH_MEM if (XShmQueryExtension(Display_Ptr)) Shmem_Flag = 1; else { Shmem_Flag = 0; if (!Quiet_Flag) fprintf(stderr, "Shared memory not supported\nReverting to normal Xlib\n"); } if (Shmem_Flag) CompletionType = XShmGetEventBase(Display_Ptr) + ShmCompletion; InstallXErrorHandler(); if (Shmem_Flag) { Ximage_Ptr = XShmCreateImage(Display_Ptr, None, 8, ZPixmap, NULL, &Shminfo1, Coded_Picture_Width, Coded_Picture_Height); if (!progressive_sequence) Ximage_Ptr2 = XShmCreateImage(Display_Ptr, None, 8, ZPixmap, NULL, &Shminfo2, Coded_Picture_Width, Coded_Picture_Height); /* If no go, then revert to normal Xlib calls. */ if (Ximage_Ptr == NULL || (!progressive_sequence && Ximage_Ptr2 == NULL)) { if (Ximage_Ptr != NULL) XDestroyImage(Ximage_Ptr); if (!progressive_sequence && Ximage_Ptr2 != NULL) XDestroyImage(Ximage_Ptr2); if (!Quiet_Flag) fprintf(stderr, "Shared memory error, disabling (Ximage error)\n"); goto shmemerror; } /* Success here, continue. */ Shminfo1.shmid = shmget(IPC_PRIVATE, Ximage_Ptr->bytes_per_line * Ximage_Ptr->height, IPC_CREAT | 0777); if (!progressive_sequence) Shminfo2.shmid = shmget(IPC_PRIVATE, Ximage_Ptr2->bytes_per_line * Ximage_Ptr2->height, IPC_CREAT | 0777); if (Shminfo1.shmid < 0 || (!progressive_sequence && Shminfo2.shmid < 0)) { XDestroyImage(Ximage_Ptr); if (!progressive_sequence) XDestroyImage(Ximage_Ptr2); if (!Quiet_Flag) fprintf(stderr, "Shared memory error, disabling (seg id error)\n"); goto shmemerror; } Shminfo1.shmaddr = (char *) shmat(Shminfo1.shmid, 0, 0); Shminfo2.shmaddr = (char *) shmat(Shminfo2.shmid, 0, 0); if (Shminfo1.shmaddr == ((char *) -1) || (!progressive_sequence && Shminfo2.shmaddr == ((char *) -1))) { XDestroyImage(Ximage_Ptr); if (Shminfo1.shmaddr != ((char *) -1)) shmdt(Shminfo1.shmaddr); if (!progressive_sequence) { XDestroyImage(Ximage_Ptr2); if (Shminfo2.shmaddr != ((char *) -1)) shmdt(Shminfo2.shmaddr); } if (!Quiet_Flag) { fprintf(stderr, "Shared memory error, disabling (address error)\n"); } goto shmemerror; } Ximage_Ptr->data = Shminfo1.shmaddr; Dithered_Image = (unsigned char *) Ximage_Ptr->data; Shminfo1.readOnly = False; XShmAttach(Display_Ptr, &Shminfo1); if (!progressive_sequence) { Ximage_Ptr2->data = Shminfo2.shmaddr; Dithered_Image2 = (unsigned char *) Ximage_Ptr2->data; Shminfo2.readOnly = False; XShmAttach(Display_Ptr, &Shminfo2); } XSync(Display_Ptr, False); if (gXErrorFlag) { /* Ultimate failure here. */ XDestroyImage(Ximage_Ptr); shmdt(Shminfo1.shmaddr); if (!progressive_sequence) { XDestroyImage(Ximage_Ptr2); shmdt(Shminfo2.shmaddr); } if (!Quiet_Flag) fprintf(stderr, "Shared memory error, disabling.\n"); gXErrorFlag = 0; goto shmemerror; } else { shmctl(Shminfo1.shmid, IPC_RMID, 0); if (!progressive_sequence) shmctl(Shminfo2.shmid, IPC_RMID, 0); } if (!Quiet_Flag) { fprintf(stderr, "Sharing memory.\n"); } } else { shmemerror: Shmem_Flag = 0; #endif Ximage_Ptr = XCreateImage(Display_Ptr, None, 8, ZPixmap, 0, &dummy, Coded_Picture_Width, Coded_Picture_Height, 8, 0); if (! (Dithered_Image = (unsigned char *) malloc(Coded_Picture_Width * Coded_Picture_Height))) Error("malloc failed"); if (!progressive_sequence) { Ximage_Ptr2 = XCreateImage(Display_Ptr, None, 8, ZPixmap, 0, &dummy, Coded_Picture_Width, Coded_Picture_Height, 8, 0); if (! (Dithered_Image2 = (unsigned char *) malloc(Coded_Picture_Width * Coded_Picture_Height))) Error("malloc failed"); } #ifdef SH_MEM } DeInstallXErrorHandler(); #endif } void Terminate_Display_Process() { #ifdef SH_MEM if (Shmem_Flag) { XShmDetach(Display_Ptr, &Shminfo1); XDestroyImage(Ximage_Ptr); shmdt(Shminfo1.shmaddr); if (!progressive_sequence) { XShmDetach(Display_Ptr, &Shminfo2); XDestroyImage(Ximage_Ptr2); shmdt(Shminfo2.shmaddr); } } #endif } static void Display_Image(Ximage_Ptr, Dithered_Image) XImage *Ximage_Ptr; unsigned char *Dithered_Image; { /* display dithered image */ #ifdef SH_MEM if (Shmem_Flag) { XShmPutImage(Display_Ptr, Window_Instance, GC_Instance, Ximage_Ptr, 0, 0, 0, 0, Ximage_Ptr->width, Ximage_Ptr->height, True); XFlush(Display_Ptr); while (1) { XEvent xev; XNextEvent(Display_Ptr, &xev); if (xev.type == CompletionType) break; } } else #endif { Ximage_Ptr->data = (char *) Dithered_Image; XPutImage(Display_Ptr, Window_Instance, GC_Instance, Ximage_Ptr, 0, 0, 0, 0, Ximage_Ptr->width, Ximage_Ptr->height); } } void Display_Second_Field() { Display_Image(Ximage_Ptr2, Dithered_Image2); } /* 4x4 ordered dither * * threshold pattern: * 0 8 2 10 * 12 4 14 6 * 3 11 1 9 * 15 7 13 5 */ void Initialize_Dither_Matrix() { int i, v; for (i = -8; i < 256 + 8; i++) { v = i >> 4; if (v < 1) v = 1; else if (v > 14) v = 14; Y_Table[i + 8] = v << 4; } for (i = 0; i < 128 + 16; i++) { v = (i - 40) >> 4; if (v < 0) v = 0; else if (v > 3) v = 3; Cb_Table[i] = v << 2; Cr_Table[i] = v; } } void dither(src) unsigned char *src[]; { /* should this test only the display flag, not progressive_sequence ? --CF */ /* CHANGE 95/05/13: progressive_sequence -> progressive_frame */ if (progressive_frame || Display_Progressive_Flag) Dither_Frame(src); else { if ((picture_structure == FRAME_PICTURE && top_field_first) || picture_structure == BOTTOM_FIELD) { /* top field first */ if (chroma_format == CHROMA420 && hiQdither) { Dither_Top_Field420(src, Dithered_Image); Dither_Bottom_Field420(src, Dithered_Image2); } else { Dither_Top_Field(src, Dithered_Image); Dither_Bottom_Field(src, Dithered_Image2); } } else { /* bottom field first */ if (chroma_format == CHROMA420 && hiQdither) { Dither_Bottom_Field420(src, Dithered_Image); Dither_Top_Field420(src, Dithered_Image2); } else { Dither_Bottom_Field(src, Dithered_Image); Dither_Top_Field(src, Dithered_Image2); } } } Display_Image(Ximage_Ptr, Dithered_Image); } static void Dither_Frame(src) unsigned char *src[]; { int i, j; int y, u, v; unsigned char *py, *pu, *pv, *dst; py = src[0]; pu = src[1]; pv = src[2]; dst = Dithered_Image; for (j = 0; j < Coded_Picture_Height; j += 4) { /* line j + 0 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y] | Cb_Table[u] | Cr_Table[v]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 8] | Cb_Table[u + 8] | Cr_Table[v + 8]]; y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 2] | Cb_Table[u + 2] | Cr_Table[v + 2]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 10] | Cb_Table[u + 10] | Cr_Table[v + 10]]; } if (chroma_format == CHROMA420) { pu -= Chroma_Width; pv -= Chroma_Width; } /* line j + 1 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 12] | Cb_Table[u + 12] | Cr_Table[v + 12]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 4] | Cb_Table[u + 4] | Cr_Table[v + 4]]; y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 14] | Cb_Table[u + 14] | Cr_Table[v + 14]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 6] | Cb_Table[u + 6] | Cr_Table[v + 6]]; } /* line j + 2 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 3] | Cb_Table[u + 3] | Cr_Table[v + 3]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 11] | Cb_Table[u + 11] | Cr_Table[v + 11]]; y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 1] | Cb_Table[u + 1] | Cr_Table[v + 1]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 9] | Cb_Table[u + 9] | Cr_Table[v + 9]]; } if (chroma_format == CHROMA420) { pu -= Chroma_Width; pv -= Chroma_Width; } /* line j + 3 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 15] | Cb_Table[u + 15] | Cr_Table[v + 15]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 7] | Cb_Table[u + 7] | Cr_Table[v + 7]]; y = *py++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 13] | Cb_Table[u + 13] | Cr_Table[v + 13]]; y = *py++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 5] | Cb_Table[u + 5] | Cr_Table[v + 5]]; } } } static void Dither_Top_Field(src, dst) unsigned char *src[]; unsigned char *dst; { int i, j; int y, Y2, u, v; unsigned char *py, *Y2_ptr, *pu, *pv, *dst2; py = src[0]; Y2_ptr = src[0] + (Coded_Picture_Width << 1); pu = src[1]; pv = src[2]; dst2 = dst + Coded_Picture_Width; for (j = 0; j < Coded_Picture_Height; j += 4) { /* line j + 0, j + 1 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y] | Cb_Table[u] | Cr_Table[v]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 12] | Cb_Table[u + 12] | Cr_Table[v + 12]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 8] | Cb_Table[u + 8] | Cr_Table[v + 8]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 4] | Cb_Table[u + 4] | Cr_Table[v + 4]]; y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 2] | Cb_Table[u + 2] | Cr_Table[v + 2]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 14] | Cb_Table[u + 14] | Cr_Table[v + 14]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 10] | Cb_Table[u + 10] | Cr_Table[v + 10]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 6] | Cb_Table[u + 6] | Cr_Table[v + 6]]; } py += Coded_Picture_Width; if (j != (Coded_Picture_Height - 4)) Y2_ptr += Coded_Picture_Width; else Y2_ptr -= Coded_Picture_Width; dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; if (chroma_format == CHROMA420) { pu -= Chroma_Width; pv -= Chroma_Width; } else { pu += Chroma_Width; pv += Chroma_Width; } /* line j + 2, j + 3 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 3] | Cb_Table[u + 3] | Cr_Table[v + 3]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 15] | Cb_Table[u + 15] | Cr_Table[v + 15]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 11] | Cb_Table[u + 11] | Cr_Table[v + 11]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 7] | Cb_Table[u + 7] | Cr_Table[v + 7]]; y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[y + 1] | Cb_Table[u + 1] | Cr_Table[v + 1]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 13] | Cb_Table[u + 13] | Cr_Table[v + 13]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[y + 9] | Cb_Table[u + 9] | Cr_Table[v + 9]]; *dst2++ = Pixel[Y_Table[((y + Y2) >> 1) + 5] | Cb_Table[u + 5] | Cr_Table[v + 5]]; } py += Coded_Picture_Width; Y2_ptr += Coded_Picture_Width; dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; pu += Chroma_Width; pv += Chroma_Width; } } static void Dither_Bottom_Field(src, dst) unsigned char *src[]; unsigned char *dst; { int i, j; int y, Y2, u, v; unsigned char *py, *Y2_ptr, *pu, *pv, *dst2; py = src[0] + Coded_Picture_Width; Y2_ptr = py; pu = src[1] + Chroma_Width; pv = src[2] + Chroma_Width; dst2 = dst + Coded_Picture_Width; for (j = 0; j < Coded_Picture_Height; j += 4) { /* line j + 0, j + 1 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[((y + Y2) >> 1)] | Cb_Table[u] | Cr_Table[v]]; *dst2++ = Pixel[Y_Table[Y2 + 12] | Cb_Table[u + 12] | Cr_Table[v + 12]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 8] | Cb_Table[u + 8] | Cr_Table[v + 8]]; *dst2++ = Pixel[Y_Table[Y2 + 4] | Cb_Table[u + 4] | Cr_Table[v + 4]]; y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 2] | Cb_Table[u + 2] | Cr_Table[v + 2]]; *dst2++ = Pixel[Y_Table[Y2 + 14] | Cb_Table[u + 14] | Cr_Table[v + 14]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 10] | Cb_Table[u + 10] | Cr_Table[v + 10]]; *dst2++ = Pixel[Y_Table[Y2 + 6] | Cb_Table[u + 6] | Cr_Table[v + 6]]; } if (j == 0) py -= Coded_Picture_Width; else py += Coded_Picture_Width; Y2_ptr += Coded_Picture_Width; dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; if (chroma_format == CHROMA420) { pu -= Chroma_Width; pv -= Chroma_Width; } else { pu += Chroma_Width; pv += Chroma_Width; } /* line j + 2. j + 3 */ for (i = 0; i < Coded_Picture_Width; i += 4) { y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 3] | Cb_Table[u + 3] | Cr_Table[v + 3]]; *dst2++ = Pixel[Y_Table[Y2 + 15] | Cb_Table[u + 15] | Cr_Table[v + 15]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 11] | Cb_Table[u + 11] | Cr_Table[v + 11]]; *dst2++ = Pixel[Y_Table[Y2 + 7] | Cb_Table[u + 7] | Cr_Table[v + 7]]; y = *py++; Y2 = *Y2_ptr++; u = *pu++ >> 1; v = *pv++ >> 1; *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 1] | Cb_Table[u + 1] | Cr_Table[v + 1]]; *dst2++ = Pixel[Y_Table[Y2 + 13] | Cb_Table[u + 13] | Cr_Table[v + 13]]; y = *py++; Y2 = *Y2_ptr++; if (chroma_format == CHROMA444) { u = *pu++ >> 1; v = *pv++ >> 1; } *dst++ = Pixel[Y_Table[((y + Y2) >> 1) + 9] | Cb_Table[u + 9] | Cr_Table[v + 9]]; *dst2++ = Pixel[Y_Table[Y2 + 5] | Cb_Table[u + 5] | Cr_Table[v + 5]]; } py += Coded_Picture_Width; Y2_ptr += Coded_Picture_Width; dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; pu += Chroma_Width; pv += Chroma_Width; } } static void Dither_Top_Field420(src, dst) unsigned char *src[]; unsigned char *dst; { int i, j; int Y1, Cb1, Cr1, Y2, Cb2, Cr2; unsigned char *Y1_ptr, *Cb1_ptr, *Cr1_ptr, *Y2_ptr, *Cb2_ptr, *Cr2_ptr, *dst2; Y1_ptr = src[0]; Cb1_ptr = src[1]; Cr1_ptr = src[2]; Y2_ptr = Y1_ptr + (Coded_Picture_Width << 1); Cb2_ptr = Cb1_ptr + (Chroma_Width << 1); Cr2_ptr = Cr1_ptr + (Chroma_Width << 1); dst2 = dst + Coded_Picture_Width; for (j = 0; j < Coded_Picture_Height; j += 4) { /* line j + 0, j + 1 */ for (i = 0; i < Coded_Picture_Width; i += 4) { Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2)] | Cb_Table[Cb1] | Cr_Table[Cr1]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 12] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 12] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 12]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 8] | Cb_Table[Cb1 + 8] | Cr_Table[Cr1 + 8]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 4] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 4] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 4]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 2] | Cb_Table[Cb1 + 2] | Cr_Table[Cr1 + 2]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 14] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 14] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 14]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 10] | Cb_Table[Cb1 + 10] | Cr_Table[Cr1 + 10]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 6] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 6] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 6]]; } Y1_ptr += Coded_Picture_Width; if (j != (Coded_Picture_Height - 4)) Y2_ptr += Coded_Picture_Width; else Y2_ptr -= Coded_Picture_Width; Cb1_ptr -= Chroma_Width; Cr1_ptr -= Chroma_Width; Cb2_ptr -= Chroma_Width; Cr2_ptr -= Chroma_Width; dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; /* line j + 2, j + 3 */ for (i = 0; i < Coded_Picture_Width; i += 4) { Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 3] | Cb_Table[((Cb1 + Cb2) >> 1) + 3] | Cr_Table[((Cr1 + Cr2) >> 1) + 3]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 15] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 15] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 15]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 11] | Cb_Table[((Cb1 + Cb2) >> 1) + 11] | Cr_Table[((Cr1 + Cr2) >> 1) + 11]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 7] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 7] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 7]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 1] | Cb_Table[((Cb1 + Cb2) >> 1) + 1] | Cr_Table[((Cr1 + Cr2) >> 1) + 1]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 13] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 13] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 13]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 9] | Cb_Table[((Cb1 + Cb2) >> 1) + 9] | Cr_Table[((Cr1 + Cr2) >> 1) + 9]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 5] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 5] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 5]]; } Y1_ptr += Coded_Picture_Width; Y2_ptr += Coded_Picture_Width; Cb1_ptr += Chroma_Width; Cr1_ptr += Chroma_Width; if (j != (Coded_Picture_Height - 8)) { Cb2_ptr += Chroma_Width; Cr2_ptr += Chroma_Width; } else { Cb2_ptr -= Chroma_Width; Cr2_ptr -= Chroma_Width; } dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; } } static void Dither_Bottom_Field420(src, dst) unsigned char *src[]; unsigned char *dst; { int i, j; int Y1, Cb1, Cr1, Y2, Cb2, Cr2; unsigned char *Y1_ptr, *Cb1_ptr, *Cr1_ptr, *Y2_ptr, *Cb2_ptr, *Cr2_ptr, *dst2; Y2_ptr = Y1_ptr = src[0] + Coded_Picture_Width; Cb2_ptr = Cb1_ptr = src[1] + Chroma_Width; Cr2_ptr = Cr1_ptr = src[2] + Chroma_Width; dst2 = dst; for (j = 0; j < Coded_Picture_Height; j += 4) { /* line j + 0, j + 1 */ for (i = 0; i < Coded_Picture_Width; i += 4) { Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 15] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 15] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 15]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2)] | Cb_Table[((Cb1 + Cb2) >> 1)] | Cr_Table[((Cr1 + Cr2) >> 1)]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 7] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 7] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 7]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 8] | Cb_Table[((Cb1 + Cb2) >> 1) + 8] | Cr_Table[((Cr1 + Cr2) >> 1) + 8]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 13] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 13] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 13]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 2] | Cb_Table[((Cb1 + Cb2) >> 1) + 2] | Cr_Table[((Cr1 + Cr2) >> 1) + 2]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 5] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 5] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 5]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 10] | Cb_Table[((Cb1 + Cb2) >> 1) + 10] | Cr_Table[((Cr1 + Cr2) >> 1) + 10]]; } if (j != 0) Y1_ptr += Coded_Picture_Width; else Y1_ptr -= Coded_Picture_Width; Y2_ptr += Coded_Picture_Width; Cb1_ptr -= Chroma_Width; Cr1_ptr -= Chroma_Width; Cb2_ptr -= Chroma_Width; Cr2_ptr -= Chroma_Width; if (j != 0) dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; /* line j + 2, j + 3 */ for (i = 0; i < Coded_Picture_Width; i += 4) { Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 12] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 12] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 12]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 3] | Cb_Table[Cb2 + 3] | Cr_Table[Cr2 + 3]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 4] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 4] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 4]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 11] | Cb_Table[Cb2 + 11] | Cr_Table[Cr2 + 11]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 14] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 14] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 14]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 1] | Cb_Table[Cb2 + 1] | Cr_Table[Cr2 + 1]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 6] | Cb_Table[((Cb1 + 3 * Cb2) >> 2) + 6] | Cr_Table[((Cr1 + 3 * Cr2) >> 2) + 6]]; *dst2++ = Pixel[Y_Table[((Y1 + 3 * Y2) >> 2) + 9] | Cb_Table[Cb2 + 9] | Cr_Table[Cr2 + 9]]; } Y1_ptr += Coded_Picture_Width; Y2_ptr += Coded_Picture_Width; if (j != 0) { Cb1_ptr += Chroma_Width; Cr1_ptr += Chroma_Width; } else { Cb1_ptr -= Chroma_Width; Cr1_ptr -= Chroma_Width; } Cb2_ptr += Chroma_Width; Cr2_ptr += Chroma_Width; dst += Coded_Picture_Width; dst2 += Coded_Picture_Width; } Y2_ptr -= (Coded_Picture_Width << 1); Cb2_ptr -= (Chroma_Width << 1); Cr2_ptr -= (Chroma_Width << 1); /* dither last line */ for (i = 0; i < Coded_Picture_Width; i += 4) { Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 15] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 15] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 15]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 7] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 7] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 7]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; Cb1 = *Cb1_ptr++ >> 1; Cr1 = *Cr1_ptr++ >> 1; Cb2 = *Cb2_ptr++ >> 1; Cr2 = *Cr2_ptr++ >> 1; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 13] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 13] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 13]]; Y1 = *Y1_ptr++; Y2 = *Y2_ptr++; *dst++ = Pixel[Y_Table[((3 * Y1 + Y2) >> 2) + 5] | Cb_Table[((3 * Cb1 + Cb2) >> 2) + 5] | Cr_Table[((3 * Cr1 + Cr2) >> 2) + 5]]; } } #endif