/* store.c, picture output routines */ /* * tmndecode * Copyright (C) 1995 Telenor R&D * Karl Olav Lillevold * * based on mpeg2decode, (C) 1994, MPEG Software Simulation Group * and mpeg2play, (C) 1994 Stefan Eckart * * */ #include #include #include #include #include "config.h" #include "global.h" /* private prototypes */ static void store_one _ANSI_ARGS_((char *outname, unsigned char *src[], int offset, int incr, int height)); static void store_yuv _ANSI_ARGS_((char *outname, unsigned char *src[], int offset, int incr, int height)); static void store_yuv_append _ANSI_ARGS_((char *outname, unsigned char *src[], int offset, int incr, int height)); static void store_sif _ANSI_ARGS_((char *outname, unsigned char *src[], int offset, int incr, int height)); static void store_ppm_tga _ANSI_ARGS_((char *outname, unsigned char *src[], int offset, int incr, int height, int tgaflag)); static void store_yuv1 _ANSI_ARGS_((char *name, unsigned char *src, int offset, int incr, int width, int height, int append)); static void putbyte _ANSI_ARGS_((int c)); static void putword _ANSI_ARGS_((int w)); static void conv422to444 _ANSI_ARGS_((unsigned char *src, unsigned char *dst)); static void conv420to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst)); #define OBFRSIZE 4096 static unsigned char obfr[OBFRSIZE]; static unsigned char *optr; static int outfile; /* * store a picture as either one frame or two fields */ void storeframe(src,frame) unsigned char *src[]; int frame; { char outname[32]; /* progressive */ sprintf(outname,outputname,frame,'f'); store_one(outname,src,0,coded_picture_width,vertical_size); } /* * store one frame or one field */ static void store_one(outname,src,offset,incr,height) char *outname; unsigned char *src[]; int offset, incr, height; { switch (outtype) { case T_YUV: store_yuv(outname,src,offset,incr,height); break; case T_YUV_CONC: store_yuv_append(outname,src,offset,incr,height); break; case T_SIF: store_sif(outname,src,offset,incr,height); break; case T_TGA: store_ppm_tga(outname,src,offset,incr,height,1); break; case T_PPM: store_ppm_tga(outname,src,offset,incr,height,0); break; #ifdef DISPLAY case T_X11: dither(src); break; #endif default: break; } } /* separate headerless files for y, u and v */ static void store_yuv(outname,src,offset,incr,height) char *outname; unsigned char *src[]; int offset,incr,height; { int hsize; char tmpname[32]; hsize = horizontal_size; sprintf(tmpname,"%s.Y",outname); store_yuv1(tmpname,src[0],offset,incr,hsize,height,0); offset>>=1; incr>>=1; hsize>>=1; height>>=1; sprintf(tmpname,"%s.U",outname); store_yuv1(tmpname,src[1],offset,incr,hsize,height,0); sprintf(tmpname,"%s.V",outname); store_yuv1(tmpname,src[2],offset,incr,hsize,height,0); } /* concatenated headerless file for y, u and v */ static void store_yuv_append(outname,src,offset,incr,height) char *outname; unsigned char *src[]; int offset,incr,height; { int hsize; hsize = horizontal_size; store_yuv1(outname,src[0],offset,incr,hsize,height,1); offset>>=1; incr>>=1; hsize>>=1; height>>=1; store_yuv1(outname,src[1],offset,incr,hsize,height,1); store_yuv1(outname,src[2],offset,incr,hsize,height,1); } /* auxiliary routine */ static void store_yuv1(name,src,offset,incr,width,height,append) char *name; unsigned char *src; int offset,incr,width,height,append; { int i, j; unsigned char *p; if (append) { if ((outfile = open(name,O_APPEND|O_WRONLY|O_BINARY,0666))==-1) { sprintf(errortext,"Couldn't append to %s\n",name); error(errortext); } } else { if ((outfile = open(name,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1) { sprintf(errortext,"Couldn't create %s\n",name); error(errortext); } } if (!quiet) fprintf(stderr,"saving %s\n",name); optr=obfr; for (i=0; i>1) *coded_picture_height))) error("malloc failed"); if (!(v422 = (unsigned char *)malloc((coded_picture_width>>1) *coded_picture_height))) error("malloc failed"); } conv420to422(src[1],u422); conv420to422(src[2],v422); strcat(outname,".SIF"); if (!quiet) fprintf(stderr,"saving %s\n",outname); if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1) { sprintf(errortext,"Couldn't create %s\n",outname); error(errortext); } optr = obfr; for (i=0; i>1) + (incr>>1)*i; pv = v422 + (offset>>1) + (incr>>1)*i; for (j=0; j>1) *coded_picture_height))) error("malloc failed"); if (!(v422 = (unsigned char *)malloc((coded_picture_width>>1) *coded_picture_height))) error("malloc failed"); if (!(u444 = (unsigned char *)malloc(coded_picture_width *coded_picture_height))) error("malloc failed"); if (!(v444 = (unsigned char *)malloc(coded_picture_width *coded_picture_height))) error("malloc failed"); } conv420to422(src[1],u422); conv420to422(src[2],v422); conv422to444(u422,u444); conv422to444(v422,v444); strcat(outname,tgaflag ? ".tga" : ".ppm"); if (!quiet) fprintf(stderr,"saving %s\n",outname); if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1) { sprintf(errortext,"Couldn't create %s\n",outname); error(errortext); } optr = obfr; if (tgaflag) { /* TGA header */ for (i=0; i<12; i++) putbyte(tga24[i]); putword(horizontal_size); putword(height); putbyte(tga24[12]); putbyte(tga24[13]); } else { /* PPM header */ sprintf(header,"P6\n%d %d\n255\n",horizontal_size,height); for (i=0; header[i]!=0; i++) putbyte(header[i]); } /* matrix coefficients */ crv = convmat[matrix_coefficients][0]; cbu = convmat[matrix_coefficients][1]; cgu = convmat[matrix_coefficients][2]; cgv = convmat[matrix_coefficients][3]; for (i=0; i>16]; g = clp[(y - cgu*u - cgv*v + 32768)>>16]; b = clp[(y + cbu*u + 32786)>>16]; if (tgaflag) { putbyte(b); putbyte(g); putbyte(r); } else { putbyte(r); putbyte(g); putbyte(b); } } } if (optr!=obfr) write(outfile,obfr,optr-obfr); close(outfile); } static void putbyte(c) int c; { *optr++ = c; if (optr == obfr+OBFRSIZE) { write(outfile,obfr,OBFRSIZE); optr = obfr; } } static void putword(w) int w; { putbyte(w); putbyte(w>>8); } /* horizontal 1:2 interpolation filter */ static void conv422to444(src,dst) unsigned char *src,*dst; { int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3; w = coded_picture_width>>1; for (j=0; j>8]; dst[i2+1] = clp[(int)( 5*src[ip3] -21*src[ip2] +70*src[ip1] +228*src[i] -37*src[im1] +11*src[im2]+128)>>8]; } src+= w; dst+= coded_picture_width; } } /* vertical 1:2 interpolation filter */ static void conv420to422(src,dst) unsigned char *src,*dst; { int w, h, i, j, j2; int jm3, jm2, jm1, jp1, jp2, jp3; w = coded_picture_width>>1; h = coded_picture_height>>1; /* intra frame */ for (i=0; i>8]; dst[w*(j2+1)] = clp[(int)( 3*src[w*jp3] -16*src[w*jp2] +67*src[w*jp1] +227*src[w*j] -32*src[w*jm1] +7*src[w*jm2]+128)>>8]; } src++; dst++; } }