Hello,
I am a postgrad student at the university of essex in the video networking lab. I am not much of
a programmer and i have been grappling with a programming problem.
I am trying to develop an mpeg frame display using X11. The program only works
on 8 bit displays, but my computer is a 24 bit truecolor.
I will be most grateful if you can look at my program and help me make it display
on 24 bit truecolor.
I can perfectly display images on 8 bit displays
Thank you
********************************
* Emmanuel A Jammeh *
* Postgrad Research Student *
* University of Essex *
* Colchester CO4 3SQ *
* England *
* *
* Tel: 00 44 1206 53 7101 *
* email: [email protected] *
* [email protected] *
********************************
#include <stdio.h>
#include <stdlib.h>
//#include "global.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/time.h>
void init_display (char *name);
void exit_display (void);
void display_second_field (void);
void dither (unsigned char *src[]);
void init_dither (void);
/* private prototypes */
void display_image (XImage *ximage, unsigned char *dithered_image);
void ditherframe (unsigned char *src[]);
void my_error(char* message);
void doframerate();
/* local data */
unsigned char *dithered_image, *dithered_image2;
unsigned char ytab[256+16];
unsigned char utab[128+16];
unsigned char vtab[128+16];
int convmat[8][4]=
{
{117504, 138453, 13954, 34903}, /* no sequence_display_extension */
{117504, 138453, 13954, 34903}, /* ITU-R Rec. 709 (1990) */
{104597, 132201, 25675, 53279}, /* unspecified */
{104597, 132201, 25675, 53279}, /* reserved */
{104448, 132798, 24759, 53109}, /* FCC */
{104597, 132201, 25675, 53279}, /* ITU-R Rec. 624-4 System B, G */
{104597, 132201, 25675, 53279}, /* SMPTE 170M */
{117579, 136230, 16907, 35559} /* SMPTE 240M (1987) */
};
int matrix_coefficients=5;
/* X11 related variables */
Display *display;
Window window;
GC gc;
XImage *ximage, *ximage2;
unsigned char pixel[256];
unsigned char *clp;
int width=352, height=288, chrom_width=176, chrom_height=144;
int framerate = 25;
struct timeval tftarget;
/*____________________________________________________________________________________*/
main(int argc, char* argv[])
{
int i,j;
FILE *fd;
char fname[255];
unsigned char* frame[400][3];
int maxFrameNum,minFrameNum;
unsigned char *showframe;
if (argc<4)
{
fprintf(stderr,"\n\nSyntax: %s InpurSeq From To [width height framerate]\n\n",argv[0]);
exit(0);
}
// clip table
if (!(clp=(unsigned char *)malloc(1024))) exit(0);
clp += 384;
for (i=-384; i<640; i++) clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
minFrameNum = atoi(argv[2]);
maxFrameNum = atoi(argv[3]);
showframe = (unsigned char *) malloc (maxFrameNum-minFrameNum+1);
//memory for the frames
for (i=0;i<maxFrameNum-minFrameNum+1;i++)
{
if (!(frame[i][0] = (unsigned char*)malloc(width*height))) error("MallocFailed");
if (!(frame[i][1] = (unsigned char*)malloc(width*height/4)))error("MallocFailed");
if (!(frame[i][2] = (unsigned char*)malloc(width*height/4)))error("MallocFailed");
showframe[i]=1;
}
if (argc==7)
{
width =atoi(argv[4]); chrom_width =width >>1;
height=atoi(argv[5]); chrom_height=height>>1;
framerate=atoi(argv[6]);
}
else
printf("\nWarning: Width=%d Height=%d Framerate = %d \n\n",width,height,framerate);
init_display(argv[1]); //initialise the display
init_dither(); // initialise the dither
//load the frames
printf("\nLoading Frames to memory..\n");
for (j=0, i=minFrameNum; i<maxFrameNum,j<maxFrameNum-minFrameNum+1; i++, j++)
{
sprintf(fname,"%s%03d.yuv",argv[1],i);
if (!(fd = fopen(fname,"rb")))
{
printf("<%s not found>\n",fname);
showframe[i]=0;
continue;
}
fread(frame[j][0],1,width*height,fd);
fread(frame[j][1],1,width*height/4,fd);
fread(frame[j][2],1,width*height/4,fd);
fclose(fd);
printf("<%d>",i);fflush(stdout);
}
do
{
gettimeofday(&tftarget,(struct timezone *)NULL);
//display the frames
for (i=0;i<maxFrameNum-minFrameNum+1;i++)
{
if (showframe[i])
{
dither(frame[i]);
doframerate();
}
}
}while (1);
}// end of main
/* connect to server, create and map window,
* allocate colors and (shared) memory
*/
void init_display(char *name)
{
int crv, cbu, cgu, cgv;
int y, u, v, r, g, b;
int i;
char dummy;
int screen;
Colormap cmap;
int private;
XColor xcolor;
unsigned int fg, bg;
char *hello = name;
XSizeHints hint;
XVisualInfo vinfo;
XEvent xev;
unsigned long tmp_pixel;
XWindowAttributes xwa;
display = XOpenDisplay("");
if (display == NULL)
my_error("Can not open display\n");
screen = DefaultScreen(display);
hint.x = 200;
hint.y = 200;
hint.width = width;
hint.height = height;
hint.flags = PPosition | PSize;
/* Get some colors */
bg = WhitePixel (display, screen);
fg = BlackPixel (display, screen);
/* Make the window */
if (!XMatchVisualInfo(display, screen, 8, PseudoColor, &vinfo))
{
if (!XMatchVisualInfo(display, screen, 8, GrayScale, &vinfo))
my_error("requires 8 bit display\n");
}
window = XCreateSimpleWindow (display, DefaultRootWindow (display),
hint.x, hint.y, hint.width, hint.height, 4, fg, bg);
XSelectInput(display, window, StructureNotifyMask);
/* Tell other applications about this window */
XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint);
/* Map window. */
XMapWindow(display, window);
/* Wait for map. */
do
{
XNextEvent(display, &xev);
}
while (xev.type != MapNotify || xev.xmap.event != window);
XSelectInput(display, window, NoEventMask);
/* matrix coefficients */
crv = convmat[matrix_coefficients][0];
cbu = convmat[matrix_coefficients][1];
cgu = convmat[matrix_coefficients][2];
cgv = convmat[matrix_coefficients][3];
/* allocate colors */
gc = DefaultGC(display, screen);
cmap = DefaultColormap(display, 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;
u = 32*((i>>2)&3) - 48;
v = 32*(i&3) - 48;
y = 76309 * (y - 16); /* (255/219)*65536 */
r = clp[(y + crv*v + 32768)>>16];
g = clp[(y - cgu*u -cgv*v + 32768)>>16];
b = clp[(y + cbu*u + 32786)>>16];
/* X11 colors are 16 bit */
xcolor.red = r << 8;
xcolor.green = g << 8;
xcolor.blue = b << 8;
if (XAllocColor(display, cmap, &xcolor) != 0)
pixel[i] = xcolor.pixel;
else
{
/* allocation failed, have to use a private colormap */
if (private)
my_error("Couldn't allocate private colormap");
private = 1;
/*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, cmap, &tmp_pixel, 1, 0);
}
/* i is now 15, this restarts the outer loop */
/* create private colormap */
XGetWindowAttributes(display, window, &xwa);
cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
XSetWindowColormap(display, window, cmap);
}
}
ximage = XCreateImage(display,None,8,ZPixmap,0,&dummy,
width,height,8,0);
if (!(dithered_image = (unsigned char *)malloc(width* height)))
my_error("malloc failed");
}
void exit_display()
{
}
void display_image(ximage,dithered_image)
XImage *ximage;
unsigned char *dithered_image;
{
/* display dithered image */
ximage->data = (char *) dithered_image;
XPutImage(display, window, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
}
void display_second_field()
{
display_image(ximage2,dithered_image2);
}
/* 4x4 ordered dither
*
* threshold pattern:
* 0 8 2 10
* 12 4 14 6
* 3 11 1 9
* 15 7 13 5
*/
void init_dither()
{
int i, v;
for (i=-8; i<256+8; i++)
{
v = i>>4;
if (v<1)
v = 1;
else if (v>14)
v = 14;
ytab[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;
utab[i] = v<<2;
vtab[i] = v;
}
}
void dither(src)
unsigned char *src[];
{
ditherframe(src);
display_image(ximage,dithered_image);
}
void ditherframe(src)
unsigned char *src[];
{
int i,j;
int y,u,v;
unsigned char *py,*pu,*pv,*dst;
int chroma_format=1;
int CHROMA444 = 2, CHROMA420 = 1;
py = src[0];
pu = src[1];
pv = src[2];
dst = dithered_image;
for (j=0; j<height; j+=4)
{
/* line j + 0 */
for (i=0; i<width; i+=4)
{
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y]|utab[u]|vtab[v]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+8]|utab[u+8]|vtab[v+8]];
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+2]|utab[u+2]|vtab[v+2]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+10]|utab[u+10]|vtab[v+10]];
}
if (chroma_format==CHROMA420)
{
pu -= chrom_width;
pv -= chrom_width;
}
/* line j + 1 */
for (i=0; i<width; i+=4)
{
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+12]|utab[u+12]|vtab[v+12]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+4]|utab[u+4]|vtab[v+4]];
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+14]|utab[u+14]|vtab[v+14]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+6]|utab[u+6]|vtab[v+6]];
}
/* line j + 2 */
for (i=0; i<width; i+=4)
{
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+3]|utab[u+3]|vtab[v+3]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+11]|utab[u+11]|vtab[v+11]];
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+1]|utab[u+1]|vtab[v+1]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+9]|utab[u+9]|vtab[v+9]];
}
if (chroma_format==CHROMA420)
{
pu -= chrom_width;
pv -= chrom_width;
}
/* line j + 3 */
for (i=0; i<width; i+=4)
{
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+15]|utab[u+15]|vtab[v+15]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+7]|utab[u+7]|vtab[v+7]];
y = *py++;
u = *pu++ >> 1;
v = *pv++ >> 1;
*dst++ = pixel[ytab[y+13]|utab[u+13]|vtab[v+13]];
y = *py++;
if (chroma_format==CHROMA444)
{
u = *pu++ >> 1;
v = *pv++ >> 1;
}
*dst++ = pixel[ytab[y+5]|utab[u+5]|vtab[v+5]];
}
}
}
void my_error(char* message)
{
printf("\n\n%s\n\n",message);
exit(0);
}
void doframerate()
{
struct timeval tfdiff;
const float REF_FRAME_RATE = /*29.97*/ 25.0; /*tjshan: changed by tamer */
tftarget.tv_usec += 1000000 / framerate;
/* this is where we should be */
if (tftarget.tv_usec >= 1000000)
{
tftarget.tv_usec -= 1000000;
tftarget.tv_sec++;
}
/* this is where we are */
gettimeofday(&tfdiff,(struct timezone *)NULL);
tfdiff.tv_usec = tftarget.tv_usec - tfdiff.tv_usec;
tfdiff.tv_sec = tftarget.tv_sec - tfdiff.tv_sec;
if (tfdiff.tv_usec < 0)
{
tfdiff.tv_usec += 1000000;
tfdiff.tv_sec--;
}
/* See if we are already lagging behind */
if (tfdiff.tv_sec < 0 || (tfdiff.tv_sec == 0 && tfdiff.tv_usec <= 0))
return;
/* Spin for awhile */
select(0,NULL,NULL,NULL,&tfdiff);
}