/* mpeg2enc.c, main() and parameter file reading */ /* 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. * */ #define MAX(a,b) ( (a)>(b) ? (a) : (b) ) #include #include #include #include #include #include #include typedef void (*sighandler_t)(int); #define GLOBAL_ /* used by global.h */ #include "config.h" #include "global.h" #ifndef DONT_USE_AVI #include "aviplugin.h" #endif #ifndef DONT_USE_NUV #include "rtjpeg_plugin.h" extern double rtjpeg_pel_ratio(); //FIXME #endif /* private prototypes */ static void init _ANSI_ARGS_((void)); static void readcmdline _ANSI_ARGS_((int argc, char *argv[])); #ifndef VIDEO_EXPORT_ONLY static void readquantmat _ANSI_ARGS_((void)); #else #define printf(x...) (fprintf(stderr,x)) #endif static pid_t dec_pid; static void sighandler(int i) { int status; if (i == SIGCHLD) { signal(SIGCHLD, SIG_DFL); // ignore fails on linux? } if (outfile) { fclose(outfile); } kill(dec_pid, 2); usleep(30000); waitpid(dec_pid, &status, 0); // we don't want to have zombies if (!status) kill(dec_pid, 9); fprintf(stderr, "\n"); // preserve status line exit(0); } int main(argc,argv) int argc; char *argv[]; { #if defined(DYNAMIC_LOADING) if (scan_codecs()) error("scanning codec dir"); #endif videoformat=0; frameratecode=0; reallyanamorphic=-1; aspectratio_out=0.0; /* Read command line */ readcmdline(argc, argv); #ifndef VIDEO_EXPORT_ONLY /* read quantization matrices */ readquantmat(); #endif if(!strlen(out_path)) { fprintf(stderr, "No output file given.\n"); } /* open output file */ #ifndef VIDEO_EXPORT_ONLY if(!(outfile = fopen(out_path, "wb"))) { sprintf(errortext,"Couldn't create output file %s", out_path); error(errortext); } #endif init(); #ifndef VIDEO_EXPORT_ONLY printf("Frame Completion Current bitrate Predicted file size\n"); putseq(); stop_slice_engines(); stop_motion_engines(); stop_transform_engines(); stop_itransform_engines(); #else #define STREAMHEADER "" #define PICHEADER "FRAME\n" { int f=0, i, stat; long long n=0; double frameratemin=1000.0,diff; unsigned char **frame; char str[255]; double framerates[]= {0.0, 24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0} ; char *frame_rate_definitions[] = { "illegal", "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)", "24.0 (NATIVE FILM)", "25.0 (PAL/SECAM VIDEO / converted FILM)", "30000.0/1001.0 (NTSC VIDEO)", "30.0", "50.0 (PAL FIELD RATE)", "60000.0/1001.0 (NTSC FIELD RATE)", "60.0" }; int frame_rate_definitions_int_1[] = { 0, 24000, 24, 25, 30000, 30, 50, 60000, 60 }; int frame_rate_definitions_int_2[] = { 0, 1001, 1, 1, 1001, 1, 1, 1001, 1 }; int fo,fokelz[2]; int end_frame; signal(SIGINT, sighandler); // install sighandler signal(SIGCHLD, sighandler); // install sighandler #define num_frame_rates (sizeof(framerates)/sizeof(double)) /* write to stdout */ if (!strlen(out_path)) { #ifndef DYNAMIC_LOADING fprintf(stderr,"warning: unfortunately libavifile currently produces too much debugging\noutput to decode to stdout, it is recommended to specify a pipe using |\n --- continuing anyways\n"); outfile = fdopen(1,"w"); #else outfile = fdopen(real_stdout,"w"); #endif } else if (out_path[0] == '|') { if (pipe(fokelz)) { perror("pipe"); exit(1); } if ((dec_pid=fork()) == 0) { char *s=&out_path[1]; close(0); close(fokelz[1]); dup2(fokelz[0],0); exit(system(s)); } else if (dec_pid < 0) { perror("fork"); exit(1); } close(fokelz[0]); outfile=fdopen(fokelz[1],"w"); } else outfile=fopen(out_path,"w"); frames_scaled = nframes; for (i=0; i num_encode)) nframes=num_encode; f=start_frame; end_frame=start_frame+nframes; while(frames_scaled != 0 && f>1 : mb_height; /* for field pictures */ width = ((xout?xout:horizontal_size)+1)&0xffe; /* must be even */ height = ((yout?yout:vertical_size)+1)&0xffe; if (!cutwidth && !xout && (width != xin || height != yin)) { cutwidth=xin; cutheight=yin; xout=width; yout=height; } if (videoformat) { if (xout) { fprintf(stderr,"WARNING! -V format overrides manual geometry settings\n"); } xout=videoformats[videoformat].hsize; if (frameratecode==1||frameratecode==4||frameratecode==7) { yout=(videoformats[videoformat].vsize_pal*5)/6; } else { yout=videoformats[videoformat].vsize_pal; } width=xout; height=yout; if (aspectratio == 0.0) aspectratio == 1.0; /* this is getting really confusing * now, input pel ratio should be obtained ok from avi and nuv * otherwise it's just 1.0 (ok for pal only :-() * * the output pel ratio on the other hand is dependant upon * - input pel ratio * - input size (offx/offy, cutwidth/cutheight in fact) * - output size * * so if we have a constant output size (like the standard sizes here) * and want to set a specific pel ratio (anamorphic, 1:1, ntsc ...), * we have to vary the input size (usually y size, hands up anyone * who wants letterbox bars to the right and left ...) * * -- aoe */ #if 0 if (((videoformats[videoformat].supports_anamorphic && (reallyanamorphic == -1)) || (reallyanamorphic == 1))) { /* kludge, should have a geom_set variable */ /* try anamorphic 2.21:1 first */ aspectratio_out=(frame_rate == 25.0 ? (270.0/288.0*4/3/2.21) : (270.0/240.0*4/3/2.21)); /* if vertical letterbox bars would result, don't do 2.21:1 ... */ if ((float)xout/(float)yout/aspectratio_out > (float)(cutwidth?cutwidth:xin)/(float)(cutheight?cutheight:yin)/aspectratio) { aspectratio_out=(frame_rate == 25.0 ? (270.0/288.0*4/3/16.0*9.0) : (270.0/240.0*4/3/16.0*9.0)); fprintf(stderr,"4:3 "); /* if vertical letterbox bars would result, don't do 16:9 ... */ if ((float)xout/(float)yout/aspectratio_out > (float)(cutwidth?cutwidth:xin)/(float)(cutheight?cutheight:yin)/aspectratio) { aspectratio_out=(frame_rate == 25.0 ? 1/0.9375 : 1/1.125); fprintf(stderr,"4:3 "); } else fprintf(stderr,"16:9 "); } else fprintf(stderr,"2.21:1 "); /* use conventional 4:3 pel ratio if !anamorphic and !aspectratio_out */ } else if (aspectratio_out == 0.0) { aspectratio_out=(frame_rate == 25.0 ? 1/0.9375 : 1/1.125); fprintf(stderr,"4:3 "); } fprintf(stderr,"predefined format %s: x=%i, y=%i\n",videoformats[videoformat].name,xout,yout); #endif }; /* either just calculated from formatcode or entered via -a */ #if 0 fprintf(stderr,"aspectratios: in %f, out %f\n",aspectratio,aspectratio_out); if (aspectratio_out > 0.0001) { /* "normal" horizontal letterbox bars */ if ((float)xout/(float)yout/(float)aspectratio_out > (float)xin/(float)yin/aspectratio) { cutheight=(float)xin*(float)yin/(float)xin*((float)xout/(float)yout*aspectratio)/aspectratio_out; cutwidth=xin; offy=-(yin-cutheight)/2; /* quite unusual vertical letterbox bars ... */ } else if ((float)xout/(float)yout/aspectratio_out < (float)xin/(float)yin/aspectratio) { cutheight=yin; cutwidth=(float)yin*(float)xin/(float)yin*((float)yout/(float)xout*aspectratio)/aspectratio_out; offx=-(xin-cutwidth)/2; fprintf(stderr,"WARNING! aspect ratios %2.2f->%2.2f necessitate VERTICAL letterbox bars!\n",aspectratio,aspectratio_out); } } #endif fprintf(stderr,"\n\n>> (%ix%i) of %ix%i -> (%ix%i) <<\n\n",cutwidth, cutheight, xin, yin, xout, yout); chrom_width = (chroma_format==CHROMA444) ? width : width>>1; chrom_height = (chroma_format!=CHROMA420) ? height : height>>1; height2 = fieldpic ? height>>1 : height; width2 = fieldpic ? width<<1 : width; chrom_width2 = fieldpic ? chrom_width<<1 : chrom_width; block_count = block_count_tab[chroma_format-1]; lum_buffer_size = (width*height) + sizeof(uint8_t) *(width/2)*(height/2) + sizeof(uint8_t) *(width/4)*(height/4+1); chrom_buffer_size = chrom_width*chrom_height; fsubsample_offset = (width)*(height) * sizeof(uint8_t); qsubsample_offset = fsubsample_offset + (width/2)*(height/2)*sizeof(uint8_t); rowsums_offset = 0; colsums_offset = 0; mb_per_pict = mb_width*mb_height2; /* 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); #ifndef VIDEO_EXPORT_ONLY /* Allocate the frame buffer */ frame_buffers = (uint8_t ***) bufalloc(2*READ_LOOK_AHEAD*sizeof(uint8_t**)); for(n=0;n<2*READ_LOOK_AHEAD;n++) { frame_buffers[n] = (uint8_t **) bufalloc(3*sizeof(uint8_t*)); for (i=0; i<3; i++) { frame_buffers[n][i] = bufalloc( (i==0) ? lum_buffer_size : chrom_buffer_size ); } } /* TODO: The ref and aux frame buffers are no redundant! */ for( i = 0 ; i<3; i++) { int size = (i==0) ? lum_buffer_size : chrom_buffer_size; newrefframe[i] = bufalloc(size); oldrefframe[i] = bufalloc(size); auxframe[i] = bufalloc(size); predframe[i] = bufalloc(size); } cur_picture.qblocks = (int16_t (*)[64])bufalloc(mb_per_pict*block_count*sizeof(int16_t [64])); /* Initialise current transformed picture data tables These will soon become a buffer for transformed picture data to allow look-ahead for bit allocation etc. */ cur_picture.mbinfo = ( struct mbinfo *)bufalloc(mb_per_pict*sizeof(struct mbinfo)); cur_picture.blocks = (int16_t (*)[64])bufalloc(mb_per_pict * block_count * sizeof(int16_t [64])); #endif /* VIDEO_EXPORT_ONLY */ /* open statistics output file */ if(statname[0]=='-') statfile = stdout; else if(!(statfile = fopen(statname,"w"))) { sprintf(errortext,"Couldn't create statistics output file %s",statname); error(errortext); } ratectl = malloc(processors * sizeof(ratectl_t*)); for(i = 0; i < processors; i++) ratectl[i] = calloc(1, sizeof(ratectl_t)); #ifndef VIDEO_EXPORT_ONLY /* Start parallel threads */ start_motion_engines(); start_transform_engines(); start_itransform_engines(); start_slice_engines(); #endif } void error(text) char *text; { fprintf(stderr,text); putc('\n',stderr); exit(1); } #define STRINGLEN 254 #ifndef VIDEO_EXPORT_ONLY int calculate_smp() { /* Get processor count */ int result = 1; FILE *proc; if(proc = fopen("/proc/cpuinfo", "r")) { char string[1024]; while(!feof(proc)) { fgets(string, 1024, proc); if(!strncasecmp(string, "processor", 9)) { char *ptr = strchr(string, ':'); if(ptr) { ptr++; result = atol(ptr) + 1; } } else if(!strncasecmp(string, "cpus detected", 13)) { char *ptr = strchr(string, ':'); if(ptr) { ptr++; result = atol(ptr); } } } fclose(proc); } return result; } #endif /* VIDEO_EXPORT_ONLY */ static void readcmdline(int argc, char *argv[]) { int i,j; int h,m,s,f; FILE *fd; char line[256]; // Master frame rate table must match decoder static double ratetab[]= {24000.0/1001.0, // Official rates 24.0, 25.0, 30000.0/1001.0, 30.0, 50.0, 60000.0/1001.0, 60.0, 1, // Unofficial economy rates 5, 10, 12, 15, 0, 0}; // VBV buffer size limits int vbvlim[4] = { 597, 448, 112, 29 }; long total_frame_rates = (sizeof(ratetab) / sizeof(double)); FILE *proc; int param_searchrad = 16; use_hires_quant = 0; use_denoise_quant = 0; quiet = 1; bit_rate = 5000000; /* default bit_rate (bits/s) */ #ifndef VIDEO_EXPORT_ONLY prog_seq = 0; /* progressive_sequence is faster */ #else prog_seq = 1; /* progressive_sequence is faster */ #endif mpeg1 = 0; /* ISO/IEC 11172-2 stream */ fixed_mquant = 0; /* vary the quantization */ quant_floor = 0; act_boost = 3.0; N = 15; /* N (# of frames in GOP) */ M = 3; /* M (I/P frame distance) */ #ifndef VIDEO_EXPORT_ONLY processors = calculate_smp(); #endif frame_rate = -1; num_encode = 0; timestamptype = 0; y4m_version = 0; xout=yout=0; sprintf(tplorg, ""); sprintf(out_path, ""); #define INTTOYES(x) ((x) ? "Yes" : "No") if(argc < 2) { fprintf(stderr, #ifndef VIDEO_EXPORT_ONLY "mpeg2encode V1.5" #else "exportvideo 1.0" #endif " (with avi/nuv-patch " VERSION "), 2001/04/04\n" "(C) 1996, MPEG Software Simulation Group\n" #ifndef VIDEO_EXPORT_ONLY "(C) 2000 Adam Williams\n" " patched by " #else "(C) 2001 " #endif "Roman and Alex (+deinterlace" #ifndef DYNAMIC_LOADING #ifndef DONT_USE_AVI " +avi" #endif #ifndef DONT_USE_NUV " +nuv" #endif #else " +modules" #endif ")\n" #ifndef VIDEO_EXPORT_ONLY "Usage: encode [options] [{outfile.raw|\"|encodingprogram\"}]\n\n" " -1 generate an MPEG-1 stream instead of MPEG-2 (%s)\n" " -b bitrate fix the bitrate, vary the quantization (%d)\n" " -d Denoise (%s)\n" " -h High resolution quantization table (%s)\n" " -m frames set number of frames between P frames (%d)\n" " -n frames set number of frames between I frames (%d)\n" " -p encode progressive frames (%s)\n" " -q quantization fix the quantization, vary the bitrate\n" " -u Use only 1 processor\n" #else "Usage: exportvideo [options] [{outfile.raw|\"|encodingprogram\"}]\n\n" #endif " -D force deinterlace on (1), off (0), auto (-1, default)\n" " -S frame# set start frame\n" " -N frames set number of frames to encode\n" " -G XoutxYout scale to this output geometry \n" " -g WIDTHxHEIGHT+XOFFxYOFF scale from this input window\n" " (negative numbers produce black borders\n" " - try to use multiples of 16)\n" /* " -V formatcode (EXPERIMENTAL) vcd 2.0: 1, svcd: 2, dvd: 3\n" " -A -1|0|1 (EXPERIMENTAL) produce anamorphic video\n" " -a aspectratio (EXP) set output pel ratio (dep upon in ar!)\n" */ #ifdef VIDEO_EXPORT_ONLY " -Y 0|1|2 YUV4MPEG format version: 0 (old, default), 1 (new)\n" " -a aspectratio used with -Y 1 only\n" #endif " -T timestamptype set timestamptype (1=time,2=framenum)\n\n" #ifndef VIDEO_EXPORT_ONLY "Default settings:\n" " fixed 5000000 bits/sec\n" " interlaced\n" " MPEG-2\n" " 15 frames between I frames 2 frames between P frames\n\n" "For the recommended encoding parameters see docs/index.html.\n", mpeg1 ? "MPEG-1" : "MPEG-2", (int)bit_rate, INTTOYES(use_denoise_quant), INTTOYES(use_hires_quant), M - 1, N, INTTOYES(prog_seq) #endif ); exit(1); } for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-1")) { mpeg1 = 1; } else if(!strcmp(argv[i], "-a")) { i++; if(i < argc) { aspectratio_out = atof(argv[i]); } else { fprintf(stderr, "-a requires an aspect ratio\n"); exit(1); } } else if(!strcmp(argv[i], "-b")) { i++; if(i < argc) { bit_rate = atol(argv[i]); } else { fprintf(stderr, "-b requires a bitrate\n"); exit(1); } } else if(!strcmp(argv[i], "-d")) { use_denoise_quant = 1; } else if(!strcmp(argv[i], "-f")) { i++; if(i < argc) { frame_rate = atof(argv[i]); } else { fprintf(stderr, "-f requires a frame rate\n"); exit(1); } } else if(!strcmp(argv[i], "-g")) { i++; if(i < argc) { sscanf(argv[i],"%ix%i+%i+%i",&cutwidth, &cutheight, &offx, &offy); } else { fprintf(stderr, "-g requires a scaling geometry of a WIDTHxHEIGHT+XINxYIN\n"); exit(1); } } else if(!strcmp(argv[i], "-h")) { use_hires_quant = 1; } else if(!strcmp(argv[i], "-m")) { i++; if(i < argc) { M = atol(argv[i]) + 1; } else { fprintf(stderr, "-m requires a frame count\n"); exit(1); } } else if(!strcmp(argv[i], "-n")) { i++; if(i < argc) { N = atol(argv[i]); } else { fprintf(stderr, "-n requires a frame count\n"); exit(1); } } else if(!strcmp(argv[i], "-A")) { i++; if(i < argc) { reallyanamorphic=atoi(argv[i]); } else { fprintf(stderr, "-A anamorphic: (1 or 0, -1 for auto)\n"); exit(1); } } else if(!strcmp(argv[i], "-D")) { i++; if(i < argc) { deinterlace=atoi(argv[i]); } else { fprintf(stderr, "-D requires a deinterlace force argument (1 or 0, -1 for auto)\n"); exit(1); } } else if(!strcmp(argv[i], "-G")) { i++; if(i < argc) { sscanf(argv[i],"%ix%i",&xout, &yout); } else { fprintf(stderr, "-G requires an output geometry of WIDTHxHEIGHT\n"); exit(1); } } else if(!strcmp(argv[i], "-S")) { i++; if(i < argc) { start_frame = atoi(argv[i]); } else { fprintf(stderr, "-S requires a start frame\n"); exit(1); } } else if(!strcmp(argv[i], "-N")) { i++; if(i < argc) { num_encode = atoi(argv[i]); } else { fprintf(stderr, "-N requires a frame count\n"); exit(1); } } else if(!strcmp(argv[i], "-Y")) { i++; if(i < argc) { y4m_version = atoi(argv[i]); } else { fprintf(stderr, "-Y is the YUV4MPEG version switch: currently old format (0) is the default, 1 is the new format\n"); exit(1); } } else if(!strcmp(argv[i], "-T")) { i++; if(i < argc) { timestamptype = atoi(argv[i]); } else { fprintf(stderr, "-T requires a timestamp type\n"); exit(1); } } else if(!strcmp(argv[i], "-V")) { i++; if(i < argc) { int numf=sizeof(videoformats)/sizeof(videoformats[0])-1; for (j=0;j= numf)) { fprintf(stderr, "-V only defined in range 0 .. %i\n", numf-1); for (j=0;j= 0 && out_path[i] != '.'; i--) ; if(i < 0) i = strlen(out_path); if(mpeg1) sprintf(&out_path[i], ".m1v"); else sprintf(&out_path[i], ".m2v"); } #endif /* Get info from input file */ mpeg_file = 0; qt_file = 0; if(mpeg3_check_sig(tplorg)) { mpeg_file = mpeg3_open(tplorg); inputtype = T_MPEG; } else if(quicktime_check_sig(tplorg)) { qt_file = quicktime_open(tplorg, 1, 0); inputtype = T_QUICKTIME; } #ifndef DYNAMIC_LOADING #ifndef DONT_USE_AVI if(avi_check_sig(tplorg)) { avi_open(tplorg); inputtype = T_AVI; } #endif #ifndef DONT_USE_NUV if(rtjpeg_check_sig(tplorg)) { rtjpeg_open(tplorg); inputtype = T_RTJPEG; } #endif #else /* !DYNAMIC */ video_in_module=0; for (i=0; i<100; i++) { if (codecs[i].video_in) { if ((codecs[i].check_file)(tplorg)) { fprintf(stderr,"found codec %i (video %i) for %s\n",i,(codecs[i].video_in)(),tplorg); video_in_module=i; (codecs[video_in_module].open_file)(tplorg); inputtype=T_DYNAMIC; break; } } } #endif /* !DYNAMIC */ if(!qt_file && !mpeg_file && inputtype!=T_AVI && inputtype != T_DYNAMIC && inputtype != T_RTJPEG #ifndef DYNAMIC_LOADING #ifndef DONT_USE_NUV && !rtjpeg_file #endif #endif ) { fprintf(stderr, "File format not recognized.\n"); exit(1); } if(qt_file) { if(!quicktime_video_tracks(qt_file)) { fprintf(stderr, "No video tracks in file.\n"); exit(1); } if(!quicktime_supported_video(qt_file, 0)) { fprintf(stderr, "Unsupported video codec.\n"); exit(1); } } /************************************************************************ * BEGIN PARAMETER FILE ************************************************************************/ /* To eliminate the user hassle we replaced the parameter file with hard coded constants. */ strcpy(tplref, "-"); /* name of intra quant matrix file ("-": default matrix) */ strcpy(iqname, "-"); /* name of intra quant matrix file ("-": default matrix) */ strcpy(niqname, "-"); /* name of non intra quant matrix file ("-": default matrix) */ strcpy(statname, "/dev/null"); /* name of statistics file ("-": stdout ) */ if(qt_file) { nframes = quicktime_video_length(qt_file, 0); /* number of frames */ horizontal_size = quicktime_video_width(qt_file, 0); vertical_size = quicktime_video_height(qt_file, 0); } if(mpeg_file) { nframes = 0x7fffffff; /* Use percentage instead */ horizontal_size = mpeg3_video_width(mpeg_file, 0); vertical_size = mpeg3_video_height(mpeg_file, 0); } #ifndef DYNAMIC_LOADING #ifndef DONT_USE_AVI if (inputtype==T_AVI) { nframes = 0x7fffffff; horizontal_size = avi_video_width(); vertical_size = avi_video_height(); aspectratio = avi_pel_ratio(); } #endif #ifndef DONT_USE_NUV if(rtjpeg_file) { nframes = 0x7fffffff; /* Use percentage instead */ horizontal_size = rtjpeg_get_video_width(mpeg_file, 0); vertical_size = rtjpeg_get_video_height(mpeg_file, 0); aspectratio = rtjpeg_pel_ratio(); } #endif #else if (inputtype==T_DYNAMIC) { nframes = 0x7fffffff; fprintf(stderr,"checking pars\n"); horizontal_size = (int)(codecs[video_in_module].get_video_width)(); /*get_video_width*/ fprintf(stderr,"width %i\n",horizontal_size); vertical_size = (int)(codecs[video_in_module].get_video_height)();/*get_video_height*/ fprintf(stderr,"height %i\n",vertical_size); // aspectratio = (float)(codecs[video_in_module].pel_ratio)(); // fprintf(stderr,"ar %f\n",aspectratio); } #endif xin=horizontal_size; yin=vertical_size; if (xout && yout) { xout=(xout+15)&0xff0; yout=(yout+15)&0xff0; horizontal_size=width=xout; vertical_size=height=yout; if (!cutwidth) { cutwidth=xin; cutheight=yin; offx=0; offy=0; } fprintf(stderr,"outsize is %ix%i\n",xout,yout); } else if (cutwidth && (!xout)) { xout=cutwidth; yout=cutheight; xout=(xout+15)&0xff0; yout=(yout+15)&0xff0; horizontal_size=width=xout; vertical_size=height=yout; fprintf(stderr,"outsize set to %ix%i\n",xout,yout); } else if ((xin != horizontal_size) || (yin != vertical_size)) { xout=horizontal_size; yout=vertical_size; cutwidth=xin; cutheight=yin; fprintf(stderr,"outsize set to %ix%i\n",xout,yout); }; fprintf(stderr,"outsize is %ix%i\n",xout,yout); if (num_encode && (nframes > num_encode)) nframes=num_encode; if (start_frame && !num_encode) num_encode=nframes; frame0 = 0; /* number of first frame */ h = m = s = f = 0; /* timecode of first frame */ fieldpic = 0; /* 0: progressive, 1: bottom first, 2: top first, 3 = progressive seq, field MC and DCT in picture */ if (aspectratio == 0) aspectratio = 1.0; /* aspect_ratio_information 1=square pel, 2=4:3, 3=16:9, 4=2.11:1 */ low_delay = 0; /* low_delay */ constrparms = 0; /* constrained_parameters_flag */ profile = 4; /* Profile ID: Simple = 5, Main = 4, SNR = 3, Spatial = 2, High = 1 */ level = 4; /* Level ID: Low = 10, Main = 8, High 1440 = 6, High = 4 */ chroma_format = 1; /* chroma_format: 1=4:2:0, 2=4:2:2, 3=4:4:4 LibMPEG3 only does 1 */ video_format = 2; /* video_format: 0=comp., 1=PAL, 2=NTSC, 3=SECAM, 4=MAC, 5=unspec. */ color_primaries = 5; /* color_primaries */ dctsatlim = mpeg1 ? 255 : 2047; dctsatlim = 255; transfer_characteristics = 5; /* transfer_characteristics */ matrix_coefficients = 4; /* matrix_coefficients (not used) */ display_horizontal_size = horizontal_size; display_vertical_size = vertical_size; cur_picture.dc_prec = 0; /* intra_dc_precision (0: 8 bit, 1: 9 bit, 2: 10 bit, 3: 11 bit */ cur_picture.topfirst = 1; /* top_field_first */ frame_pred_dct_tab[0] = mpeg1 ? 1 : 0; /* frame_pred_frame_dct (I P B) */ frame_pred_dct_tab[1] = mpeg1 ? 1 : 0; /* frame_pred_frame_dct (I P B) */ frame_pred_dct_tab[2] = mpeg1 ? 1 : 0; /* frame_pred_frame_dct (I P B) */ conceal_tab[0] = 0; /* concealment_motion_vectors (I P B) */ conceal_tab[1] = 0; /* concealment_motion_vectors (I P B) */ conceal_tab[2] = 0; /* concealment_motion_vectors (I P B) */ qscale_tab[0] = mpeg1 ? 0 : 1; /* q_scale_type (I P B) */ qscale_tab[1] = mpeg1 ? 0 : 1; /* q_scale_type (I P B) */ qscale_tab[2] = mpeg1 ? 0 : 1; /* q_scale_type (I P B) */ intravlc_tab[0] = 0; /* intra_vlc_format (I P B)*/ intravlc_tab[1] = 0; /* intra_vlc_format (I P B)*/ intravlc_tab[2] = 0; /* intra_vlc_format (I P B)*/ altscan_tab[0] = 0; /* alternate_scan (I P B) */ altscan_tab[1] = 0; /* alternate_scan (I P B) */ altscan_tab[2] = 0; /* alternate_scan (I P B) */ opt_dc_prec = 0; /* 8 bits */ opt_topfirst = (fieldpic == 2); opt_repeatfirst = 0; opt_prog_frame = prog_seq; cur_picture.repeatfirst = 0; /* repeat_first_field */ cur_picture.prog_frame = prog_seq; /* progressive_frame */ /* P: forw_hor_f_code forw_vert_f_code search_width/height */ motion_data = (struct motion_data *)malloc(3 * sizeof(struct motion_data)); video_buffer_size = 46 * 1024 * 8; /************************************************************************ * END PARAMETER FILE ************************************************************************/ if(mpeg1) { opt_prog_frame = 1; cur_picture.prog_frame = 1; prog_seq = 1; } if(qt_file) input_frame_rate = quicktime_frame_rate(qt_file, 0); if(mpeg_file) input_frame_rate = mpeg3_frame_rate(mpeg_file, 0); #ifndef DYNAMIC_LOADING #ifndef DONT_USE_AVI if(inputtype == T_AVI) input_frame_rate = avi_frame_rate(mpeg_file, 0); #endif #ifndef DONT_USE_NUV if(rtjpeg_file) input_frame_rate = rtjpeg_get_video_frame_rate(); #endif #else if(inputtype == T_DYNAMIC) input_frame_rate = (codecs[video_in_module].get_video_framerate)();/*get_video_framerate*/ #endif if(frame_rate < 0) { frame_rate = input_frame_rate; } //processors = 1; //nframes = 16; // Show status printf("Encoding: %s frames %ld\n", out_path, nframes); if(fixed_mquant == 0) printf(" bitrate %.0f\n", bit_rate); else printf(" quantization %d\n", fixed_mquant); printf(" %d frames between I frames %d frames between P frames\n", N, M - 1); printf(" %s\n", (prog_seq ? "progressive" : "interlaced")); printf(" %s\n", (mpeg1 ? "MPEG-1" : "MPEG-2")); printf(" %d processors\n", processors); printf(" %.02f frames per second\n", frame_rate); printf(" Denoise %s\n", INTTOYES(use_denoise_quant)); printf(" Hires quantization %s\n", INTTOYES(use_hires_quant)); if(mpeg_file) { fprintf(stderr, "(MPEG to MPEG transcoding for official use only.)\n"); mpeg3_set_mmx(mpeg_file, 0); } { int radius_x = ((param_searchrad+4)/8)*8; int radius_y = ((param_searchrad*vertical_size/horizontal_size+4)/8)*8; int c; /* TODO: These f-codes should really be adjusted for each picture type... */ c=5; if( radius_x*M < 64) c = 4; if( radius_x*M < 32) c = 3; if( radius_x*M < 16) c = 2; if( radius_x*M < 8) c = 1; if (!motion_data) error("malloc failed\n"); for (i=0; i vbvlim[(level - 4) >> 1]) vbv_buffer_size = vbvlim[(level - 4) >> 1]; /* Set up frame buffers */ frame_buffer = malloc(horizontal_size * vertical_size * 3 + 4); row_pointers = malloc(sizeof(unsigned char*) * vertical_size); for(i = 0; i < vertical_size; i++) row_pointers[i] = &frame_buffer[horizontal_size * 3 * i]; // Get frame rate code from input frame rate for(i = 0; i < total_frame_rates; i++) { if(fabs(frame_rate - ratetab[i]) < 0.001) frame_rate_code = i + 1; } /* make flags boolean (x!=0 -> x=1) */ mpeg1 = !!mpeg1; fieldpic = !!fieldpic; low_delay = !!low_delay; constrparms = !!constrparms; prog_seq = !!prog_seq; cur_picture.topfirst = !!cur_picture.topfirst; for (i = 0; i < 3; i++) { frame_pred_dct_tab[i] = !!frame_pred_dct_tab[i]; conceal_tab[i] = !!conceal_tab[i]; qscale_tab[i] = !!qscale_tab[i]; intravlc_tab[i] = !!intravlc_tab[i]; altscan_tab[i] = !!altscan_tab[i]; } cur_picture.repeatfirst = !!cur_picture.repeatfirst; cur_picture.prog_frame = !!cur_picture.prog_frame; #ifndef VIDEO_EXPORT_ONLY /* make sure MPEG specific parameters are valid */ range_checks(); #endif /* timecode -> frame number */ tc0 = h; tc0 = 60*tc0 + m; tc0 = 60*tc0 + s; tc0 = (int)(frame_rate+0.5)*tc0 + f; qt_output = 0; /* * qt_output = quicktime_open("/mov/test.mov", 0, 1); * quicktime_set_video(qt_output, * 1, * horizontal_size, * vertical_size, * frame_rate, * QUICKTIME_YUV420); */ #ifndef VIDEO_EXPORT_ONLY if (!mpeg1) { profile_and_level_checks(); } else { /* MPEG-1 */ if (constrparms) { if (horizontal_size>768 || vertical_size>576 || ((horizontal_size+15)/16)*((vertical_size+15) / 16) > 396 || ((horizontal_size+15)/16)*((vertical_size+15) / 16)*frame_rate>396*25.0 || frame_rate>30.0) { if (!quiet) fprintf(stderr,"*** Warning: setting constrained_parameters_flag = 0\n"); constrparms = 0; } } } #endif /* relational checks */ if (mpeg1) { if (!prog_seq) { prog_seq = 1; } if (chroma_format!=CHROMA420) { chroma_format = CHROMA420; } if (cur_picture.dc_prec!=0) { cur_picture.dc_prec = 0; } for (i=0; i<3; i++) if (qscale_tab[i]) { qscale_tab[i] = 0; } for (i=0; i<3; i++) if (intravlc_tab[i]) { intravlc_tab[i] = 0; } for (i=0; i<3; i++) if (altscan_tab[i]) { altscan_tab[i] = 0; } } if (!mpeg1 && constrparms) { constrparms = 0; } if (prog_seq && !cur_picture.prog_frame) { cur_picture.prog_frame = 1; } if (cur_picture.prog_frame && fieldpic) { fieldpic = 0; } if (!cur_picture.prog_frame && cur_picture.repeatfirst) { cur_picture.repeatfirst = 0; } if (cur_picture.prog_frame) { for (i=0; i<3; i++) if (!frame_pred_dct_tab[i]) { frame_pred_dct_tab[i] = 1; } } if (prog_seq && !cur_picture.repeatfirst && cur_picture.topfirst) { if (!quiet) fprintf(stderr,"Warning: setting top_field_first = 0\n"); cur_picture.topfirst = 0; } /* search windows */ for (i=0; i (4< (4< (4< (4< 4 ) qboost += (256*(x-4)/3); if( y > 4 ) qboost += (256*(y-4)/3); return (orgquant * qboost + 512)/ 1024; } static void readquantmat() { int i,v,q; load_iquant = 0; load_niquant = 0; if (iqname[0]=='-') { if(use_hires_quant) { load_iquant |= 1; for (i=0; i<64; i++) { intra_q[i] = hires_intra_quantizer_matrix[i]; } } else { load_iquant = use_denoise_quant; for (i=0; i<64; i++) { v = quant_hfnoise_filt(default_intra_quantizer_matrix[i], i); if (v<1 || v>255) error("value in intra quant matrix invalid (after noise filt adjust)"); intra_q[i] = v; } } } /* TODO: Inv Quant matrix initialisation should check if the fraction fits in 16 bits! */ if (niqname[0]=='-') { if(use_hires_quant) { for (i=0; i<64; i++) { inter_q[i] = hires_nonintra_quantizer_matrix[i]; } } else { /* default non-intra matrix is all 16's. For *our* default we use something more suitable for domestic analog sources... which is non-standard...*/ load_niquant |= 1; for (i=0; i<64; i++) { v = quant_hfnoise_filt(default_nonintra_quantizer_matrix[i],i); if (v<1 || v>255) error("value in non-intra quant matrix invalid (after noise filt adjust)"); inter_q[i] = v; } } } for (i=0; i<64; i++) { i_intra_q[i] = (int)(((double)IQUANT_SCALE) / ((double)intra_q[i])); i_inter_q[i] = (int)(((double)IQUANT_SCALE) / ((double)inter_q[i])); } for( q = 1; q <= 112; ++q ) { for (i=0; i<64; i++) { intra_q_tbl[q][i] = intra_q[i] * q; inter_q_tbl[q][i] = inter_q[i] * q; intra_q_tblf[q][i] = (float)intra_q_tbl[q][i]; inter_q_tblf[q][i] = (float)inter_q_tbl[q][i]; i_intra_q_tblf[q][i] = 1.0f/ ( intra_q_tblf[q][i] * 0.98); i_intra_q_tbl[q][i] = (IQUANT_SCALE/intra_q_tbl[q][i]); i_inter_q_tblf[q][i] = 1.0f/ (inter_q_tblf[q][i] * 0.98); i_inter_q_tbl[q][i] = (IQUANT_SCALE/inter_q_tbl[q][i] ); } } } #endif /* VIDEO_EXPORT_ONLY */