/* tmndec.c, main(), initialization, option processing */ /* * 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 #ifdef USE_TIME #include #endif #define GLOBAL #include "config.h" #include "global.h" /* private prototypes */ static void initdecoder _ANSI_ARGS_((void)); static void options _ANSI_ARGS_((int *argcp, char **argvp[])); static int getval _ANSI_ARGS_((char *argv[])); /* private data */ static int loopflag; int main(argc,argv) int argc; char *argv[]; { int first, framenum; #ifdef USE_TIME int runtime; struct timeval tstart,tstop; #endif options(&argc,&argv); /* pointer to name of output files */ #ifdef DISPLAY if (outtype==T_X11) outputname = ""; else #endif outputname = argv[argc-1]; ld = &base; /* open MPEG input file(s) */ if ((base.infile=open(argv[1],O_RDONLY|O_BINARY))<0) { sprintf(errortext,"Input file %s not found\n",argv[1]); error(errortext); } first = 1; do { if (base.infile!=0) lseek(base.infile,0l,0); initbits(); framenum = tr_framenum = 0; while (getheader()) { if (first) { initdecoder(); #ifdef USE_TIME gettimeofday(&tstart,(struct timezone *)NULL); if (framerate > 0) gettimeofday(&tftarget,(struct timezone *)NULL); #endif first = 0; } getpicture(&framenum); #ifdef USE_TIME if (framerate > 0) doframerate(); #endif framenum++; tr_framenum++; } } while (loopflag); close(base.infile); #ifdef USE_TIME gettimeofday(&tstop,(struct timezone *)NULL); runtime = 100*(tstop.tv_sec-tstart.tv_sec) + (tstop.tv_usec-tstart.tv_usec)/10000; if (!quiet && runtime!=0) printf("%d.%02d seconds, %d frames, %d.%02d fps\n", runtime/100, runtime%100, framenum, ((10000*framenum+runtime/2)/runtime)/100, ((10000*framenum+runtime/2)/runtime)%100); #endif #ifdef DISPLAY if (outtype==T_X11) exit_display(); #endif return 0; } static void initdecoder() { int i, cc, size; FILE *cleared; /* clip table */ if (!(clp=(unsigned char *)malloc(1024))) error("malloc failed\n"); clp += 384; for (i=-384; i<640; i++) clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i); /* MPEG-1 = TMN parameters */ matrix_coefficients = 5; horizontal_size = MBC*16; vertical_size = MBR*16; #ifdef SQCIF if (source_format != SF_SQCIF) { printf("This version was compiled for SQCIF format (128x96)\n"); printf("Change USE_FMT in Makefile to the correct format, and recompile\n"); exit (1); } #endif #ifdef QCIF if (source_format != SF_QCIF) { printf("This version was compiled for QCIF format (176x144)\n"); printf("Change USE_FMT in Makefile to the correct format, and recompile\n"); printf("sourec_format=%d\n", source_format); /* exit (1); */ } #endif #ifdef CIF if (source_format != SF_CIF) { printf("This version was compiled for CIF format (352x288)\n"); printf("Change USE_FMT in Makefile to the correct format, and recompile\n"); exit(1); } #endif #ifdef CIF4 if (source_format != SF_4CIF) { printf("This version was compiled for 4CIF format (704x576)\n"); printf("Change USE_FMT in Makefile to the correct format, and recompile\n"); exit(1); } #endif #ifdef CIF16 if (source_format != SF_16CIF) { printf("This version was compiled for 16CIF format (1408x1152)\n"); printf("Change USE_FMT in Makefile to the correct format, and recompile\n"); exit(1); } #endif mb_width = horizontal_size/16; mb_height = vertical_size/16; coded_picture_width = 16*mb_width; coded_picture_height = 16*mb_height; chrom_width = coded_picture_width>>1; chrom_height = coded_picture_height>>1; blk_cnt = 6; for (cc=0; cc<3; cc++) { if (cc==0) size = coded_picture_width*coded_picture_height; else size = chrom_width*chrom_height; if (!(refframe[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); if (!(oldrefframe[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); if (!(bframe[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); } for (cc=0; cc<3; cc++) { if (cc==0) { size = (coded_picture_width+32)*(coded_picture_height+32); if (!(edgeframeorig[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); edgeframe[cc] = edgeframeorig[cc] + (coded_picture_width+32) * 16 + 16; } else { size = (chrom_width+16)*(chrom_height+16); if (!(edgeframeorig[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); edgeframe[cc] = edgeframeorig[cc] + (chrom_width+16) * 8 + 8; } } if (expand) { for (cc=0; cc<3; cc++) { if (cc==0) size = coded_picture_width*coded_picture_height*4; else size = chrom_width*chrom_height*4; if (!(exnewframe[cc] = (unsigned char *)malloc(size))) error("malloc failed\n"); } } /* Clear output file for concatenated storing */ if (outtype == T_YUV_CONC) { if ((cleared = fopen(outputname,"wb")) == NULL) error("couldn't clear outputfile\n"); else fclose(cleared); } /* IDCT */ if (refidct) init_idctref(); else init_idct(); #ifdef DISPLAY if (outtype==T_X11) { init_display(""); init_dither(); } #endif } void error(text) char *text; { fprintf(stderr,text); exit(1); } /* trace output */ void printbits(code,bits,len) int code,bits,len; { int i; for (i=0; i>(bits-1-i))&1); } /* option processing */ static void options(argcp,argvp) int *argcp; char **argvp[]; { while (*argcp>1 && (*argvp)[1][0]=='-') { while ((*argvp)[1][1]) { switch (toupper((*argvp)[1][1])) { #ifdef USE_TIME case 'F': framerate = getval(*argvp); break; #endif case 'V': verbose = getval(*argvp); break; case 'O': outtype = getval(*argvp); break; case 'R': refidct = 1; break; case 'L': loopflag = 1; break; case 'X': expand = 1; break; case 'T': trace = 1; break; case 'Q': quiet = 1; break; default: fprintf(stderr,"undefined option -%c ignored\n",(*argvp)[1][1]); } (*argvp)[1]++; } (*argvp)++; (*argcp)--; } if (outtype != T_X11) { loopflag = 0; /* No looping for output to file */ #ifdef USE_TIME framerate = 0; /* No delay necessary when output to file */ #endif } #ifdef DISPLAY if (outtype==T_X11) { (*argcp)++; /* fake outfile parameter */ } #endif if (*argcp!=3 && *argcp!=4) { printf("\n%s\n%s\n",version,author); printf("Usage: tmndecode {options} bitstream {outputfilename%%d}\n\ Options: -vn verbose output (n: level)\n\ -on output format \n\ (0:YUV, 1:SIF, 2:TGA, 3:PPM, 4:X11, 5:YUV concatenated)\n\ You have to choose one output format!\n\ -q disable warnings to stderr\n\ -r use double precision reference IDCT\n\ -t enable low level tracing\n"); #ifdef DISPLAY printf("\ -x interpolate pictures to double size before display\n"); #endif #ifdef USE_TIME printf("\ -fn frame rate (default = as fast as possible)\n"); printf("\ -l loop sequence\n"); #endif exit(0); } } static int getval(argv) char *argv[]; { int val; if (sscanf(argv[1]+2,"%d",&val)!=1) return 0; while (isdigit(argv[1][2])) argv[1]++; return val; } #ifdef USE_TIME void doframerate() { struct timeval tfdiff; /* Compute desired frame rate */ if (framerate <= 0) return; 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); } #endif