diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/ppm/ppmtompeg | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/ppm/ppmtompeg')
260 files changed, 39497 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/BUGS b/converter/ppm/ppmtompeg/BUGS new file mode 100644 index 00000000..64269dfb --- /dev/null +++ b/converter/ppm/ppmtompeg/BUGS @@ -0,0 +1,43 @@ +Known BUGS: + +1. <fixed> + +2. rate control and specifics files interact badly + +3. using REMOTE parallel execution: + `command` to find INPUT files does not work + SPECIFICS_FILE (CDL_FILE) + USER_DATA + dont work (should send the files over the socket, but do not + +4. using any sort of parallel code: + REFERENCE_FRAME DECODED + does not work + +5. Cannot use both STDIN and CDL_FILEs (ok, since it doesnt make sense...) + +6. <fixed> + +7. Patterns of BBI... seem to cause problems for parallel encoding. + I believe the bugs are fixed for sequential, but if you hit one, let us + know! + +8. Sometimes parallel encoding results in a zero size being written into + the stream. To fix, specify SIZE of the actual size. + +8.1 (related? minor, anyway) in parallel is also writes the Quant matrix + even when it is the default one + +9. It is unclear (to us anyway) if we should generate Y's from 0..255 or 16..224 + +10. <fixed> + +11. <fixed> + +12. reading JPEG from stdin, the encoder will sometimes stop before the end +of the stream (if the images are smaller than half the buffer size). + +13. Sometimes INPUT_CONVERT * is not good (requires "cat *"), in a parallel +case reported by a user it was needed. + +14. Parallel encoding often generates improper temporal_ref's... diff --git a/converter/ppm/ppmtompeg/CHANGES b/converter/ppm/ppmtompeg/CHANGES new file mode 100644 index 00000000..fffa7a65 --- /dev/null +++ b/converter/ppm/ppmtompeg/CHANGES @@ -0,0 +1,180 @@ +Changes chronology +------------------ +1.5b Release August 1995 + - added date to default USER_DATA string + - made prototypes happier + - renamed SPECIFICS_FILE to CDL_FILE + - fixed bit_rate param in constrained param setting (was too restrictive) + - fixed obscure P-block motion vector bug + - added a file name replication: + foo.ppm [1-10] will make 10 copies of foo.ppm + - generalized fopen calls to specify binary mode (MSDOG) + - generalized times calls into elapsed_time to handle different library routines + - fixed motion vector bug in bframes; skip block bug + - fixed minor bugs in parallel, mpeg, main, iframe, param, .... + - accepts extra whitespace at the end of lines in parameter files + - "PIXEL FULL" bug in B-frames fixed (caused ghosting) + - B-blocks "can I skip" rutine now looks at color too (more ghosting problems) + - switched from JPEG4 to JPEG5 (if they crash for you, + do a -DJPEG4 for the encoder, and get jpeg4.tar.gz off our site) + - combine server (parallel) waits longer for files to exist ( + thanks to apian@ise.fhg.de) + - killing the parallel server kills the clients!!!! (apian@ise.fhg.de) + +1.5 Release 8 May 1995 Changes since version 1.3 release (to 1.5) += BUG FIXES + - removed SetBlocksPerSlice() from GOPStoMPEG + - don't access bb after freeing + - non-integer frame rates now work for all machines + - fixed parsing of -mv_histogram + - fixed numPadding bug (file name problem) + - fixed full pixel assertation bug + - corrected ASPECT_RATIO bug (was forced to 1) + - buffer size is now set correctly + - complains when file is too small + - fixed bug with non-ranged INPUT_FILE names + - forced MB at start/end of slice in P-frame bug fixed + - Actually evaluates the constrained parameter settings + - fixed a Cr/Cb mixup in bframe.c + += NEW FEATURES + - rate control + - optional B search range different from P range + - can read images from stdin, allowing encoding on-the-fly + - Does Y files (no U or V) + - New way of specifying files `cmd`, like `ls jan-*-94` + - Can encode Abekas and Phillips style YUV formats + - gamma correction + - added -realquiet mode + - JMOVIE and JPEGv4 input format fully supported + - -float_dct uses the (slower) double precision floating point DCT + - automatically identifies itself in (sequence header) userdata + - enforced [0][0] entry of Intra Q-table to be 8 + - added Jim Boucher's resize code + - added -mse flag to print mean squared error on a per-block basis + - can specify Sequence header user data + - prints version number + - finds more skip blocks in GenBFrame + - can generate multiple sequence headers (every N GOPs) + += SPEED IMPROVEMENTS + + += MAINTENANCE + - removed mpeg_jrevdct_sparse(), since it wasn't used + - added CompileTests(); + - uses libpnmrw rather than entire pbmplus directory + - redid RCS + - reorganized [ipb]frame.c to make playing with rate controls easier + += PORTABILITY + - added #ifdef's, #ifndef's LINUX'es to ease porting + + +Changes from 1.2 to 1.3 +----------------------- += BUG FIXES + + deletes frame files when done with them in parallel version + + fixed bug in ComputeFrameTable + + completion time estimation now is closer to actual time + + modified ComputeSNR to avoid overflow of varOrig + + fixed bug that caused I/P/B times on HP's to be wrong + + fixed bug that made TwoLevel search out of the search window + + fixed bug in -quiet 0 + + fixed memory leak when using PNM files + + fixed bug: crashed when CPU time was 0 (very rare) + + fixed bug in -gop option + + fixed bug in AppendFiles() + += NEW FEATURES + + added FORCE_ENCODE_LAST_FRAME option (allows encoding of all frames) + + added PARALLEL_CHUNK_TAPER option + + added -bit_rate_info option to show bit rate per frame + + added -mv_histogram option to show motion vector histogram + + custom quantization tables allowed + + can specify frame rate, aspect ratio + += SPEED IMPROVEMENTS + + replaced most remaining binary multiplies/divides with shifts + (except those concerning negative numbers) + += MAINTENANCE + + got rid of & before array warning in block.c + + got rid of references to srandom, random in pbmplus.h + + undefine 'index' if defined as 'strchr' (since we use index as + variable name) + + modified frame type code to be more flexible + += PORTABILITY + + replaced all bzero() calls with memset() calls + + +1.2 Release 20 October 1993 + +Changes from 1.1 to 1.2 +----------------------- += BUG FIXES + + allow comments in PPM files + + first and last macroblocks in a slice may not be skipped macroblocks + + fixed YUV bug: should be able to handle dimensions which + aren't multiples of 16 + + fixed the separate I/O conversion for parallel NFS version + + no_frame_summary can now be last option + += NEW FEATURES + + using DECODED frames as reference frames in parallel + version now works + + implemented multiple I/O Servers + + FORCE_I_ALIGN added + + reorganized Server structure slightly (only I/O Servers + handle individual frame files on disk) + + add option to allow exact division of frames per processor + (PARALLEL_PERFECT) + += SPEED IMPROVEMENTS + + don't start Input server if not needed + += MAINTENANCE + + got rid of niceProcesses line in main.c + + changed write() to SafeWrite() in parallel.c + + commented stuff out after #endif's + + fixed prototype warnings (eliminated non-4-byte args) + + +1.1 Release August 1993 + +Changes from 1.0 to 1.1 +----------------------- += BUG FIXES + + fixed bug in parallel Server code which didn't htonl() frame + numbers correctly (so it didn't work on little-endian machines) + + fixed bug -- B-frames were always getting just 1 slice + + fixed listen() to use max connections allowed + + fixed noparallel.c so it doesn't complain during non-parallel + execution + += NEW FEATURES + + added level-2 p-search (exhaustive full, then half) + + now prints signal-to-noise ratio + + parallel code complains if absolute path not used for parameter + file + + changed single I/O server into separate Input and Output Servers + (and have Output Server combine frames in parallel) + += SPEED IMPROVEMENTS + + slight improvement in Mpost_QuantZigBlock (.10 ms/call down to .08 ms + on Sparc-10) + + improvement in speed of BlockifyFrame (45.8 ms/call down to 21.2 ms) + + improvement in ComputeMotionBlock (0.02 ms/call down to 0.01 ms) + + improvement in ComputeMotionLumBlock (0.04 ms/call down to 0.02 ms) + + improvement in LumAddMotionError (0.06 ms/call down to 0.05 ms) + (changed /2 to >>1) + += MAINTENANCE + + removed most memory.h references (except jrevdct) + + added CFLAGS lines in Makefile for SVR4.0 and SGI machines + + removed mproto.h + + got rid of printing connection times + + +1.0 Release July 1993 diff --git a/converter/ppm/ppmtompeg/COPYRIGHT b/converter/ppm/ppmtompeg/COPYRIGHT new file mode 100644 index 00000000..08216f34 --- /dev/null +++ b/converter/ppm/ppmtompeg/COPYRIGHT @@ -0,0 +1,20 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/HISTORY b/converter/ppm/ppmtompeg/HISTORY new file mode 100644 index 00000000..c9f4932a --- /dev/null +++ b/converter/ppm/ppmtompeg/HISTORY @@ -0,0 +1,313 @@ +The entire ppmtojpeg directory was adapted by Bryan from the package +mpeg_encode-1.5b-src (subdirectory mpeg_encode) on March 30, 1999. The +program was called mpeg_encode in that package. It was dated August 16, +1995 and came from ftp://mm-ftp.cs.berkeley.edu/pub/multimedia/mpeg/ +encode/mpeg_encode-1.5b-src.tar.gz + +Changes for Netpbm include: + + - mpeg_encode recognizes two input formats: "PPM" and "PNM". For + PPM, mpeg_encode parses it itself. For PNM, it uses the Netpbm + PNM library routines. + + In the Netpbm version, PPM is gone and "PPM" is accepted as a + synonym for "PNM". For PNM, it uses the PPM (not PNM) Netpbm + library routines. + + - mpeg_encode PNM code is broken for maxval != 255 (divides by zero + if maxval < 255 and overly quantize if > 255 because PNMtoYUV() + uses an integer divisor = maxval/256). + +In November 2004, Bryan rewrote large portions of the code so that he +could read it easily enough to debug some problems. He eliminated +long subroutines, global variables, gotos, and the like. + +See the file LOGIC for some documentation on how the code works. + + +The following is the README from the aforementioned mpeg_encode subdirectory. + + + MPEG-1 Video Software Encoder + (Version 1.5; February 1, 1995) + + Lawrence A. Rowe, Kevin Gong, Eugene Hung, Ketan Patel, Steve Smoot + and Dan Wallach + Computer Science Division-EECS, Univ. of Calif. at Berkeley + +This directory contains the freely distributed Berkeley MPEG-1 Video +Encoder. The encoder implements the standard described in the ISO/IEC +International Standard 11172-2. The code has been compiled and tested +on the following platforms: + + DECstation 5000 and Alpha + HP PA-RISC (HP/UX 9.X) (i.e., HP 9000/7XX and 9000/3XX) + SGI Indigo running IRIX 5.0.1 + Sun Sparc (SunOS 4.X) + +In addition, Rainer Menes from the Technical University of Munich has +ported the encoder and decoder to the Macintosh. You can get that code +directly from him (menes@statistik.tu-muenchen.de), or from the +Berkeley FTP archive (mm-ftp.CS.Berkeley.EDU). If you decide to port +the code to a new architecture, please let us know so that we can +incorporate the changes into our sources. + +This directory contains everything required to build the encoder +and run it. We have included source code, makefiles, binaries +for selected platforms, documentation, and test data. Installation +instructions are given in the file named src/mpeg_encode/INSTALL. A man +page is given in the file doc/mpeg_encode.1. A detailed user +manual is provided in postscript format in the file doc/user-manual.ps. + +The encoder will accept any input file format as long as you provide +a script to convert the images to PPM, YUV, JPEG, or JMOVIE format. Input +file processing is described in the file doc/INPUT.FORMAT. Options to +control input file processing and compression parameters are specified in +a parameter file. Very little error processing is done when reading +this file. We suggest you start with the sample parameter file +examples/template.param and modify it. See also examples/default.param. + +The convert directory of Mpeg-Tools contains utilities you might find +useful including: + +programs to do PPM/YUV conversion and programs to convert Parallax +XVideo JPEG files into PPM, YUV, or JPEG frames. + +The motion vector search window can be specified, including half-pixel +block matching, in the parameter file. We have implemented several +search algorithms for P-frames including: 1) exhaustive search, +2) subsampled search, and 3) logarithmic search. We have also implemented +several alternatives for B-frame block matching including: 1) interpolate +best forward and best backward block, 2) find backward block for best +forward or vice-versa (called CROSS2), and 3) exhaustive cross product +(i.e., go out for coffee and a donut!). The search algorithms are controlled +by options in the parameters file. For tips on choosing the right search +technique, see the user manual. + +The encoder can be run on one computer (i.e., sequential) or on several +computers (i.e., parallel). Our goal is to produce a portable, easy-to-use +encoder that we can use to encode large volumes of video material for +the Berkeley VOD system (see paper VodsProp93.ps.Z on the FTP archive). +The parallelism is done on a sequence of pictures. In other words, you +can spawn one or more children to encode continuous runs pictures. The +uncompressed data can be accessed either through NFS or TCP sockets. +The goal is to allow you to encode using multiple processors, think +spare cycles on workstations, to speed up the encoding time. Although +performance depends on the speed of individual processors, the file system +and network, and the P/B frame search methods, we have encoded 3.75 +frames/second on 8 HP Snakes running in parallel as compared with 0.6 +frames/second on 1 Snake. These are preliminary results. We are continuing +to experiment with and tune the code. Instructions to run the parallel system +are given in the man page and the parallel.param example parameter file. + +We have done some tuning to produce a reasonable encoder, but there are +many more optimizations that we would like to incorporate. These +extensions are listed in the file doc/EXTENSIONS. If you succeed in +implementing any of them, please let us know! + +Send bug reports to: + +mpeg-bugs@CS.Berkeley.EDU + Problems, questions, or patches should be sent to this address. + +Anyone interested in providing financial support for this research or +discussing other aspects of this project should contact Larry Rowe at +Rowe@CS.Berkeley.EDU (+1 510-642-5117). + +This software is freely distributed. That means, you may use it for +any non-commercial purpose. However, patents are held by several companies +on various aspects of the MPEG video standard. Companies or individuals +who want to develop commercial products that include this code must +acquire licenses from these companies. For information on licensing, see +Appendix F in the standard. + +ACKNOWLEDGEMENTS: + +We gratefully thank Hewlett-Packard and Fujitsu who provided financial +support for this work. We also want to thank the following people and +organizations for their help: + + Jef Poskanzer who developed the pbmplus package. + --------- + Copyright (C) 1989, 1991 by Jef Poskanzer. + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, provided + that the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation. This software is provided "as is" without express or + implied warranty. + --------- + + Eiichi Kowashi of Intel and Avideh Zakhor of U.C. Berkeley who + provided valuable suggestions on motion vector searching. + + Chad Fogg of the University of Washington who has helped us + understand many issues in MPEG coding and decoding. + + Rainer Menes of the Technical University of Munich who has ported the + the Berkeley MPEG encoder and decoder to the Macintosh, and he has + provided us with many suggestions to improve the code. + + Robert Safranek of ATT for comments, suggestions, and most of the + code for custom quantization tables. + + Jim Boucher of Boston University for jmovie2jpeg. + + The San Diego SuperComputing Center for providing facilities to + develop some of the code contained within. + + +This is the TODO file from the original Berkeley package: + + +TODO list for next release +-------------------------- + +Add option to do searches in Cr/Cb as well as Lum blocks +jpeg5! (below) +last-frame must be P/I error, and pattern interact badly +add gnuconfigure so the Makefile is cake +YUV correct (cf mail below) +fix the "ifdef BUGGY_CODE" code in bframe.c +Change sizing stuff so it works with non multiples of 16 +Does "RESIZE WxH" work? Seems to for PPm but not JPG. Fix it. Document it +mpeg_encode in parallel generates a "zero size warning" It should + exit(1) here, when not in parallel, and not warn when in parallel. + sometimes it generates a 0x0 MPEG! +Give time estimates for parallel encoding +Verify YUV file sizes with stat() call (when not STDIN) + +-------------------- + +YUV mail: +Please have a look on these few lines extracted from the ISO +mpeg2encode/readpic.c/read_ppm() available on +ftp.netcom.com:/pub/cf/cfogg/mpeg2 : + + ......... + + /* convert to YUV */ + + y = cr*r +cg*g +cb*b; + u = cu*(b-y); + v = cv*(r-y); + yp[j] = (219.0/256.0)*y + 16.5; /* nominal range : 16..235 */ + up[j] = (224.0/256.0)*u + 128.5; /* nominal range : 16..240 */ + vp[j] = (224.0/256.0)*v + 128.5; /* nominal range : 16..240 */ + ........... + +I think there is a slight misunderstanding in the Berkeley's mpeg1 codec about +what the YUV format looks like, exactly about how to translate from PPM to YUV +and vice versa : the dynamic of YUV format has to be reduced as described +above. Otherwise, on a full color display a Berkeley's MPEG bitstream has not +exactly the right colors if played by an ISO compliant player. + +Best regards + + + Thierry GODIN + +-------------------- +And just for fun, kevin's list: +To-do list (in no particular order) +---------- + - should delete decoded frame files when done with them + (need to make sure no one else needs it) + - port to CM5 + - try on Snake cluster, and other clusters (FDDI -- 100Mb/s) + - fix bug on snakes (look at header file for queue length) + - look at 24-bit display + - try having I/O server getting things in order, and asking Master + where to send them + - bug: closing connections at end (on DEC 5000) + - GOP on space in input list + - pnm convolve + - telescopic search + - include system layer + - update documentation + - show error images + - graphical interface (showing motion vectors, etc.) + - use DCT-space when computing error terms + - vary the q-scale according to the error term + - modify the program to have a finer-grained parallelism option -- we + can probably encode slices in parallel (this will only be useful if + we want to do a few B-frames using exhaustive search) + - make search technique stop at x.5, not x.0 + - pel aspect ratio in parameter file (2.4.3.2) + - skipped blocks options? + - recover from parallel machine errors? + - subsample B-search + - bug: decoded with 1 machine can freeze + - malloc bug: hello.param, with DECODED frames only + - portability: + times() function + popen/pclose + +Oh yes, I liked the concept of a spiral for your full search algorithm, +however I thought this code a little difficult to read. What about +using a look up table (pre generated at compile time) to generate +the coord offsets that would then spiral around the location in question? + + + change MAXPATHLEN to something else + + put ./ in test in Makefile + +Currently, the IPPBPBB sequence is fixed for the entire sequence. A later +version should probably either test for scene changes or allow the user to +specify them. + + + check all << and >> to make sure they are used properly + (note truncation of >>) + + allow variable bit rate + + allow size of video sequences to be set + + make REMOTE usage more clear + + fix bug: when I-frame only, and decoded, does a lot of extra work + + replace ZAG[i] with a pointer? (in quantization) + (and speed up by using 31 times the space (one for each + q-value) + + add interrupt handler to parallel encoder + + should pad black instead of truncating + - graph histogram of motion vectors + - allow new PATTERN statements inside of file listing + - put in run-time checks for size of int32, int16, etc. + - replace pnm crap with ppm.dwallach + - add option to allow different p-search in b-search + - allow -frames option along with parallel option (shouldn't be + too difficult) + - incorrect compression rates given if do -frames option + + - enforce: >Hmmm...I will have to look at the standard. I did find something earlier -- +>"forced updating" makes it illegal to have more than 132 P-frames without an +>I-frame. But "forced updating" does not disallow any number of consecutive +>B-frames. I'll have to check on limits for GOP lengths... + + - rectangular search windows + + - make parallel stats to 4 digits + +One of my friend just fixed the problem.....she +retype the whole parameter file and it is working +now. I think the problem was there were some +spacing problem......for example, if there +are some space is the line, when the +program read in....it just mess everything up. + +It really become a problem if there is space after the image name... +or even after the path name. + + Subject: may not want to >> 4 in postdct.c + +------------------------------------------------------------------------ +P.S. In the future versions (is one already been released), you could add +option for encoder to remove picture after encoding it & therefore saving +space on disk + option to sleep while picture it's waiting for is not done. +I've hacked this: (in readframe.c) + + while ((tempfile = fopen(fullFileName, "r")) == NULL) { + fprintf(stderr, "Cannot open '%s', retrying...\n", fullFileName); + sleep(120); + } + + fclose(tempfile); + +arijan@kette.fer.uni-lj.si diff --git a/converter/ppm/ppmtompeg/LOGIC b/converter/ppm/ppmtompeg/LOGIC new file mode 100644 index 00000000..8c19dc8d --- /dev/null +++ b/converter/ppm/ppmtompeg/LOGIC @@ -0,0 +1,126 @@ +This file describes (a little) how the program works. + +PARALLEL MODE +------------- + +In parallel mode, two processes run on the machine where you invoke +Ppmtompeg: the master server and the combine server. Sometimes, there's +a third process called a decode server, but I don't know what that's for +yet. + +Other processes, which are typically on separate machines, one per +machine, are called encoder processes. The code normally calls these +"child" processes and the documentation normally calls them "slave" +processes. We really should fix that. + +The master server's job is to feed work assignments to the encoder +processes. A work assignment is a set of frames to encode. + +The combine server's job is to take the encoded output from the encoder +processes and combine them into a single MPEG movie. + +The master process is the first process that exists. The first thing +it does is create the combine server. Then it creates the encoder +processes. It creates each encoder process with an initial +assignment. The master process then waits in a loop for an encoder +process to report that it has finished its assignment and gives a new +assignment to it. + +The master process and the combine process both have a listening TCP +port. They choose an available port number. When the master server +creates the combine server, it passes the master server's TCP listen +port number to the combine server. It then waits to hear from the +combine process what TCP listen port it has chosen. The combine +server connects to the master server's listen port and tells it. The +master server then passes to each encode server, as it creates it, +the TCP listen ports of both the master server and the combine server. + +When the combine server has processed all the frames, it shuts down. +It connects to the master server TCP listen port and tells the master +server it is shutting down. + +When an encoder server finishes a frame, it connects to the combine +server's TCP listen port and tells the combine server that the frame +is ready. + +When an encoder server finishes an assignment, it connects to the master +server TCP listen port and tells the master it is done, and receives over +the same connetion its next assignment. If there is no more work to do, +the master server instead tells the encoder server just to terminate. + +When the master server has told every encoder server to terminate, it +waits for the combine server to say that it has terminated. The master +server then terminates. + +To create the combine server, the master server forks and execs +'ppmtompeg' with the -output_server option. + +To create an encoder server, the master server invokes Ssh (or something +like it) and tells the remote shell to execute 'ppmtompeg' with the +-child option. + +The various processes communicate frame data via a shared filesystem +(e.g. NFS). An encoder server grabs the input frames from the shared +filesystem and writes the encoded frames to it. The combine server +grabs the encoded frames from it and writes the MPEG movie file to it. +The encoded frames go in individual files. The combine server deletes +each file after it has copied it to the MPEG movie file. Use the +KEEP_TEMP_FILES parameter file statement to keep them around for +debugging. + +There's also an alternative "remote I/O" method of communication that +doesn't require a shared filesystem. I haven't studied that. + +The master server and combine server code are in parallel.c. The +encoder server code is roughly the same as what the single encoder +process executes when you aren't running in parallel mode. + + +THE ENCODING PROCEDURE +---------------------- + +Encoding is done by ppmtompeg.c, which calls GenMPEGStream in mpeg.c to +do most of the work. + +The encoder goes through the input frames in movie sequence. But the +frames don't go into an MPEG stream in movie sequence. A B frame not +only can't be encoded without the subsequent I or P frame (reference +frame); it can't be decoded without it either. So in the MPEG stream, +B frames come immediately after the reference frame which comes +immediately after the B frames in the actual movie. + +When the input is from a sequential stream (the only way that's possible +today is with Standard Input), the encoder saves up B frame input until +after it has encoded and output the post reference frame. It does +this by chaining the input frames to the pre reference frame. We really +should clean this up so that a single module handles input of all kinds +and presents only a sequential stream to the encoder. The encoder should +not have special cases for the different types of input. That input +module would let the encoder ask from Frame N even if the input is +sequential. The input module would buffer frames from the sequential +input as necessary. + +In parallel mode, the combine server takes encoded frames from the +encoder servers as it comes. It can be in any order. The combine +server knows which frames go where in the output stream and outputs them +in the proper order. This is important for two reasons. First, the +encoder servers don't finish assignments in the same order in which they +get them. Second, when an encoder server gets an assignment that ends +with a B frame, the combine server has to wait for the encoder server +that has the next assignment to produce the post reference frame before +the combine server can do anything with that trailing B frame. + +genMPEGStream() encodes a frame at a time, but it inserts a stream +header and GOP headers where they belong. genMPEGStream() operates in +three modes: Whole Stream, GOP, and Just Frames. In Whole Stream +mode, it inserts all the required headers. In GOP mode, it inserts +GOP headers but not the stream header. In Just Frames mode, it +inserts no headers at all. In parallel mode, genMPEGStream generates +one frame per file, and only Just Frames mode makes any sense. We +really should fix this up so that the encoder always works in Just +Frames mode and a GOP builder module takes the encoder's output and +splices it with GOP headers and a stream builder module takes the GOP +builder's output and adds it to a stream header. In parallel mode, +the combine server would run the GOP builder and stream builder +modules. + diff --git a/converter/ppm/ppmtompeg/Makefile b/converter/ppm/ppmtompeg/Makefile new file mode 100644 index 00000000..5e923fee --- /dev/null +++ b/converter/ppm/ppmtompeg/Makefile @@ -0,0 +1,140 @@ +ifeq ($(SRCDIR)x,x) + SRCDIR = $(CURDIR)/../../.. + BUILDDIR = $(SRCDIR) +endif +SUBDIR = converter/ppm/ppmtompeg +VPATH=.:$(SRCDIR)/$(SUBDIR) + +include $(BUILDDIR)/Makefile.config + +ifeq ($(JPEGLIB),NONE) + # 'nojpeg' is a module that implements all the jpeg access routines as + # error messages that tell you we don't have jpeg capability + JPEG_MODULE = nojpeg + JPEGLIBX = +else + # 'jpeg' is a module that accesses J-movies via the JPEG library. + JPEG_MODULE = jpeg + JPEGLIBX = $(JPEGLIB) +endif + +INCLUDES = -I$(SRCDIR)/$(SUBDIR)/headers + +ifneq ($(JPEGHDR_DIR),NONE) + ifneq ($(JPEGHDR_DIR)x,x) + INCLUDES += -I$(JPEGHDR_DIR) + endif +endif + +# use -DLONG_32 iff +# 1) long's are 32 bits and +# 2) int's are not +# +# if you are using a non-ANSI compiler, then use: +# -DNON_ANSI_COMPILER +# +# one other option: +# -DHEINOUS_DEBUG_MODE +# + +MP_BASE_OBJS = mfwddct.o postdct.o huff.o bitio.o mheaders.o +MP_ENCODE_OBJS = iframe.o pframe.o bframe.o psearch.o bsearch.o block.o +MP_OTHER_OBJS = mpeg.o subsample.o param.o rgbtoycc.o \ + readframe.o combine.o jrevdct.o frame.o fsize.o frametype.o \ + specifics.o rate.o opts.o input.o gethostname.o +ifeq ($(OMIT_NETWORK),y) + MP_PARALLEL_OBJS = noparallel.o +else + MP_PARALLEL_OBJS = parallel.o psocket.o +endif +NONMAIN_OBJS = $(MP_BASE_OBJS) $(MP_OTHER_OBJS) $(MP_ENCODE_OBJS) \ + $(MP_PARALLEL_OBJS) $(JPEG_MODULE).o +OBJECTS = ppmtompeg.o $(NONMAIN_OBJS) +MERGE_OBJECTS = ppmtompeg.o2 $(NONMAIN_OBJS) +MP_INCLUDE = mproto.h mtypes.h huff.h bitio.h +MP_MISC = Makefile huff.table parse_huff.pl + +BINARIES = ppmtompeg +MERGEBINARIES = $(BINARIES) +SCRIPTS = + +.PHONY: all +all: ppmtompeg + +include $(SRCDIR)/Makefile.common + +ifeq ($(NEED_RUNTIME_PATH),Y) + LIBOPTR = -runtime +else + LIBOPTR = +endif + +ppmtompeg: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) + $(LD) -o $@ $(LDFLAGS) \ + $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \ + $(NETWORKLD) $(MATHLIB) $(LDLIBS) \ + $(RPATH) $(LADD) + +profile: $(OBJECTS) $(NETPBMLIB) $(LIBOPT) + $(LD) -o $@ -Bstatic -pg $(LDFLAGS) \ + $(OBJECTS) $(shell $(LIBOPT) $(NETPBMLIB) $(LIBOPTR) $(JPEGLIBX)) \ + $(NETWORKLD) $(MATHLIB) $(LDLIBS) \ + $(RPATH) $(LADD) + + +######### +# OTHER # +######### + +# +# Perl is necessary if you want to modify the Huffman RLE encoding table. +# +PERL = perl + +# The following stuff is for the Huffman encoding tables. It's commented-out +# because you probably don't want to change this. If you do, then uncommment +# it. +# +# huff.h: huff.c +# +# huff.c: parse_huff.pl huff.table +# $(PERL) parse_huff.pl huff.table + +MP_ALL_SRCS = $(patsubst %.o, %.c, $(MP_ALL_OBJS)) + +wc:; wc -l *.[ch] headers/*.h *.pl *.table +ci:; ci -l $(MP_ALL_SRCS) $(MP_INCLUDE) $(MP_MISC) +tags: $(MP_ALL_SRCS) + ctags -t $(MP_ALL_SRCS) + etags -f TAGS -t $(MP_ALL_SRCS) headers/*.h + +# +# WARNING: this assumes you're using GNU indent... +# +indent:; indent -T FILE -T int8 -T int16 -T int32 -T uint8 -T uint16 -T uint32 -T BitBucket -T MpegFrame -T Block -T FlatBlock $(MP_ALL_SRCS) + +spotless: clean + rm -f huff.c huff.h *.pure.a + +FORCE: + +# +# Copyright (c) 1995 The Regents of the University of California. +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose, without fee, and without written agreement is +# hereby granted, provided that the above copyright notice and the following +# two paragraphs appear in all copies of this software. +# +# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT +# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF +# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO +# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +# diff --git a/converter/ppm/ppmtompeg/bframe.c b/converter/ppm/ppmtompeg/bframe.c new file mode 100644 index 00000000..5dfb76d3 --- /dev/null +++ b/converter/ppm/ppmtompeg/bframe.c @@ -0,0 +1,1347 @@ +/*===========================================================================* + * bframe.c + * + * Procedures concerned with the B-frame encoding + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include <sys/param.h> +#include <assert.h> + +#include "ppm.h" + +#include "mtypes.h" +#include "bitio.h" +#include "frames.h" +#include "prototypes.h" +#include "block.h" +#include "fsize.h" +#include "param.h" +#include "mheaders.h" +#include "postdct.h" +#include "rate.h" +#include "opts.h" +#include "specifics.h" + +extern int **bfmvHistogram; +extern int **bbmvHistogram; + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int32 totalTime = 0; +static int qscaleB; +static float totalSNR = 0.0; +static float totalPSNR = 0.0; + +static struct bframeStats { + unsigned int BSkipped; + unsigned int BIBits; + unsigned int BBBits; + unsigned int Frames; + unsigned int FrameBits; + unsigned int BIBlocks; + unsigned int BBBlocks; + unsigned int BFOBlocks; /* forward only */ + unsigned int BBABlocks; /* backward only */ + unsigned int BINBlocks; /* interpolate */ + unsigned int BFOBits; + unsigned int BBABits; + unsigned int BINBits; +} bframeStats = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + +/*====================* + * EXTERNAL VARIABLES * + *====================*/ + +extern Block **dct, **dctr, **dctb; +extern dct_data_type **dct_data; +#define NO_MOTION 0 +#define MOTION 1 +#define SKIP 2 /* used in useMotion in dct_data */ + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +static void +zeroMotion(motion * const motionP) { + + motionP->fwd.y = motionP->fwd.x = motionP->bwd.y = motionP->bwd.x = 0; +} + + + +static motion +halfMotion(motion const motion) { + struct motion half; + + half.fwd.y = motion.fwd.y / 2; + half.fwd.x = motion.fwd.x / 2; + half.bwd.y = motion.bwd.y / 2; + half.bwd.x = motion.bwd.x / 2; + + return half; +} + + + + +/*===========================================================================* + * + * compute the block resulting from motion compensation + * + * RETURNS: motionBlock is modified + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static void +ComputeBMotionBlock(MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + int const mode, + motion const motion, + Block * const motionBlockP, + int const type) { + + Block prevBlock, nextBlock; + + switch(mode) { + case MOTION_FORWARD: + switch (type) { + case LUM_BLOCK: + ComputeMotionBlock(prev->ref_y, by, bx, motion.fwd, motionBlockP); + break; + case CB_BLOCK: + ComputeMotionBlock(prev->ref_cb, by, bx, motion.fwd, motionBlockP); + break; + case CR_BLOCK: + ComputeMotionBlock(prev->ref_cr, by, bx, motion.fwd, motionBlockP); + } + break; + case MOTION_BACKWARD: + switch (type) { + case LUM_BLOCK: + ComputeMotionBlock(next->ref_y, by, bx, motion.bwd, motionBlockP); + break; + case CB_BLOCK: + ComputeMotionBlock(next->ref_cb, by, bx, motion.bwd, motionBlockP); + break; + case CR_BLOCK: + ComputeMotionBlock(next->ref_cr, by, bx, motion.bwd, motionBlockP); + break; + } + break; + case MOTION_INTERPOLATE: + switch (type) { + case LUM_BLOCK: + ComputeMotionBlock(prev->ref_y, by, bx, motion.fwd, &prevBlock); + ComputeMotionBlock(next->ref_y, by, bx, motion.bwd, &nextBlock); + break; + case CB_BLOCK: + ComputeMotionBlock(prev->ref_cb, by, bx, motion.fwd, &prevBlock); + ComputeMotionBlock(next->ref_cb, by, bx, motion.bwd, &nextBlock); + break; + case CR_BLOCK: + ComputeMotionBlock(prev->ref_cr, by, bx, motion.fwd, &prevBlock); + ComputeMotionBlock(next->ref_cr, by, bx, motion.bwd, &nextBlock); + break; + } + { + unsigned int y; + for (y = 0; y < 8; ++y) { + int16 * const blockRow = (*motionBlockP)[y]; + int16 * const prevRow = prevBlock[y]; + int16 * const nextRow = nextBlock[y]; + unsigned int x; + for (x = 0; x < 8; ++x) + blockRow[x] = (prevRow[x] + nextRow[x] + 1) / 2; + } + } + break; + } +} + + + +/*===========================================================================* + * + * compute the DCT of the error term + * + * RETURNS: appropriate blocks of current will contain the DCTs + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static void +ComputeBDiffDCTs(MpegFrame * const current, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + int const mode, + motion const motion, + int * const patternP) { + + Block motionBlock; + + if (*patternP & 0x20) { + boolean significantDiff; + ComputeBMotionBlock(prev, next, by, bx, mode, motion, + &motionBlock, LUM_BLOCK); + ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x20; + } + + if (*patternP & 0x10) { + boolean significantDiff; + ComputeBMotionBlock(prev, next, by, bx+1, mode, motion, + &motionBlock, LUM_BLOCK); + ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x10; + } + + if (*patternP & 0x8) { + boolean significantDiff; + ComputeBMotionBlock(prev, next, by+1, bx, mode, motion, + &motionBlock, LUM_BLOCK); + ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x8; + } + + if (*patternP & 0x4) { + boolean significantDiff; + ComputeBMotionBlock(prev, next, by+1, bx+1, mode, motion, + &motionBlock, LUM_BLOCK); + ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x4; + } + + if (*patternP & 0x2) { + boolean significantDiff; + ComputeBMotionBlock(prev, next, by/2, bx/2, mode, + halfMotion(motion), &motionBlock, CB_BLOCK); + ComputeDiffDCTBlock(current->cb_blocks[by/2][bx/2], + dctb[by/2][bx/2], motionBlock, + &significantDiff); + if (!significantDiff) + *patternP ^= 0x2; + } + + if (*patternP & 0x1) { + boolean significantDiff; + ComputeBMotionBlock(prev, next, by/2, bx/2, mode, + halfMotion(motion), + &motionBlock, CR_BLOCK); + ComputeDiffDCTBlock(current->cr_blocks[by/2][bx/2], + dctr[by/2][bx/2], motionBlock, + &significantDiff); + if (!significantDiff) + *patternP ^= 0x1; + } +} + + + +/*===========================================================================* + * + * decides if this block should be coded as intra-block + * + * RETURNS: TRUE if intra-coding should be used; FALSE otherwise + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static boolean +DoBIntraCode(MpegFrame * const current, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + int const mode, + motion const motion) { + + boolean retval; + unsigned int y; + int32 sum = 0, vard = 0, varc = 0; + LumBlock motionBlock; + int fy, fx; + + ComputeBMotionLumBlock(prev, next, by, bx, mode, motion, &motionBlock); + + MotionToFrameCoord(by, bx, 0, 0, &fy, &fx); + + for (y = 0; y < 16; ++y) { + unsigned int x; + for (x = 0; x < 16; ++x) { + int32 const currPixel = current->orig_y[fy+y][fx+x]; + int32 const prevPixel = motionBlock.l[y][x]; + int32 const dif = currPixel - prevPixel; + + sum += currPixel; + varc += SQR(currPixel); + vard += SQR(dif); + } + } + + vard >>= 8; /* divide by 256; assumes mean is close to zero */ + varc = (varc>>8) - (sum>>8)*(sum>>8); + + if (vard <= 64) + retval = FALSE; + else if (vard < varc) + retval = FALSE; + else + retval = TRUE; + return retval; +} + + + +static int +ComputeBlockColorDiff(Block current, + Block motionBlock) { + + unsigned int y; + int diffTotal; + + diffTotal = 0; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + int const diffTmp = current[y][x] - motionBlock[y][x]; + diffTotal += ABS(diffTmp); + } + } + return diffTotal; +} + + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * MotionSufficient + * + * decides if this motion vector is sufficient without DCT coding + * + * RETURNS: TRUE if no DCT is needed; FALSE otherwise + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +static boolean +MotionSufficient(MpegFrame * const curr, + const LumBlock * const currBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + int const mode, + motion const motion) { + + LumBlock mLumBlock; + Block mColorBlock; + int lumErr, colorErr; + + /* check bounds */ + if ( mode != MOTION_BACKWARD ) { + if ( (by*DCTSIZE+(motion.fwd.y-1)/2 < 0) || + ((by+2)*DCTSIZE+(motion.fwd.y+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(motion.fwd.x-1)/2 < 0) || + ((bx+2)*DCTSIZE+(motion.fwd.x+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + if ( mode != MOTION_FORWARD ) { + if ( (by*DCTSIZE+(motion.bwd.y-1)/2 < 0) || + ((by+2)*DCTSIZE+(motion.bwd.y+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(motion.bwd.x-1)/2 < 0) || + ((bx+2)*DCTSIZE+(motion.bwd.x+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + /* check Lum */ + ComputeBMotionLumBlock(prev, next, by, bx, mode, motion, &mLumBlock); + lumErr = LumBlockMAD(currBlockP, &mLumBlock, 0x7fffffff); + if (lumErr > 512) { + return FALSE; + } + + /* check color */ + ComputeBMotionBlock(prev, next, by/2, bx/2, mode, + halfMotion(motion), &mColorBlock, CR_BLOCK); + colorErr = ComputeBlockColorDiff(curr->cr_blocks[by/2][bx/2], + mColorBlock); + ComputeBMotionBlock(prev, next, by/2, bx/2, mode, halfMotion(motion), + &mColorBlock, CB_BLOCK); + colorErr += ComputeBlockColorDiff(curr->cr_blocks[by/2][bx/2], + mColorBlock); + + return (colorErr < 256); /* lumErr checked above */ +} + + + + +struct stats { + int IBlocks; + int BBlocks; + int Skipped; + int totalBits; + int IBits; + int BBits; +}; + + + +static void +initializeStats(struct stats * const statsP) { + statsP->IBlocks = 0; + statsP->BBlocks = 0; + statsP->Skipped = 0; + statsP->totalBits = 0; + statsP->IBits = 0; + statsP->BBits = 0; +} + + + +static void +checkSpecifics(MpegFrame * const curr, + int const mbAddress, + int const QScale, + boolean * const skipItP, + boolean * const doBsearchP, + int * const modeP, + motion * const motionP) { +/*---------------------------------------------------------------------------- + We return *modeP iff we return *doBsearchP == FALSE. + + We return *motionP iff we return *skipItP == FALSE. +-----------------------------------------------------------------------------*/ + BlockMV * info; + + SpecLookup(curr->id, 2, mbAddress, &info, QScale); + if (info == NULL) { + *doBsearchP = TRUE; + *skipItP = FALSE; + } else { + *doBsearchP = FALSE; + + switch (info->typ) { + case TYP_SKIP: + *skipItP = TRUE; + break; + case TYP_FORW: + *skipItP = FALSE; + motionP->fwd.y = info->fy; + motionP->fwd.x = info->fx; + *modeP = MOTION_FORWARD; + break; + case TYP_BACK: + *skipItP = FALSE; + motionP->bwd.y = info->by; + motionP->bwd.x = info->bx; + *modeP = MOTION_BACKWARD; + break; + case TYP_BOTH: + *skipItP = FALSE; + motionP->fwd.y = info->fy; + motionP->fwd.x = info->fx; + motionP->bwd.y = info->by; + motionP->bwd.x = info->bx; + *modeP = MOTION_INTERPOLATE; + break; + default: + pm_error("Unreachable code in GenBFrame!"); + } + } +} + + + +static void +makeNonSkipBlock(int const y, + int const x, + MpegFrame * const curr, + MpegFrame * const prev, + MpegFrame * const next, + boolean const specificsOn, + int const mbAddress, + int const QScale, + const LumBlock * const currentBlockP, + int * const modeP, + int * const oldModeP, + boolean const IntrPBAllowed, + boolean * const lastIntraP, + motion * const motionP, + motion * const oldMotionP, + struct stats * const statsP) { + + motion motion; + int mode; + boolean skipIt; + boolean doBsearch; + + if (specificsOn) + checkSpecifics(curr, mbAddress, QScale, &skipIt, &doBsearch, + &mode, &motion); + else { + skipIt = FALSE; + doBsearch = TRUE; + } + if (skipIt) + dct_data[y][x].useMotion = SKIP; + else { + if (doBsearch) { + motion = *motionP; /* start with old motion */ + mode = BMotionSearch(currentBlockP, prev, next, y, x, + &motion, mode); + } + /* STEP 2: INTRA OR NON-INTRA CODING */ + if (IntraPBAllowed && + DoBIntraCode(curr, prev, next, y, x, mode, motion)) { + /* output I-block inside a B-frame */ + ++statsP->IBlocks; + zeroMotion(oldMotionP); + *lastIntraP = TRUE; + dct_data[y][x].useMotion = NO_MOTION; + *oldModeP = MOTION_FORWARD; + /* calculate forward dct's */ + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "l\n"); + mp_fwd_dct_block2(curr->y_blocks[y][x], dct[y][x]); + mp_fwd_dct_block2(curr->y_blocks[y][x+1], dct[y][x+1]); + mp_fwd_dct_block2(curr->y_blocks[y+1][x], dct[y+1][x]); + mp_fwd_dct_block2(curr->y_blocks[y+1][x+1], dct[y+1][x+1]); + if (collect_quant && (collect_quant_detailed & 1)) { + fprintf(collect_quant_fp, "c\n"); + } + mp_fwd_dct_block2(curr->cb_blocks[y>>1][x>>1], + dctb[y>>1][x>>1]); + mp_fwd_dct_block2(curr->cr_blocks[y>>1][x>>1], + dctr[y>>1][x>>1]); + + } else { /* dct P/Bi/B block */ + int pattern; + + pattern = 63; + *lastIntraP = FALSE; + ++statsP->BBlocks; + dct_data[y][x].mode = mode; + *oldModeP = mode; + dct_data[y][x].fmotionY = motion.fwd.y; + dct_data[y][x].fmotionX = motion.fwd.x; + dct_data[y][x].bmotionY = motion.bwd.y; + dct_data[y][x].bmotionX = motion.bwd.x; + + switch (mode) { + case MOTION_FORWARD: + ++bframeStats.BFOBlocks; + oldMotionP->fwd = motion.fwd; + break; + case MOTION_BACKWARD: + ++bframeStats.BBABlocks; + oldMotionP->bwd = motion.bwd; + break; + case MOTION_INTERPOLATE: + ++bframeStats.BINBlocks; + *oldMotionP = motion; + break; + default: + pm_error("INTERNAL ERROR: Illegal mode: %d", mode); + } + + ComputeBDiffDCTs(curr, prev, next, y, x, mode, motion, &pattern); + + dct_data[y][x].pattern = pattern; + dct_data[y][x].useMotion = MOTION; + if ( computeMVHist ) { + assert(motion.fwd.x + searchRangeB + 1 >= 0); + assert(motion.fwd.y + searchRangeB + 1 >= 0); + assert(motion.fwd.x + searchRangeB + 1 <= 2*searchRangeB + 2); + assert(motion.fwd.y + searchRangeB + 1 <= 2*searchRangeB + 2); + assert(motion.bwd.x + searchRangeB + 1 >= 0); + assert(motion.bwd.y + searchRangeB + 1 >= 0); + assert(motion.bwd.x + searchRangeB + 1 <= 2*searchRangeB + 2); + assert(motion.bwd.y + searchRangeB + 1 <= 2*searchRangeB + 2); + + ++bfmvHistogram[motion.fwd.x + searchRangeB + 1] + [motion.fwd.y + searchRangeB + 1]; + ++bbmvHistogram[motion.bwd.x + searchRangeB + 1] + [motion.bwd.y + searchRangeB + 1]; + } + } /* motion-block */ + } + *motionP = motion; + *modeP = mode; +} + + + +/*===========================================================================* + * + * GenBFrame + * + * generate a B-frame from previous and next frames, adding the result + * to the given bit bucket + * + * RETURNS: frame appended to bb + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GenBFrame(BitBucket * const bb, + MpegFrame * const curr, + MpegFrame * const prev, + MpegFrame * const next) { + + FlatBlock fba[6], fb[6]; + Block dec[6]; + int32 y_dc_pred, cr_dc_pred, cb_dc_pred; + int x, y; + struct motion motion; + struct motion oldMotion; + int oldMode = MOTION_FORWARD; + int mode = MOTION_FORWARD; + int offsetX, offsetY; + struct motion motionRem; + struct motion motionQuot; + struct stats stats; + boolean lastIntra = TRUE; + boolean motionForward, motionBackward; + int totalFrameBits; + int32 startTime, endTime; + int lastX, lastY; + int lastBlockX, lastBlockY; + int ix, iy; + LumBlock currentBlock; + int fy, fx; + boolean make_skip_block; + int mbAddrInc = 1; + int mbAddress; + int slicePos; + float snr[3], psnr[3]; + int idx; + int QScale; + BlockMV *info; + int bitstreamMode, newQScale; + int rc_blockStart=0; + boolean overflowChange=FALSE; + int overflowValue = 0; + + assert(prev != NULL); + assert(next != NULL); + + initializeStats(&stats); + + if (collect_quant) {fprintf(collect_quant_fp, "# B\n");} + if (dct == NULL) AllocDctBlocks(); + ++bframeStats.Frames; + totalFrameBits = bb->cumulativeBits; + startTime = time_elapsed(); + + /* Rate Control */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + targetRateControl(curr); + } + + QScale = GetBQScale(); + Mhead_GenPictureHeader(bb, B_FRAME, curr->id, fCodeB); + /* Check for Qscale change */ + if (specificsOn) { + newQScale = SpecLookup(curr->id, 0, 0 /* junk */, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + /* check for slice */ + newQScale = SpecLookup(curr->id, 1, 1, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); + + Frame_AllocBlocks(curr); + BlockifyFrame(curr); + + if ( printSNR ) { + Frame_AllocDecoded(curr, FALSE); + } + + /* for I-blocks */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + stats.totalBits = bb->cumulativeBits; + + if ( ! pixelFullSearch ) { + if ( ! prev->halfComputed ) { + ComputeHalfPixelData(prev); + } + + if ( ! next->halfComputed ) { + ComputeHalfPixelData(next); + } + } + + lastBlockX = Fsize_x / 8; + lastBlockY = Fsize_y / 8; + lastX = lastBlockX - 2; + lastY = lastBlockY - 2; + mbAddress = 0; + + /* Start with zero motion assumption */ + zeroMotion(&motion); + zeroMotion(&oldMotion); + zeroMotion(&motionRem); + zeroMotion(&motionQuot); + + /* find motion vectors and do dcts */ + /* In this first loop, all MVs are in half-pixel scope, (if FULL + is set then they will be multiples of 2). This is not true in + the second loop. + */ + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + slicePos = (mbAddress % blocksPerSlice); + + /* compute currentBlock */ + BLOCK_TO_FRAME_COORD(y, x, fy, fx); + for ( iy = 0; iy < 16; iy++ ) { + for ( ix = 0; ix < 16; ix++ ) { + currentBlock.l[iy][ix] = (int16)curr->orig_y[fy+iy][fx+ix]; + } + } + + if (slicePos == 0) { + zeroMotion(&oldMotion); + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + } + + /* STEP 1: Select Forward, Backward, or Interpolated motion + vectors */ + /* see if old motion is good enough */ + /* but force last block to be non-skipped */ + /* can only skip if: + * 1) not the last block in frame + * 2) not the last block in slice + * 3) not the first block in slice + * 4) previous block was not intra-coded + */ + if ( ((y < lastY) || (x < lastX)) && + (slicePos+1 != blocksPerSlice) && + (slicePos != 0) && + (! lastIntra) && + (BSkipBlocks) ) { + make_skip_block = + MotionSufficient(curr, ¤tBlock, + prev, next, y, x, oldMode, oldMotion); + } else + make_skip_block = FALSE; + + if (make_skip_block) { + /* skipped macro block */ + dct_data[y][x].useMotion = SKIP; + } else + makeNonSkipBlock(y, x, curr, prev, next, specificsOn, + mbAddress, + QScale, ¤tBlock, + &mode, &oldMode, + IntraPBAllowed, + &lastIntra, &motion, &oldMotion, &stats); + + ++mbAddress; + } + } + + /* reset everything */ + zeroMotion(&oldMotion); + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + mbAddress = 0; + + /* Now generate the frame */ + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + slicePos = (mbAddress % blocksPerSlice); + + if ( (slicePos == 0) && (mbAddress != 0) ) { + if (specificsOn) { + /* Make sure no slice Qscale change */ + newQScale = + SpecLookup(curr->id,1,mbAddress/blocksPerSlice, &info, QScale); + if (newQScale != -1) QScale = newQScale; + } + Mhead_GenSliceEnder(bb); + Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); + + /* reset everything */ + zeroMotion(&oldMotion); + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + mbAddrInc = 1+(x>>1); + } + + /* Determine if new Qscale needed for Rate Control purposes */ + if (bitstreamMode == FIXED_RATE) { + rc_blockStart = bb->cumulativeBits; + newQScale = needQScaleChange(QScale, + curr->y_blocks[y][x], + curr->y_blocks[y][x+1], + curr->y_blocks[y+1][x], + curr->y_blocks[y+1][x+1]); + if (newQScale > 0) { + QScale = newQScale; + } + } + + if (specificsOn) { + newQScale = SpecLookup(curr->id, 2, mbAddress, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + }} + + if (dct_data[y][x].useMotion == NO_MOTION) { + + GEN_I_BLOCK(B_FRAME, curr, bb, mbAddrInc, QScale); + mbAddrInc = 1; + stats.IBits += (bb->cumulativeBits - stats.totalBits); + stats.totalBits = bb->cumulativeBits; + + /* reset because intra-coded */ + zeroMotion(&oldMotion); + oldMode = MOTION_FORWARD; + lastIntra = TRUE; + + if ( printSNR ) { + /* need to decode block we just encoded */ + /* and reverse the DCT transform */ + for ( idx = 0; idx < 6; idx++ ) { + Mpost_UnQuantZigBlock(fb[idx], dec[idx], QScale, TRUE); + mpeg_jrevdct((int16 *)dec[idx]); + } + + /* now, unblockify */ + BlockToData(curr->decoded_y, dec[0], y, x); + BlockToData(curr->decoded_y, dec[1], y, x+1); + BlockToData(curr->decoded_y, dec[2], y+1, x); + BlockToData(curr->decoded_y, dec[3], y+1, x+1); + BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1); + } + } else if (dct_data[y][x].useMotion == SKIP) { + ++stats.Skipped; + mbAddrInc++; + + /* decode skipped block */ + if (printSNR) { + struct motion motion; + + for (idx = 0; idx < 6; ++idx) + memset((char *)dec[idx], 0, sizeof(Block)); + + if (pixelFullSearch) { + motion.fwd.y = 2 * oldMotion.fwd.y; + motion.fwd.x = 2 * oldMotion.fwd.x; + motion.bwd.y = 2 * oldMotion.bwd.y; + motion.bwd.x = 2 * oldMotion.bwd.x; + } else + motion = oldMotion; + + /* now add the motion block */ + AddBMotionBlock(dec[0], prev->decoded_y, + next->decoded_y, y, x, mode, motion); + AddBMotionBlock(dec[1], prev->decoded_y, + next->decoded_y, y, x+1, mode, motion); + AddBMotionBlock(dec[2], prev->decoded_y, + next->decoded_y, y+1, x, mode, motion); + AddBMotionBlock(dec[3], prev->decoded_y, + next->decoded_y, y+1, x+1, mode, motion); + AddBMotionBlock(dec[4], prev->decoded_cb, + next->decoded_cb, y/2, x/2, mode, + halfMotion(motion)); + AddBMotionBlock(dec[5], prev->decoded_cr, + next->decoded_cr, y/2, x/2, mode, + halfMotion(motion)); + + /* now, unblockify */ + BlockToData(curr->decoded_y, dec[0], y, x); + BlockToData(curr->decoded_y, dec[1], y, x+1); + BlockToData(curr->decoded_y, dec[2], y+1, x); + BlockToData(curr->decoded_y, dec[3], y+1, x+1); + BlockToData(curr->decoded_cb, dec[4], y/2, x/2); + BlockToData(curr->decoded_cr, dec[5], y/2, x/2); + } + } else /* B block */ { + int const fCode = fCodeB; + int pattern; + + pattern = dct_data[y][x].pattern; + motion.fwd.y = dct_data[y][x].fmotionY; + motion.fwd.x = dct_data[y][x].fmotionX; + motion.bwd.y = dct_data[y][x].bmotionY; + motion.bwd.x = dct_data[y][x].bmotionX; + + if (pixelFullSearch) + motion = halfMotion(motion); + + /* create flat blocks and update pattern if necessary */ + calc_blocks: + /* Note DoQuant references QScale, overflowChange, overflowValue, + pattern, and the calc_blocks label */ + DoQuant(0x20, dct[y][x], fba[0]); + DoQuant(0x10, dct[y][x+1], fba[1]); + DoQuant(0x08, dct[y+1][x], fba[2]); + DoQuant(0x04, dct[y+1][x+1], fba[3]); + DoQuant(0x02, dctb[y/2][x/2], fba[4]); + DoQuant(0x01, dctr[y/2][x/2], fba[5]); + + motionForward = (dct_data[y][x].mode != MOTION_BACKWARD); + motionBackward = (dct_data[y][x].mode != MOTION_FORWARD); + + /* Encode Vectors */ + if (motionForward) { + /* transform the fMotion vector into the appropriate values */ + offsetY = motion.fwd.y - oldMotion.fwd.y; + offsetX = motion.fwd.x - oldMotion.fwd.x; + + encodeMotionVector(offsetX, offsetY, + &motionQuot.fwd, &motionRem.fwd, + FORW_F, fCode); + oldMotion.fwd = motion.fwd; + } + + if (motionBackward) { + /* transform the bMotion vector into the appropriate values */ + offsetY = motion.bwd.y - oldMotion.bwd.y; + offsetX = motion.bwd.x - oldMotion.bwd.x; + encodeMotionVector(offsetX, offsetY, + &motionQuot.bwd, &motionRem.bwd, + BACK_F, fCode); + oldMotion.bwd = motion.bwd; + } + + oldMode = dct_data[y][x].mode; + + if (printSNR) { /* Need to decode */ + if (pixelFullSearch) { + motion.fwd.x *= 2; motion.fwd.y *= 2; + motion.bwd.x *= 2; motion.bwd.y *= 2; + } + for ( idx = 0; idx < 6; idx++ ) { + if ( pattern & (1 << (5-idx)) ) { + Mpost_UnQuantZigBlock(fba[idx], dec[idx], QScale, FALSE); + mpeg_jrevdct((int16 *)dec[idx]); + } else { + memset((char *)dec[idx], 0, sizeof(Block)); + } + } + + /* now add the motion block */ + AddBMotionBlock(dec[0], prev->decoded_y, + next->decoded_y, y, x, mode, motion); + AddBMotionBlock(dec[1], prev->decoded_y, + next->decoded_y, y, x+1, mode, motion); + AddBMotionBlock(dec[2], prev->decoded_y, + next->decoded_y, y+1, x, mode, motion); + AddBMotionBlock(dec[3], prev->decoded_y, + next->decoded_y, y+1, x+1, mode, motion); + AddBMotionBlock(dec[4], prev->decoded_cb, + next->decoded_cb, y/2, x/2, mode, + halfMotion(motion)); + AddBMotionBlock(dec[5], prev->decoded_cr, + next->decoded_cr, y/2, x/2, mode, + halfMotion(motion)); + + /* now, unblockify */ + BlockToData(curr->decoded_y, dec[0], y, x); + BlockToData(curr->decoded_y, dec[1], y, x+1); + BlockToData(curr->decoded_y, dec[2], y+1, x); + BlockToData(curr->decoded_y, dec[3], y+1, x+1); + BlockToData(curr->decoded_cb, dec[4], y/2, x/2); + BlockToData(curr->decoded_cr, dec[5], y/2, x/2); + } + + /* reset because non-intra-coded */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + lastIntra = FALSE; + mode = dct_data[y][x].mode; + + /* DBG_PRINT(("MB Header(%d,%d)\n", x, y)); */ + Mhead_GenMBHeader( + bb, 3 /* pict_code_type */, mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCodeB /* forw_f_code */, fCodeB /* back_f_code */, + motionRem.fwd.x /* horiz_forw_r */, + motionRem.fwd.y /* vert_forw_r */, + motionRem.bwd.x /* horiz_back_r */, + motionRem.bwd.y /* vert_back_r */, + motionForward /* motion_forw */, + motionQuot.fwd.x /* m_horiz_forw */, + motionQuot.fwd.y /* m_vert_forw */, + motionBackward /* motion_back */, + motionQuot.bwd.x /* m_horiz_back */, + motionQuot.bwd.y /* m_vert_back */, + pattern /* mb_pattern */, FALSE /* mb_intra */); + + mbAddrInc = 1; + + /* now output the difference */ + { + unsigned int x; + for (x = 0; x < 6; ++x) { + if (GET_ITH_BIT(pattern, 5-x)) + Mpost_RLEHuffPBlock(fba[x], bb); + } + } + + switch (mode) { + case MOTION_FORWARD: + bframeStats.BFOBits += (bb->cumulativeBits - stats.totalBits); + break; + case MOTION_BACKWARD: + bframeStats.BBABits += (bb->cumulativeBits - stats.totalBits); + break; + case MOTION_INTERPOLATE: + bframeStats.BINBits += (bb->cumulativeBits - stats.totalBits); + break; + default: + pm_error("PROGRAMMER ERROR: Illegal mode: %d", mode); + } + + stats.BBits += (bb->cumulativeBits - stats.totalBits); + stats.totalBits = bb->cumulativeBits; + + if (overflowChange) { + /* undo an overflow-caused Qscale change */ + overflowChange = FALSE; + QScale -= overflowValue; + overflowValue = 0; + } + } /* if I-block, skip, or B */ + + mbAddress++; + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + incMacroBlockBits( bb->cumulativeBits - rc_blockStart); + rc_blockStart = bb->cumulativeBits; + MB_RateOut(TYPE_BFRAME); + } + + } + } + + if ( printSNR ) { + BlockComputeSNR(curr,snr,psnr); + totalSNR += snr[0]; + totalPSNR += psnr[0]; + } + + Mhead_GenSliceEnder(bb); + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + updateRateControl(TYPE_BFRAME); + } + + endTime = time_elapsed(); + totalTime += (endTime-startTime); + + if ( showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(bitRateFile, "%5d\t%8d\n", curr->id, + 30*(bb->cumulativeBits-totalFrameBits)); + } + + if ( frameSummary && !realQuiet) { + fprintf(stdout, "FRAME %d (B): " + "I BLOCKS: %5d; B BLOCKS: %5d SKIPPED: %5d (%ld seconds)\n", + curr->id, stats.IBlocks, stats.BBlocks, stats.Skipped, + (long)((endTime-startTime)/TIME_RATE)); + if ( printSNR ) + fprintf(stdout, "FRAME %d: " + "SNR: %.1f\t%.1f\t%.1f\tPSNR: %.1f\t%.1f\t%.1f\n", + curr->id, snr[0], snr[1], snr[2], + psnr[0], psnr[1], psnr[2]); + } + + bframeStats.FrameBits += (bb->cumulativeBits-totalFrameBits); + bframeStats.BIBlocks += stats.IBlocks; + bframeStats.BBBlocks += stats.BBlocks; + bframeStats.BSkipped += stats.Skipped; + bframeStats.BIBits += stats.IBits; + bframeStats.BBBits += stats.BBits; + } + + +/*===========================================================================* + * + * SetBQScale + * + * set the B-frame Q-scale + * + * RETURNS: nothing + * + * SIDE EFFECTS: qscaleB + * + *===========================================================================*/ +void +SetBQScale(qB) + int qB; +{ + qscaleB = qB; +} + + +/*===========================================================================* + * + * GetBQScale + * + * get the B-frame Q-scale + * + * RETURNS: the Q-scale + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +GetBQScale() +{ + return qscaleB; +} + + +/*===========================================================================* + * + * ResetBFrameStats + * + * reset the B-frame stats + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ResetBFrameStats() { + + bframeStats.BIBlocks = 0; + bframeStats.BBBlocks = 0; + bframeStats.BSkipped = 0; + bframeStats.BIBits = 0; + bframeStats.BBBits = 0; + bframeStats.Frames = 0; + bframeStats.FrameBits = 0; + totalTime = 0; +} + + + +float +BFrameTotalTime(void) { + return (float)totalTime/(float)TIME_RATE; +} + + + +void +ShowBFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer) { + + if (bframeStats.Frames > 0) { + fprintf(fpointer, "-------------------------\n"); + fprintf(fpointer, "*****B FRAME SUMMARY*****\n"); + fprintf(fpointer, "-------------------------\n"); + + if (bframeStats.BIBlocks > 0) { + fprintf(fpointer, + " I Blocks: %5d (%6d bits) (%5d bpb)\n", + bframeStats.BIBlocks, bframeStats.BIBits, + bframeStats.BIBits/bframeStats.BIBlocks); + } else + fprintf(fpointer, " I Blocks: %5d\n", 0); + + if (bframeStats.BBBlocks > 0) { + fprintf(fpointer, + " B Blocks: %5d (%6d bits) (%5d bpb)\n", + bframeStats.BBBlocks, bframeStats.BBBits, + bframeStats.BBBits/bframeStats.BBBlocks); + fprintf(fpointer, + " B types: %5d (%4d bpb) " + "forw %5d (%4d bpb) back %5d (%4d bpb) bi\n", + bframeStats.BFOBlocks, + (bframeStats.BFOBlocks==0) ? + 0 : bframeStats.BFOBits/bframeStats.BFOBlocks, + bframeStats.BBABlocks, + (bframeStats.BBABlocks==0) ? + 0 : bframeStats.BBABits/bframeStats.BBABlocks, + bframeStats.BINBlocks, + (bframeStats.BINBlocks==0) ? + 0 : bframeStats.BINBits/bframeStats.BINBlocks); + } else + fprintf(fpointer, " B Blocks: %5d\n", 0); + + fprintf(fpointer, " Skipped: %5d\n", bframeStats.BSkipped); + + fprintf(fpointer, " Frames: %5d (%6d bits) " + "(%5d bpf) (%2.1f%% of total)\n", + bframeStats.Frames, bframeStats.FrameBits, + bframeStats.FrameBits/bframeStats.Frames, + 100.0*(float)bframeStats.FrameBits/(float)totalBits); + fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", + bframeStats.Frames*inputFrameBits/bframeStats.FrameBits, + 24.0*(float)bframeStats.FrameBits/ + (float)(bframeStats.Frames*inputFrameBits)); + if (printSNR) + fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", + totalSNR/(float)bframeStats.Frames, + totalPSNR/(float)bframeStats.Frames); + if (totalTime == 0) { + fprintf(fpointer, " Seconds: NONE\n"); + } else { + fprintf(fpointer, " Seconds: %9ld (%9.4f fps) " + "(%9ld pps) (%9ld mps)\n", + (long)(totalTime/TIME_RATE), + (float)((float)(TIME_RATE*bframeStats.Frames)/ + (float)totalTime), + (long)((float)TIME_RATE*(float)bframeStats.Frames * + (float)inputFrameBits/(24.0*(float)totalTime)), + (long)((float)TIME_RATE*(float)bframeStats.Frames * + (float)inputFrameBits/(256.0*24.0 * + (float)totalTime))); + } + } +} + + + +/*===========================================================================* + * + * compute the luminance block resulting from motion compensation + * + * RETURNS: motionBlock modified + * + * SIDE EFFECTS: none + * + * PRECONDITION: the motion vectors must be valid! + * + *===========================================================================*/ +void +ComputeBMotionLumBlock(MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + int const mode, + motion const motion, + LumBlock * const motionBlockP) { + + switch(mode) { + case MOTION_FORWARD: + ComputeMotionLumBlock(prev, by, bx, motion.fwd, motionBlockP); + break; + case MOTION_BACKWARD: + ComputeMotionLumBlock(next, by, bx, motion.bwd, motionBlockP); + break; + case MOTION_INTERPOLATE: { + LumBlock prevBlock, nextBlock; + unsigned int y; + + ComputeMotionLumBlock(prev, by, bx, motion.fwd, &prevBlock); + ComputeMotionLumBlock(next, by, bx, motion.bwd, &nextBlock); + + for (y = 0; y < 16; ++y) { + unsigned int x; + for (x = 0; x < 16; ++x) + motionBlockP->l[y][x] = + (prevBlock.l[y][x] + nextBlock.l[y][x] + 1) / 2; + } + } break; + default: + pm_error("Bad mode! Programmer error!"); + } /* switch */ +} + + +/*===========================================================================* + * + * estimate the seconds to compute a B-frame + * + * RETURNS: the time, in seconds + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +EstimateSecondsPerBFrame() { + if (bframeStats.Frames == 0) + return 20.0; + else + return (float)totalTime/((float)TIME_RATE*(float)bframeStats.Frames); +} + + diff --git a/converter/ppm/ppmtompeg/bitio.c b/converter/ppm/ppmtompeg/bitio.c new file mode 100644 index 00000000..e0dc4d4e --- /dev/null +++ b/converter/ppm/ppmtompeg/bitio.c @@ -0,0 +1,536 @@ +/*===========================================================================* + * bitio.c + * + * Procedures concerned with the bit-wise I/O + * + * EXPORTED PROCEDURES: + * Bitio_New + * Bitio_Free + * Bitio_Write + * Bitio_Flush + * Bitio_WriteToSocket + * Bitio_BytePad + * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + +#include "pm.h" +#include "intcode.h" + +#include "all.h" +#include "byteorder.h" +#include "bitio.h" +#include "mtypes.h" + + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static uint32 lower_mask[33] = { + 0, + 0x1, 0x3, 0x7, 0xf, + 0x1f, 0x3f, 0x7f, 0xff, + 0x1ff, 0x3ff, 0x7ff, 0xfff, + 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, + 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, + 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff +}; + + +extern time_t IOtime; + + +/*===========================================================================* + * + * Dump + * + * Writes out the first MAX_BITS bits of the bit bucket to the + * appropriate output file + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +Dump(BitBucket * const bbPtr) { + struct bitBucket *ptr, *tempPtr; + int i, nitems; + int bitsWritten = 0; + time_t tempTimeStart, tempTimeEnd; + + time(&tempTimeStart); + + for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS); + ptr = ptr->nextPtr) { + + bigend32 buffer[WORDS_PER_BUCKET]; + + if (ptr->bitsleftcur == 32 && ptr->currword == 0) { + continue; /* empty */ + } + + for (i = 0; i <= ptr->currword; ++i) + buffer[i] = pm_bigendFromUint32(ptr->bits[i]); + + nitems = fwrite(buffer, sizeof(buffer[0]), ptr->currword + 1, + bbPtr->filePtr); + if (nitems != ptr->currword+1) { + fprintf(stderr, + "Whoa! Trouble writing %u words (wrote %u words)! " + "Game over, dude!\n", + ptr->currword+1, nitems); + exit(1); + } + + bitsWritten += ((ptr->currword + 1) * 32); + } + + while ( bbPtr->firstPtr != ptr ) { + tempPtr = bbPtr->firstPtr; + bbPtr->firstPtr = tempPtr->nextPtr; + free(tempPtr); + } + + bbPtr->totalbits -= bitsWritten; + bbPtr->bitsWritten += bitsWritten; + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * Bitio_New + * + * Create a new bit bucket; filePtr is a pointer to the open file the + * bits should ultimately be written to. + * + * RETURNS: pointer to the resulting bit bucket + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +BitBucket * +Bitio_New(FILE * const filePtr) { + + BitBucket *bbPtr; + + bbPtr = (BitBucket *) malloc(sizeof(BitBucket)); + ERRCHK(bbPtr, "malloc"); + + bbPtr->firstPtr = bbPtr->lastPtr = malloc(sizeof(struct bitBucket)); + ERRCHK(bbPtr->firstPtr, "malloc"); + + bbPtr->totalbits = 0; + bbPtr->cumulativeBits = 0; + bbPtr->bitsWritten = 0; + bbPtr->filePtr = filePtr; + + bbPtr->firstPtr->nextPtr = NULL; + bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET; + bbPtr->firstPtr->bitsleftcur = 32; + bbPtr->firstPtr->currword = 0; + memset((char *)bbPtr->firstPtr->bits, 0, + sizeof(uint32) * WORDS_PER_BUCKET); + + return bbPtr; +} + + + +BitBucket * +Bitio_New_Filename(const char * const fileName) { + + FILE * outputFile; + + outputFile = fopen(fileName, "wb"); + if (outputFile == NULL) + pm_error("Could not open output file '%s'. " + "Errno=%d (%s)", fileName, errno, strerror(errno)); + + return Bitio_New(outputFile); +} + + + +/*===========================================================================* + * + * Bitio_Free + * + * Frees the memory associated with the given bit bucket + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Bitio_Free(BitBucket * const bbPtr) { + + struct bitBucket *tmpPtr, *nextPtr; + + for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) { + nextPtr = tmpPtr->nextPtr; + free(tmpPtr); + } + free(bbPtr); +} + + +/*===========================================================================* + * + * Bitio_Write + * + * Writes 'nbits' bits from 'bits' into the given bit bucket + * 'nbits' must be between 0 and 32 + * + * RETURNS: nothing + * + * SIDE EFFECTS: if the number of bits in the bit bucket surpasses + * MAX_BITS, then that many bits are flushed to the + * appropriate output file + * + *===========================================================================*/ +void +Bitio_Write(BitBucket * const bbPtr, + uint32 const bits_arg, + int const nbits) { + + register struct bitBucket *lastPtr, *newPtr; + register int delta; + uint32 bits; + + bits=bits_arg; + assert(nbits <= 32 && nbits >= 0); + + /* + * Clear top bits if not part of data, necessary due to down and + * dirty calls of Bitio_Write with unecessary top bits set. + */ + + bits &= lower_mask[nbits]; + bits = bits & lower_mask[nbits]; + + bbPtr->totalbits += nbits; + bbPtr->cumulativeBits += nbits; + lastPtr = bbPtr->lastPtr; + + delta = nbits - lastPtr->bitsleft; + if (delta >= 0) { + /* + * there's not enough room in the current bucket, so we're + * going to have to allocate another bucket + */ + newPtr = lastPtr->nextPtr = (struct bitBucket *) + malloc(sizeof(struct bitBucket)); + ERRCHK(newPtr, "malloc"); + newPtr->nextPtr = NULL; + newPtr->bitsleft = MAXBITS_PER_BUCKET; + newPtr->bitsleftcur = 32; + newPtr->currword = 0; + memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET); + bbPtr->lastPtr = newPtr; + + assert(lastPtr->currword == WORDS_PER_BUCKET - 1); + lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta); + lastPtr->bitsleft = 0; + lastPtr->bitsleftcur = 0; + /* lastPtr->currword++; */ + + if (!delta) { + if ( bbPtr->totalbits > MAX_BITS ) { + Dump(bbPtr); + } + } + + assert(delta <= 32); + newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta); + newPtr->bitsleft -= delta; + newPtr->bitsleftcur -= delta; + } else { + /* + * the current bucket will be sufficient + */ + delta = nbits - lastPtr->bitsleftcur; + lastPtr->bitsleftcur -= nbits; + lastPtr->bitsleft -= nbits; + + if (delta >= 0) + { + /* + * these bits will span more than one word + */ + lastPtr->bits[lastPtr->currword] |= (bits >> delta); + lastPtr->currword++; + lastPtr->bits[lastPtr->currword] = + (bits & lower_mask[delta]) << (32 - delta); + lastPtr->bitsleftcur = 32 - delta; + } else { + /* + * these bits will fit, whole + */ + lastPtr->bits[lastPtr->currword] |= (bits << (-delta)); + } + } + + if ( bbPtr->totalbits > MAX_BITS ) /* flush bits */ + Dump(bbPtr); +} + + +/*===========================================================================* + * + * Bitio_Flush + * + * Flushes all of the remaining bits in the given bit bucket to the + * appropriate output file. It will generate up to the nearest 8-bit + * unit of bits, which means that up to 7 extra 0 bits will be appended + * to the end of the file. + * + * RETURNS: nothing + * + * SIDE EFFECTS: frees the bit bucket + * + *===========================================================================*/ +void +Bitio_Flush(BitBucket * const bbPtr) { + + struct bitBucket *ptr, *tempPtr; + uint32 lastWord; + int i, nitems; + int bitsWritten = 0; + int bitsLeft; + unsigned int numWords; + uint8 charBuf[4]; + boolean flushHere = FALSE; + time_t tempTimeStart, tempTimeEnd; + + time(&tempTimeStart); + + bitsLeft = bbPtr->totalbits; + + for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) { + if (ptr->bitsleftcur == 32 && ptr->currword == 0) { + continue; /* empty */ + } + + if ( bitsLeft >= 32 ) { + bigend32 buffer[WORDS_PER_BUCKET]; + + if ( ((ptr->currword + 1) * 32) > bitsLeft ) { + numWords = ptr->currword; + flushHere = TRUE; + } else + numWords = ptr->currword+1; + + for (i = 0; i < numWords; ++i) + buffer[i] = pm_bigendFromUint32(ptr->bits[i]); + + nitems = fwrite(buffer, sizeof(buffer[0]), numWords, + bbPtr->filePtr); + if (nitems != numWords) { + if (ferror(bbPtr->filePtr)) + pm_error("Error writing %u words to flush a bit bucket. " + "fwrite() gives errno %d (%s)", + numWords, errno, strerror(errno)); + else + pm_error("Problem writing %u words " + "to flush a bit bucket. " + "Only %d words transferred.", + numWords, nitems); + } + + bitsWritten += (numWords * 32); + bitsLeft -= (numWords * 32); + } else { + flushHere = TRUE; + } + + if ( (bitsLeft < 32) && flushHere ) { + lastWord = ptr->bits[ptr->currword]; + + /* output the lastPtr word in big-endian order (network) */ + + /* now write out lastPtr bits */ + while ( bitsLeft > 0 ) { + charBuf[0] = (lastWord >> 24); + charBuf[0] &= lower_mask[8]; + fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr); + lastWord = (lastWord << 8); + bitsLeft -= 8; + bitsWritten += 8; + } + } + } + fflush(bbPtr->filePtr); + while ( bbPtr->firstPtr != ptr ) { + tempPtr = bbPtr->firstPtr; + bbPtr->firstPtr = tempPtr->nextPtr; + free(tempPtr); + } + + free(bbPtr); + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + + +void +Bitio_Close(BitBucket * const bbPtr) { + + fclose(bbPtr->filePtr); +} + + + +/*===========================================================================* + * + * Bitio_WriteToSocket + * + * Writes all of the remaining bits in the given bit bucket to the + * given socket. May pad the end of the socket stream with extra 0 + * bits as does Bitio_Flush. + * + * RETURNS: nothing + * + * SIDE EFFECTS: frees the bit bucket + * + *===========================================================================*/ +void +Bitio_WriteToSocket(BitBucket * const bbPtr, + int const socket) { + + struct bitBucket *ptr, *tempPtr; + uint32 lastWord; + int i, nitems; + int bitsWritten = 0; + int bitsLeft; + int numWords; + uint8 charBuf[4]; + boolean flushHere = FALSE; + + bitsLeft = bbPtr->totalbits; + + for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) { + if (ptr->bitsleftcur == 32 && ptr->currword == 0) { + continue; /* empty */ + } + + if ( bitsLeft >= 32 ) { + bigend32 buffer[WORDS_PER_BUCKET]; + + if ( ((ptr->currword + 1) * 32) > bitsLeft ) { + numWords = ptr->currword; + flushHere = TRUE; + } else { + numWords = ptr->currword+1; + } + + for (i = 0; i < numWords; ++i) + buffer[i] = pm_bigendFromUint32(ptr->bits[i]); + + nitems = write(socket, buffer, numWords * sizeof(buffer[0])); + if (nitems != numWords*sizeof(uint32)) { + fprintf(stderr, "Whoa! Trouble writing %u bytes " + "(wrote %u bytes)! " + "Game over, dude!\n", + (unsigned)(numWords*sizeof(buffer[0])), nitems); + exit(1); + } + + bitsWritten += (numWords * 32); + bitsLeft -= (numWords * 32); + } else { + flushHere = TRUE; + } + + if ( (bitsLeft < 32) && flushHere ) { + lastWord = ptr->bits[ptr->currword]; + + /* output the lastPtr word in big-endian order (network) */ + + /* now write out lastPtr bits */ + while ( bitsLeft > 0 ) { + charBuf[0] = (lastWord >> 24); + charBuf[0] &= lower_mask[8]; + if ( write(socket, charBuf, 1) != 1 ) { + fprintf(stderr, "ERROR: write of lastPtr bits\n"); + exit(1); + } + lastWord = (lastWord << 8); + bitsLeft -= 8; + bitsWritten += 8; + } + } + } + + while ( bbPtr->firstPtr != ptr ) { + tempPtr = bbPtr->firstPtr; + bbPtr->firstPtr = tempPtr->nextPtr; + free(tempPtr); + } + + free(bbPtr); +} + + +/*===========================================================================* + * + * Bitio_BytePad + * + * Pads the end of the bit bucket to the nearest byte with 0 bits + * + * RETURNS: nothing + * + *===========================================================================*/ +void +Bitio_BytePad(BitBucket * const bbPtr) { + + struct bitBucket *lastPtrPtr = bbPtr->lastPtr; + + if (lastPtrPtr->bitsleftcur % 8) { + Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8); + } +} diff --git a/converter/ppm/ppmtompeg/block.c b/converter/ppm/ppmtompeg/block.c new file mode 100644 index 00000000..913518c4 --- /dev/null +++ b/converter/ppm/ppmtompeg/block.c @@ -0,0 +1,1045 @@ +/*===========================================================================* + * block.c + * + * Block routines + * + * NOTES: MAD = Mean Absolute Difference + *===========================================================================*/ + +/* Copyright information is at end of file */ + +#include <assert.h> + +#include "pm_c_util.h" +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "bitio.h" +#include "prototypes.h" +#include "fsize.h" +#include "opts.h" +#include "postdct.h" + +#include "block.h" + +#define TRUNCATE_UINT8(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + + +extern Block **dct, **dctb, **dctr; + + +static vector +halfVector(vector const v) { + vector half; + + half.y = v.y/2; + half.x = v.x/2; + + return half; +} + +/*===========================* + * COMPUTE DCT OF DIFFERENCE * + *===========================*/ + +/*===========================================================================* + * + * compute current-motionBlock, take the DCT, and put the difference + * back into current + * + * RETURNS: current block modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ComputeDiffDCTBlock(Block current, + Block dest, + Block motionBlock, + boolean * const significantDifferenceP) { + + unsigned int y; + int diff; + + diff = 0; /* initial value */ + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + current[y][x] -= motionBlock[y][x]; + diff += ABS(current[y][x]); + } + } + /* Kill the block if change is too small */ + /* (block_bound defaults to 128, see opts.c) */ + if (diff < block_bound) + *significantDifferenceP = FALSE; + else { + mp_fwd_dct_block2(current, dest); + *significantDifferenceP = TRUE; + } +} + + + +/*===========================================================================* + * + * appropriate (according to pattern, the coded block pattern) blocks + * of 'current' are diff'ed and DCT'd. + * + * RETURNS: current blocks modified + * + * SIDE EFFECTS: Can remove too-small difference blocks from pattern + * + * PRECONDITIONS: appropriate blocks of 'current' have not yet been + * modified + * + *===========================================================================*/ +void +ComputeDiffDCTs(MpegFrame * const current, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int * const patternP) { + + Block motionBlock; + + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "l\n"); + if (*patternP & 0x20) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by, bx, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x20; + } + + if (*patternP & 0x10) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by, bx+1, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x10; + } + + if (*patternP & 0x8) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by+1, bx, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x8; + } + + if (*patternP & 0x4) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by+1, bx+1, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x4; + } + + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "c\n"); + + if (*patternP & 0x2) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_cb, by/2, bx/2, halfVector(m), + &motionBlock); + ComputeDiffDCTBlock(current->cb_blocks[by/2][bx/2], + dctb[by/2][bx/2], motionBlock, + &significantDiff); + if (!significantDiff) + *patternP ^= 0x2; + } + + if (*patternP & 0x1) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_cr, by/2, bx/2, halfVector(m), + &motionBlock); + ComputeDiffDCTBlock(current->cr_blocks[by/2][bx/2], + dctr[by/2][bx/2], motionBlock, + &significantDiff); + if (!significantDiff) + *patternP ^= 0x1; + } +} + + + +static void +computePrevFyFx(MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + uint8 *** const prevP, + int * const fyP, + int * const fxP) { + + boolean const xHalf = (ABS(m.x) % 2 == 1); + boolean const yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, m.y/2, m.x/2, fyP, fxP); + + assert(*fyP >= 0); assert(*fxP >= 0); + + /* C integer arithmetic rounds toward zero. But what we need is a + "floor" -- i.e. round down. So we adjust now for where the dividend + in the above divide by two was negative. + */ + + if (xHalf) { + if (m.x < 0) + --*fxP; + + if (yHalf) { + if (m.y < 0) + --*fyP; + + *prevP = prevFrame->halfBoth; + } else + *prevP = prevFrame->halfX; + } else if (yHalf) { + if (m.y < 0) + --*fyP; + + *prevP = prevFrame->halfY; + } else + *prevP = prevFrame->ref_y; +} + + + +/*======================* + * COMPUTE MOTION BLOCK * + *======================*/ + +/*===========================================================================* + * + * compute the motion-compensated block + * + * RETURNS: motionBlock + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTE: could try to speed this up using halfX, halfY, halfBoth, + * but then would have to compute for chrominance, and it's just + * not worth the trouble (this procedure is not called relatively + * often -- a constant number of times per macroblock) + * + *===========================================================================*/ +void +ComputeMotionBlock(uint8 ** const prev, + int const by, + int const bx, + vector const m, + Block * const motionBlockP) { + + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(m.x) % 2 == 1); + yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, m.y/2, m.x/2, &fy, &fx); + + if (xHalf && yHalf) { + unsigned int y; + /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and + (fy-1)+y+1 = fy+y + */ + if (m.y < 0) + --fy; + + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + uint8 * const srcPtr2 = &(prev[fy+y+1][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = + (srcPtr[x]+srcPtr[x+1]+srcPtr2[x]+srcPtr2[x+1]+2) >> 2; + } + } else if (xHalf) { + unsigned int y; + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = (srcPtr[x]+srcPtr[x+1]+1) >> 1; + } + } else if (yHalf) { + unsigned int y; + if ( m.y < 0 ) + fy--; + + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + uint8 * const srcPtr2 = &(prev[fy+y+1][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = (srcPtr[x]+srcPtr2[x]+1) >> 1; + } + } else { + unsigned int y; + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = srcPtr[x]; + } + } +} + + + +/*===========================================================================* + * + * compute the motion-compensated luminance block + * + * RETURNS: motionBlock + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTE: see ComputeMotionBlock + * + *===========================================================================*/ +void +ComputeMotionLumBlock(MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + LumBlock * const motionBlockP) { + + unsigned int y; + uint8 ** prev; + int fy, fx; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + for (y = 0; y < 16; ++y) { + uint8 * const across = &(prev[fy+y][fx]); + int32 * const macross = motionBlockP->l[y]; + unsigned int x; + + for (x = 0; x < 16; ++x) + macross[x] = across[x]; + } + + /* this is what's really happening, in slow motion: + * + * for (y = 0; y < 16; ++y, ++py) + * for (x = 0; x < 16; ++x, ++px) + * motionBlock[y][x] = prev[fy+y][fx+x]; + * + */ +} + + +/*=======================* + * BASIC ERROR FUNCTIONS * + *=======================*/ + + +/*===========================================================================* + * + * return the MAD of two luminance blocks + * + * RETURNS: the MAD, if less than bestSoFar, or some number bigger if not + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumBlockMAD(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + unsigned int y; + + diff = 0; /* initial value */ + + for (y = 0; y < 16; ++y) { + const int32 * const currentRow = currentBlockP->l[y]; + const int32 * const motionRow = motionBlockP->l[y]; + unsigned int x; + for (x = 0; x < 16; ++x) + diff += ABS(currentRow[x] - motionRow[x]); + + if (diff > bestSoFar) + /* We already know the MAD won't be less than bestSoFar; + Caller doesn't care by how much we missed, so just return + this. + */ + return diff; + } + /* Return the actual MAD */ + return diff; +} + + + +/*===========================================================================* + * + * return the MAD of the currentBlock and the motion-compensated block + * (without TUNEing) + * + * (by, bx) is the location of the block in the frame + * (block number coordinates). 'm' is the motion of the block in pixels. + * The moved block must be wholly within the frame. + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTES: this is the procedure that is called the most, and should therefore + * be the most optimized!!! + * + *===========================================================================*/ +int32 +LumMotionError(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 adiff; + int32 diff; /* max value of diff is 255*256 = 65280 */ + int y; + uint8 **prev; + int fy, fx; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + assert(fy >= 0); assert(fx >= 0); + + adiff = 0; /* initial value */ + diff = 0; /* initial value */ + + switch (SearchCompareMode) { + case DEFAULT_SEARCH: /* Default. */ + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &prev[fy+y][fx]; + unsigned int x; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = across[x]-cacross[x]; + diff += ABS(localDiff); + } + if (diff > bestSoFar) + return diff; + } + break; + + case LOCAL_DCT: { + Block dctdiff[4], dctquant[4]; + FlatBlock quant; + int x, i, tmp; + int distortion=0, datarate=0; + int pq = GetPQScale(); + + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + for (x = 0; x < 16; ++x) { + dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x]; + }} + + /* Calculate rate */ + for (i = 0; i < 4; ++i) { + mp_fwd_dct_block2(dctdiff[i], dctdiff[i]); + if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == + MPOST_ZERO) { + /* no sense in continuing */ + memset((char *)dctquant[i], 0, sizeof(Block)); + } else { + Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE); + mpeg_jrevdct((int16 *)dctquant[i]); + datarate += CalcRLEHuffLength(quant); + } + } + + /* Calculate distortion */ + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + for (x = 0; x < 16; ++x) { + tmp = across[x] - cacross[x] + + dctquant[(x>7)+2*(y>7)][y%8][x%8]; + distortion += tmp*tmp; + }} + distortion /= 256; + distortion *= LocalDCTDistortScale; + datarate *= LocalDCTRateScale; + diff = (int) sqrt(distortion*distortion + datarate*datarate); + break; + } + + case NO_DC_SEARCH: { + extern int32 niqtable[]; + int pq = niqtable[0]*GetPQScale(); + unsigned int y; + + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = across[x]-cacross[x]; + diff += localDiff; + adiff += ABS(localDiff); + } + } + + diff /= 64*pq; /* diff is now the DC difference (with QSCALE 1) */ + adiff -= 64*pq*ABS(diff); + diff = adiff; + } + break; + + case DO_Mean_Squared_Distortion: + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = across[x] - cacross[x]; + diff += localDiff * localDiff; + } + if (diff > bestSoFar) + return diff; + } + break; + } /* End of Switch */ + + return diff; +} + + + +/*===========================================================================* + * + * return the MAD of the currentBlock and the average of the blockSoFar + * and the motion-compensated block (this is used for B-frame searches) + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + *===========================================================================*/ +int32 +LumAddMotionError(const LumBlock * const currentBlockP, + const LumBlock * const blockSoFarP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + int y; + uint8 **prev; + int fy, fx; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + diff = 0; /* initial value */ + + /* do we add 1 before dividing by two? Yes -- see MPEG-1 doc page 46 */ + + for (y = 0; y < 16; ++y) { + unsigned int x; + const uint8 * const across = &prev[fy+y][fx]; + const int32 * const bacross = blockSoFarP->l[y]; + const int32 * const cacross = currentBlockP->l[y]; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = + ((across[x] + bacross[x] + 1) / 2) - cacross[x]; + diff += ABS(localDiff); + } + + if (diff > bestSoFar) + return diff; + } + + /* This is what's happening: + * + * ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock); + * + * for (y = 0; y < 16; ++y) + * for (x = 0; x < 16; ++x) { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + */ + + return diff; +} + + + +/*===========================================================================* + * + * adds the motion-compensated block to the given block + * + * RETURNS: block modified + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + *===========================================================================*/ +void +AddMotionBlock(Block block, + uint8 ** const prev, + int const by, + int const bx, + vector const m) { + + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(m.x) % 2 == 1); + yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, (m.y/2), (m.x/2), &fy, &fx); + + if (xHalf && yHalf) { + unsigned int y; + /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and + (fy-1)+y+1 = fy+y + */ + if (m.y < 0) + --fy; + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+ + prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2; + } + } else if (xHalf) { + unsigned int y; + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1; + } + } + } else if ( yHalf ) { + unsigned int y; + if (m.y < 0) + --fy; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1; + } + } + } else { + unsigned int y; + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (int16)prev[fy+y][fx+x]; + } + } + } +} + + +/*===========================================================================* + * + * adds the motion-compensated B-frame block to the given block + * + * RETURNS: block modified + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vectors MUST be valid + * + *===========================================================================*/ +void +AddBMotionBlock(Block block, + uint8 ** const prev, + uint8 ** const next, + int const by, + int const bx, + int const mode, + motion const motion) { + + unsigned int y; + Block prevBlock, nextBlock; + + switch (mode) { + case MOTION_FORWARD: + AddMotionBlock(block, prev, by, bx, motion.fwd); + break; + case MOTION_BACKWARD: + AddMotionBlock(block, next, by, bx, motion.bwd); + break; + default: + ComputeMotionBlock(prev, by, bx, motion.fwd, &prevBlock); + ComputeMotionBlock(next, by, bx, motion.bwd, &nextBlock); + } + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (prevBlock[y][x] + nextBlock[y][x] + 1) / 2; + } + } +} + + +/*===========================================================================* + * + * copies the given block into the appropriate data area + * + * RETURNS: data modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +BlockToData(uint8 ** const data, + Block block, + int const by, + int const bx) { + + int x, y; + int fy, fx; + int16 blockItem; + + BLOCK_TO_FRAME_COORD(by, bx, fy, fx); + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + blockItem = block[y][x]; + data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem); + } + } +} + + +/*===========================================================================* + * + * copies data into appropriate blocks + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + * NOTES: probably shouldn't be in this file + * + *===========================================================================*/ +void +BlockifyFrame(MpegFrame * const frameP) { + + int dctx, dcty; + int x, y; + int bx, by; + int fy, fx; + int16 *destPtr; + uint8 *srcPtr; + int16 *destPtr2; + uint8 *srcPtr2; + Block *blockPtr; + Block *blockPtr2; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + /* + * copy y data into y_blocks + */ + for (by = 0; by < dcty; by++) { + fy = by*DCTSIZE; + for (bx = 0; bx < dctx; bx++) { + fx = bx*DCTSIZE; + blockPtr = (Block *) &(frameP->y_blocks[by][bx][0][0]); + for (y = 0; y < DCTSIZE; y++) { + destPtr = &((*blockPtr)[y][0]); + srcPtr = &(frameP->orig_y[fy+y][fx]); + for (x = 0; x < DCTSIZE; x++) { + destPtr[x] = srcPtr[x]; + } + } + } + } + + /* + * copy cr/cb data into cr/cb_blocks + */ + for (by = 0; by < (dcty >> 1); by++) { + fy = by*DCTSIZE; + for (bx = 0; bx < (dctx >> 1); bx++) { + fx = bx*DCTSIZE; + blockPtr = (Block *) &(frameP->cr_blocks[by][bx][0][0]); + blockPtr2 = (Block *) &(frameP->cb_blocks[by][bx][0][0]); + for (y = 0; y < DCTSIZE; y++) { + destPtr = &((*blockPtr)[y][0]); + srcPtr = &(frameP->orig_cr[fy+y][fx]); + destPtr2 = &((*blockPtr2)[y][0]); + srcPtr2 = &(frameP->orig_cb[fy+y][fx]); + for (x = 0; x < DCTSIZE; x++) { + destPtr[x] = srcPtr[x]; + destPtr2[x] = srcPtr2[x]; + } + } + } + } +} + + +/*===========================================================================* + * * + * UNUSED PROCEDURES * + * * + * The following procedures are all unused by the encoder * + * * + * They are listed here for your convenience. You might want to use * + * them if you experiment with different search techniques * + * * + *===========================================================================*/ + +#ifdef UNUSED_PROCEDURES + +/* this procedure calculates the subsampled motion block (obviously) + * + * for speed, this procedure is probably not called anywhere (it is + * incorporated directly into LumDiffA, LumDiffB, etc. + * + * but leave it here anyway for clarity + * + * (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D + * + */ +void +ComputeSubSampledMotionLumBlock(MpegFrame * const prevFrame, + int const by, + int const bx, + int const my, + int const mx, + LumBlock const motionBlock, + int const startY, + int const startX) { + + uint8 *across; + int32 *macross; + int32 *lastx; + int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MotionToFrameCoord(by, bx, my/2, mx/2, &fy, &fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + for ( y = startY; y < 16; y += 2 ) { + across = &(prev[fy+y][fx+startX]); + macross = &(motionBlock[y][startX]); + lastx = &(motionBlock[y][16]); + while ( macross < lastx ) { + (*macross) = (*across); + across += 2; + macross += 2; + } + } + + /* this is what's really going on in slow motion: + * + * for ( y = startY; y < 16; y += 2 ) + * for ( x = startX; x < 16; x += 2 ) + * motionBlock[y][x] = prev[fy+y][fx+x]; + * + */ +} + + +/*===========================================================================* + * + * return the MAD of the currentBlock and the motion-compensated block, + * subsampled 4:1 with given starting coordinates (startY, startX) + * + * RETURNS: the MAD + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTES: this procedure is never called. Instead, see subsample.c. This + * procedure is provided only for possible use in extensions + * + *===========================================================================*/ +int32 +LumMotionErrorSubSampled(LumBlock const currentBlock, + MpegFrame * const prevFrame, + int const by, + int const bx, + int const my, + int const mx, + int const startY, + int const startX) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + int32 localDiff; + int32 *cacross; + uint8 *macross; + int32 *lastx; + int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + motionToFrameCoord(by, bx, my/2, mx/2, &fy, &fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + diff = 0; /* initial value */ + + for ( y = startY; y < 16; y += 2 ) { + macross = &(prev[fy+y][fx+startX]); + cacross = &(currentBlock[y][startX]); + lastx = &(currentBlock[y][16]); + while ( cacross < lastx ) { + localDiff = (*cacross)-(*macross); + diff += ABS(localDiff); + macross += 2; + cacross += 2; + } + } + + /* this is what's really happening: + * + * ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, + * lumMotionBlock, startY, startX); + * + * for ( y = startY; y < 16; y += 2 ) + * for ( x = startX; x < 16; x += 2 ) + * { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + * + */ + + return (int32)diff; +} + + +#endif /* UNUSED_PROCEDURES */ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + diff --git a/converter/ppm/ppmtompeg/bsearch.c b/converter/ppm/ppmtompeg/bsearch.c new file mode 100644 index 00000000..142987f5 --- /dev/null +++ b/converter/ppm/ppmtompeg/bsearch.c @@ -0,0 +1,1088 @@ +/*===========================================================================* + * bsearch.c + * + * Procedures concerned with the B-frame motion search + * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/bsearch.c,v 1.10 1995/08/07 21:49:01 smoot Exp $ + * $Log: bsearch.c,v $ + * Revision 1.10 1995/08/07 21:49:01 smoot + * fixed bug in initial-B-frame searches + * + * Revision 1.9 1995/06/26 21:36:07 smoot + * added new ordering constraints + * (B frames which are backward P's at the start of a sequence) + * + * Revision 1.8 1995/03/27 19:17:43 smoot + * killed useless type error messge (int32 defiend as int) + * + * Revision 1.7 1995/01/19 23:07:20 eyhung + * Changed copyrights + * + * Revision 1.6 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.5 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.3 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/03/02 18:27:05 keving + * nothing + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "pm_c_util.h" +#include "pm.h" +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "motion_search.h" +#include "fsize.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int bsearchAlg; + + +/*===========================* + * INITIALIZATION PROCEDURES * + *===========================*/ + + +/*===========================================================================* + * + * SetBSearchAlg + * + * set the B-search algorithm + * + * RETURNS: nothing + * + * SIDE EFFECTS: bsearchAlg modified + * + *===========================================================================*/ +void +SetBSearchAlg(const char * const alg) { + if (strcmp(alg, "SIMPLE") == 0) + bsearchAlg = BSEARCH_SIMPLE; + else if (strcmp(alg, "CROSS2") == 0) + bsearchAlg = BSEARCH_CROSS2; + else if (strcmp(alg, "EXHAUSTIVE") == 0) + bsearchAlg = BSEARCH_EXHAUSTIVE; + else + pm_error("ERROR: Impossible bsearch alg: %s", alg); +} + + +/*===========================================================================* + * + * BSearchName + * + * return the text of the B-search algorithm + * + * RETURNS: a pointer to the string + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +const char * +BSearchName(void) +{ + const char *retval; + + switch(bsearchAlg) { + case BSEARCH_SIMPLE: + retval = "SIMPLE";break; + case BSEARCH_CROSS2: + retval = "CROSS2";break; + case BSEARCH_EXHAUSTIVE: + retval = "EXHAUSTIVE";break; + default: + pm_error("ERROR: Impossible BSEARCH ALG: %d", psearchAlg); + } + return retval; +} + + + +/*===========================================================================* + * + * FindBestMatchExhaust + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: uses an exhaustive search + * + *===========================================================================*/ +static int32 +FindBestMatchExhaust(const LumBlock * const blockP, + const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int32 const bestSoFar, + int const searchRange) { + + register int mx, my; + int32 bestDiff; + int stepSize; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + boolean changed = FALSE; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + /* try old motion vector first */ + if (VALID_MOTION(*motionP)) { + bestDiff = LumAddMotionError(currentBlockP, blockP, prev, by, bx, + *motionP, bestSoFar); + + if (bestSoFar < bestDiff) + bestDiff = bestSoFar; + } else { + motionP->y = motionP->x = 0; + bestDiff = bestSoFar; + } + + /* maybe should try spiral pattern centered around prev motion vector? */ + + /* try a spiral pattern */ + for (distance = stepSize; + distance <= searchRange; + distance += stepSize) { + tempRightMY = MIN(distance, rightMY); + tempRightMX = MIN(distance, rightMX); + + /* do top, bottom */ + for (my = -distance; my < tempRightMY; + my += max(tempRightMY+distance-stepSize, stepSize)) { + if (my >= leftMY) { + for (mx = -distance; mx < tempRightMX; mx += stepSize) { + if (mx >= leftMX) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumAddMotionError(currentBlockP, blockP, prev, + by, bx, m, bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + + /* do left, right */ + for (mx = -distance; + mx < tempRightMX; + mx += max(tempRightMX+distance-stepSize, stepSize)) { + if (mx >= leftMX) { + for (my = -distance+stepSize; + my < tempRightMY-stepSize; + my += stepSize) { + if (my >= leftMY) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumAddMotionError(currentBlockP, blockP, prev, + by, bx, + m, bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + changed = TRUE; + } + } + } + } + } + } + + if (!changed) + ++bestDiff; + + return bestDiff; +} + + +/*===========================================================================* + * + * FindBestMatchTwoLevel + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: uses an exhaustive full-pixel search, then looks at + * neighboring half-pixels + * + *===========================================================================*/ +static int32 +FindBestMatchTwoLevel(const LumBlock * const blockP, + const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int32 const bestSoFar, + int const searchRange) { + + int mx, my; + int32 bestDiff; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + boolean changed = FALSE; + int yOffset, xOffset; + + /* exhaustive full-pixel search first */ + + COMPUTE_MOTION_BOUNDARY(by,bx,2,leftMY,leftMX,rightMY,rightMX); + + --rightMY; + --rightMX; + + /* convert vector into full-pixel vector */ + if (motionP->y > 0 ) { + if ((motionP->y % 2) == 1) + --motionP->y; + } else if ((-motionP->y % 2) == 1) + ++motionP->y; + + if (motionP->x > 0 ) { + if ((motionP->x % 2) == 1 ) + --motionP->x; + } else if ((-motionP->x % 2) == 1) + ++motionP->x; + + /* try old motion vector first */ + if (VALID_MOTION(*motionP)) { + bestDiff = LumAddMotionError(currentBlockP, blockP, prev, by, bx, + *motionP, bestSoFar); + + if (bestSoFar < bestDiff) + bestDiff = bestSoFar; + } else { + motionP->y = motionP->x = 0; + bestDiff = bestSoFar; + } + + ++rightMY; + ++rightMX; + + /* maybe should try spiral pattern centered around prev motion vector? */ + + /* try a spiral pattern */ + for ( distance = 2; distance <= searchRange; distance += 2 ) { + tempRightMY = MIN(distance, rightMY); + tempRightMX = MIN(distance, rightMX); + + /* do top, bottom */ + for (my = -distance; my < tempRightMY; + my += max(tempRightMY+distance-2, 2)) { + if (my >= leftMY) { + for ( mx = -distance; mx < tempRightMX; mx += 2 ) { + if (mx >= leftMX) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumAddMotionError(currentBlockP, blockP, prev, + by, bx, m, bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + + /* do left, right */ + for (mx = -distance; + mx < tempRightMX; + mx += max(tempRightMX+distance-2, 2)) { + if (mx >= leftMX) { + for (my = -distance+2; my < tempRightMY-2; my += 2) { + if (my >= leftMY) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumAddMotionError(currentBlockP, blockP, prev, + by, bx, m, bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + changed = TRUE; + } + } + } + } + } + } + + /* now look at neighboring half-pixels */ + my = motionP->y; + mx = motionP->x; + + --rightMY; + --rightMX; + + for (yOffset = -1; yOffset <= 1; ++yOffset) { + for (xOffset = -1; xOffset <= 1; ++xOffset) { + if ((yOffset != 0) || (xOffset != 0)) { + vector m; + m.y = my + yOffset; + m.x = mx + xOffset; + if (VALID_MOTION(m)) { + int diff; + diff = LumAddMotionError(currentBlockP, blockP, + prev, by, bx, m, bestDiff); + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + changed = TRUE; + } + } + } + } + } + + if (!changed) + ++bestDiff; + + return bestDiff; +} + + + +static void +trySpacing(int const spacing, + vector const center, + int const bestDiffSoFar, + vector * const newCenterP, + int32 * const newBestDiffP, + int const leftMY, + int const leftMX, + int const rightMY, + int const rightMX, + const LumBlock * const currentBlockP, + const LumBlock * const blockP, + MpegFrame * const prev, + int const by, + int const bx) { + + int tempRightMY, tempRightMX; + int my; + int bestDiff; + vector newCenter; + + /* Initial values */ + newCenter = center; + bestDiff = bestDiffSoFar; + + tempRightMY = MIN(rightMY, center.y + spacing + 1); + tempRightMX = MIN(rightMX, center.x + spacing + 1); + + for (my = center.y - spacing; my < tempRightMY; my += spacing) { + if (my >= leftMY) { + int mx; + for (mx = center.x - spacing; mx < tempRightMX; mx += spacing) { + if (mx >= leftMX) { + int32 diff; + vector m; + m.y = my; m.x = mx; + diff = LumAddMotionError(currentBlockP, blockP, prev, + by, bx, m, bestDiff); + + if (diff < bestDiff) { + /* We have a new best */ + newCenter = m; + bestDiff = diff; + } + } + } + } + } + *newCenterP = newCenter; + *newBestDiffP = bestDiff; +} + + + +static void +chooseNewSpacing(int const oldSpacing, + int const stepSize, + int * const newSpacingP) { + + if (stepSize == 2) { /* make sure spacing is even */ + if (oldSpacing == 2) + *newSpacingP = 0; + else { + int const trialSpacing = (oldSpacing + 1) / 2; + if ((trialSpacing % 2) != 0) + *newSpacingP = trialSpacing + 1; + else + *newSpacingP = trialSpacing; + } + } else { + if (oldSpacing == 1) + *newSpacingP = 0; + else + *newSpacingP = (oldSpacing + 1) / 2; + } +} + + + +/*===========================================================================* + * + * FindBestMatchLogarithmic + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: uses a logarithmic search + * + *===========================================================================*/ +static int32 +FindBestMatchLogarithmic(const LumBlock * const blockP, + const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int32 const bestSoFar, + int const searchRange) { + + int const stepSize = (pixelFullSearch ? 2 : 1); + + int32 diff, bestDiff; + int leftMY, leftMX; + int rightMY, rightMX; + int spacing; + vector center; + + COMPUTE_MOTION_BOUNDARY(by, bx, stepSize, + leftMY, leftMX, rightMY, rightMX); + + bestDiff = 0x7fffffff; + + /* grid spacing */ + if (stepSize == 2) { /* make sure spacing is even */ + spacing = (searchRange + 1) / 2; + if ((spacing % 2) != 0) + ++spacing; + } else + spacing = (searchRange + 1) / 2; + + /* Start at (0,0) */ + center.y = center.x = 0; + + while (spacing >= stepSize) { + trySpacing(spacing, center, bestDiff, + ¢er, &bestDiff, + leftMY, leftMX, rightMY, rightMX, + currentBlockP, blockP, prev, by, bx); + + chooseNewSpacing(spacing, stepSize, &spacing); + } + + /* check old motion -- see if it's better */ + if ((motionP->y >= leftMY) && (motionP->y < rightMY) && + (motionP->x >= leftMX) && (motionP->x < rightMX)) { + diff = LumAddMotionError(currentBlockP, blockP, prev, by, bx, + *motionP, bestDiff); + } else + diff = 0x7fffffff; + + if (bestDiff < diff) + *motionP = center; + else + bestDiff = diff; + + return bestDiff; +} + + + +/*===========================================================================* + * + * FindBestMatchSubSample + * + * tries to find matching motion vector + * see FindBestMatch for generic description + * + * DESCRIPTION: should use subsampling method, but too lazy to write all + * the code for it (so instead just calls FindBestMatchExhaust) + * + *===========================================================================*/ +static int32 +FindBestMatchSubSample(const LumBlock * const blockP, + const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int32 const bestSoFar, + int const searchRange) { + + /* too lazy to write the code for this... */ + + return FindBestMatchExhaust(blockP, currentBlockP, prev, + by, bx, motionP, bestSoFar, + searchRange); +} + + +/*===========================================================================* + * + * FindBestMatch + * + * given a motion-compensated block in one direction, tries to find + * the best motion vector in the opposite direction to match it + * + * RETURNS: the best vector (*motionY, *motionX), and the corresponding + * error is returned if it is better than bestSoFar. If not, + * then a number greater than bestSoFar is returned and + * (*motionY, *motionX) has no meaning. + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int32 +FindBestMatch(const LumBlock * const blockP, + const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int32 const bestSoFar, + int const searchRange) { + + int32 result; + + switch(psearchAlg) { + case PSEARCH_SUBSAMPLE: + result = FindBestMatchSubSample( + blockP, currentBlockP, prev, by, bx, + motionP, bestSoFar, searchRange); + break; + case PSEARCH_EXHAUSTIVE: + result = FindBestMatchExhaust( + blockP, currentBlockP, prev, by, bx, + motionP, bestSoFar, searchRange); + break; + case PSEARCH_LOGARITHMIC: + result = FindBestMatchLogarithmic( + blockP, currentBlockP, prev, by, bx, + motionP, bestSoFar, searchRange); + break; + case PSEARCH_TWOLEVEL: + result = FindBestMatchTwoLevel( + blockP, currentBlockP, prev, by, bx, + motionP, bestSoFar, searchRange); + break; + default: + pm_error("ERROR: Impossible P-search alg %d", psearchAlg); + } + return result; +} + + + +/*===========================================================================* + * + * finds the best backward and forward motion vectors + * if backNeeded == FALSE, then won't find best backward vector if it + * is worse than the best forward vector + * + * *motionP is input as well as output. We do not update it + * if it would make the error worse than the existing value. + * + * RETURNS: *motionP and associated errors *forwardErrP and *backErrP. + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +BMotionSearchNoInterp(const LumBlock * const currentBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + motion * const motionP, + int32 * const forwardErrP, + int32 * const backErrP, + boolean const backNeeded) { + + /* CALL SEARCH PROCEDURE */ + switch(psearchAlg) { + case PSEARCH_SUBSAMPLE: + *forwardErrP = PSubSampleSearch(currentBlockP, prev, by, bx, + &motionP->fwd,searchRangeB); + *backErrP = PSubSampleSearch(currentBlockP, next, by, bx, + &motionP->bwd, searchRangeB); + break; + case PSEARCH_EXHAUSTIVE: + *forwardErrP = PLocalSearch(currentBlockP, prev, by, bx, + &motionP->fwd, + 0x7fffffff, searchRangeB); + if (backNeeded) + *backErrP = PLocalSearch(currentBlockP, next, by, bx, + &motionP->bwd, + 0x7fffffff, searchRangeB); + else + *backErrP = PLocalSearch(currentBlockP, next, by, bx, + &motionP->bwd, + *forwardErrP, searchRangeB); + break; + case PSEARCH_LOGARITHMIC: + *forwardErrP = PLogarithmicSearch(currentBlockP, prev, by, bx, + &motionP->fwd, searchRangeB); + *backErrP = PLogarithmicSearch(currentBlockP, next, by, bx, + &motionP->bwd, searchRangeB); + break; + case PSEARCH_TWOLEVEL: + *forwardErrP = + PTwoLevelSearch(currentBlockP, prev, by, bx, + &motionP->fwd, 0x7fffffff, searchRangeB); + if ( backNeeded ) { + *backErrP = + PTwoLevelSearch(currentBlockP, next, by, bx, + &motionP->bwd, 0x7fffffff, searchRangeB); + } else { + *backErrP = + PTwoLevelSearch(currentBlockP, next, by, bx, + &motionP->bwd, *forwardErrP, searchRangeB); + } + break; + default: + pm_error("ERROR: Impossible PSEARCH ALG: %d", psearchAlg); + } +} + + + +/*===========================================================================* + * + * BMotionSearchSimple + * + * does a simple search for B-frame motion vectors + * see BMotionSearch for generic description + * + * DESCRIPTION: + * 1) find best backward and forward vectors + * 2) compute interpolated error using those two vectors + * 3) return the best of the three choices + * + * *fmyP,fmxP,bmyP,bmxP are inputs as well as outputs. We do not update + * them if it would make the error worse than the existing values. Otherwise, + * we update them to the vectors we find to be best. + * + *===========================================================================*/ +static int +BMotionSearchSimple(const LumBlock * const currentBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + motion * const motionP, + int const oldMode) { + + int retval; + int32 forwardErr, backErr, interpErr; + LumBlock interpBlock; + int32 bestSoFar; + + /* STEP 1 */ + BMotionSearchNoInterp(currentBlockP, prev, next, by, bx, motionP, + &forwardErr, &backErr, TRUE); + + /* STEP 2 */ + + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_INTERPOLATE, + *motionP, &interpBlock); + bestSoFar = min(backErr, forwardErr); + interpErr = + LumBlockMAD(currentBlockP, &interpBlock, bestSoFar); + + /* STEP 3 */ + + if (interpErr <= forwardErr) { + if (interpErr <= backErr) + retval = MOTION_INTERPOLATE; + else + retval = MOTION_BACKWARD; + } else if (forwardErr <= backErr) + retval = MOTION_FORWARD; + else + retval = MOTION_BACKWARD; + + return retval; +} + + +/*===========================================================================* + * + * BMotionSearchCross2 + * + * does a cross-2 search for B-frame motion vectors + * see BMotionSearch for generic description + * + * DESCRIPTION: + * 1) find best backward and forward vectors + * 2) find best matching interpolating vectors + * 3) return the best of the 4 choices + * + * *fmyP,fmxP,bmyP,bmxP are inputs as well as outputs. We do not update + * them if it would make the error worse than the existing values. Otherwise, + * we update them to the vectors we find to be best. + *===========================================================================*/ +static int +BMotionSearchCross2(const LumBlock * const currentBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + motion * const motionP, + int const oldMode) { + + int retval; + LumBlock forwardBlock, backBlock; + int32 forwardErr, backErr; + motion newMotion; + int32 interpErrF, interpErrB, interpErr; + int32 bestErr; + + /* STEP 1 */ + + BMotionSearchNoInterp(currentBlockP, prev, next, by, bx, motionP, + &forwardErr, &backErr, TRUE); + + bestErr = min(forwardErr, backErr); + + { + /* STEP 2 */ + + struct motion motion; + motion.fwd = motionP->fwd; + motion.bwd.y = motion.bwd.x = 0; + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_FORWARD, motion, + &forwardBlock); + + motion.fwd.y = motion.fwd.x = 0; + motion.bwd = motionP->bwd; + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_BACKWARD, motion, + &backBlock); + } + /* try a cross-search; total of 4 local searches */ + newMotion = *motionP; + + interpErrF = FindBestMatch(&forwardBlock, currentBlockP, + next, by, bx, &newMotion.bwd, + bestErr, searchRangeB); + bestErr = min(bestErr, interpErr); + interpErrB = FindBestMatch(&backBlock, currentBlockP, + prev, by, bx, &newMotion.fwd, + bestErr, searchRangeB); + + /* STEP 3 */ + + if (interpErrF <= interpErrB) { + newMotion.fwd = motionP->fwd; + interpErr = interpErrF; + } else { + newMotion.bwd = motionP->bwd; + interpErr = interpErrB; + } + + if (interpErr <= forwardErr) { + if (interpErr <= backErr) { + *motionP = newMotion; + retval = MOTION_INTERPOLATE; + } else + retval = MOTION_BACKWARD; + } else if (forwardErr <= backErr) + retval = MOTION_FORWARD; + else + retval = MOTION_BACKWARD; + + return retval; +} + + +/*===========================================================================* + * + * BMotionSearchExhaust + * + * does an exhaustive search for B-frame motion vectors + * see BMotionSearch for generic description + * + * DESCRIPTION: + * 1) find best backward and forward vectors + * 2) use exhaustive search to find best interpolating vectors + * 3) return the best of the 3 choices + * + * *fmyP,fmxP,bmyP,bmxP are inputs as well as outputs. We do not update + * them if it would make the error worse than the existing values. Otherwise, + * we update them to the vectors we find to be best. + *===========================================================================*/ +static int +BMotionSearchExhaust(const LumBlock * const currentBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + motion * const motionP, + int const oldMode) { + + int mx, my; + int32 bestDiff; + int stepSize; + LumBlock forwardBlock; + int32 forwardErr, backErr; + int leftMY, leftMX; + int rightMY, rightMX; + boolean result; + + /* STEP 1 */ + + BMotionSearchNoInterp(currentBlockP, prev, next, by, bx, motionP, + &forwardErr, &backErr, FALSE); + + if (forwardErr <= backErr) { + bestDiff = forwardErr; + result = MOTION_FORWARD; + } else { + bestDiff = backErr; + result = MOTION_BACKWARD; + } + + /* STEP 2 */ + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + if (searchRangeB < rightMY) + rightMY = searchRangeB; + if (searchRangeB < rightMX) + rightMX = searchRangeB; + + for (my = -searchRangeB; my < rightMY; my += stepSize) { + if (my >= leftMY) { + for (mx = -searchRangeB; mx < rightMX; mx += stepSize) { + if (mx >= leftMX) { + struct motion motion; + vector newMotion; + int32 diff; + motion.fwd.y = my; motion.fwd.x = mx; + motion.bwd.y = 0; motion.bwd.x = 0; + ComputeBMotionLumBlock(prev, next, by, bx, MOTION_FORWARD, + motion, &forwardBlock); + + newMotion = motion.fwd; + + diff = FindBestMatch(&forwardBlock, + currentBlockP, next, by, bx, + &newMotion, bestDiff, searchRangeB); + + if (diff < bestDiff) { + motionP->fwd = motion.fwd; + motionP->bwd = newMotion; + bestDiff = diff; + result = MOTION_INTERPOLATE; + } + } + } + } + } + return result; +} + + + +/*===========================================================================* + * + * search for the best B-frame motion vectors + * + * RETURNS: MOTION_FORWARD forward motion should be used + * MOTION_BACKWARD backward motion should be used + * MOTION_INTERPOLATE both should be used and interpolated + * + * OUTPUTS: *motionP = TWICE the forward motion vectors + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). Thus, the data in 'current' can be + * accesed through y_blocks, cr_blocks, and cb_blocks. + * This is not the case for the blocks in 'prev' and + * 'next.' Therefore, references into 'prev' and 'next' + * should be done + * through the struct items ref_y, ref_cr, ref_cb + * + * POSTCONDITIONS: current, prev, next should be unchanged. + * Some computation could be saved by requiring + * the dct'd difference to be put into current's block + * elements here, depending on the search technique. + * However, it was decided that it mucks up the code + * organization a little, and the saving in computation + * would be relatively little (if any). + * + * NOTES: the search procedure MAY return (0,0) motion vectors + * + *===========================================================================*/ +int +BMotionSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + motion * const motionP, + int const oldMode) { + + int retval; + + /* If we are an initial B frame, no possibility of forward motion */ + if (prev == (MpegFrame *) NULL) { + PMotionSearch(currentBlockP, next, by, bx, &motionP->bwd); + return MOTION_BACKWARD; + } + + /* otherwise simply call the appropriate algorithm, based on user + preference + */ + + switch(bsearchAlg) { + case BSEARCH_SIMPLE: + retval = BMotionSearchSimple(currentBlockP, prev, next, by, bx, + motionP, oldMode); + break; + case BSEARCH_CROSS2: + retval = BMotionSearchCross2(currentBlockP, prev, next, by, bx, + motionP, oldMode); + break; + case BSEARCH_EXHAUSTIVE: + retval = BMotionSearchExhaust(currentBlockP, prev, next, by, bx, + motionP, oldMode); + break; + default: + pm_error("Impossible B-frame motion search algorithm: %d", + bsearchAlg); + } + return retval; +} + + +/*===========================================================================* + * * + * UNUSED PROCEDURES * + * * + * The following procedures are all unused by the encoder * + * * + * They are listed here for your convenience. You might want to use * + * them if you experiment with different search techniques * + * * + *===========================================================================*/ + +#ifdef UNUSED_PROCEDURES + +/*===========================================================================* + * + * ValidBMotion + * + * decides if the given B-frame motion is valid + * + * RETURNS: TRUE if the motion is valid, FALSE otherwise + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +boolean +ValidBMotion(by, bx, mode, fmy, fmx, bmy, bmx) + int by; + int bx; + int mode; + int fmy; + int fmx; + int bmy; + int bmx; +{ + if ( mode != MOTION_BACKWARD ) { + /* check forward motion for bounds */ + if ( (by*DCTSIZE+(fmy-1)/2 < 0) || ((by+2)*DCTSIZE+(fmy+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(fmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(fmx+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + if ( mode != MOTION_FORWARD ) { + /* check backward motion for bounds */ + if ( (by*DCTSIZE+(bmy-1)/2 < 0) || ((by+2)*DCTSIZE+(bmy+1)/2-1 >= Fsize_y) ) { + return FALSE; + } + if ( (bx*DCTSIZE+(bmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(bmx+1)/2-1 >= Fsize_x) ) { + return FALSE; + } + } + + return TRUE; +} + + +#endif /* UNUSED_PROCEDURES */ diff --git a/converter/ppm/ppmtompeg/combine.c b/converter/ppm/ppmtompeg/combine.c new file mode 100644 index 00000000..341bb5dc --- /dev/null +++ b/converter/ppm/ppmtompeg/combine.c @@ -0,0 +1,357 @@ +/*===========================================================================* + * combine.c + * + * Procedures to combine frames or GOPS into an MPEG sequence + * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include <time.h> +#include <errno.h> +#include <unistd.h> + +#include "ppm.h" +#include "nstring.h" + +#include "mtypes.h" +#include "frames.h" +#include "frametype.h" +#include "motion_search.h" +#include "mpeg.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "mheaders.h" +#include "fsize.h" +#include "input.h" +#include "combine.h" + + +#define READ_ATTEMPTS 5 /* number of times (seconds) to retry an input file */ + +/*==================* + * GLOBAL VARIABLES * + *==================*/ +extern int yuvWidth, yuvHeight; + + +/*===========================================================================* + * + * AppendFile + * + * appends the output file with the contents of the given input file + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +AppendFile(FILE * const ofP, + FILE * const ifP) { + + uint8 data[9999]; + unsigned int readItems; + + readItems = 9999; + while (readItems == 9999) { + readItems = fread(data, sizeof(uint8), 9999, ifP); + if (readItems > 0) + fwrite(data, sizeof(uint8), readItems, ofP); + } + fclose(ifP); +} + + + +static void +appendSpecifiedGopFiles(struct inputSource * const inputSourceP, + const char * const currentGopPath, + FILE * const ofP) { + + unsigned int fileSeq; + + for (fileSeq = 0; fileSeq < inputSourceP->numInputFiles; ++fileSeq) { + const char * inputFileName; + const char * fileName; + unsigned int nAttempts; + FILE * ifP; + + GetNthInputFileName(inputSourceP, fileSeq, &inputFileName); + asprintfN(&fileName, "%s/%s", currentGOPPath, inputFileName); + + for (nAttempts = 0, ifP = NULL; + nAttempts < READ_ATTEMPTS && !ifP; + ++nAttempts) { + + FILE * ifP; + ifP = fopen(fileName, "rb"); + if (ifP == NULL) { + pm_message("ERROR: Couldn't read file '%s'. retry %u", + fileName, nAttempts); + sleep(1); + } + } + if (ifP) { + if (!realQuiet) + pm_message("Appending file %u '%s'", fileSeq, fileName); + AppendFile(ofP, ifP); + } else + pm_error("Unable to read file '%s' after %u attempts.", + fileName, READ_ATTEMPTS); + strfree(fileName); + strfree(inputFileName); + } +} + + + +static void +appendDefaultGopFiles(const char * const outputFileName, + FILE * const ofP) { + + unsigned int fileSeq; + bool endOfFiles; + + for (fileSeq = 0, endOfFiles = FALSE; !endOfFiles; ++fileSeq) { + const char * fileName; + FILE * ifP; + + asprintfN(&fileName, "%s.gop.%u", outputFileName, fileSeq); + + ifP = fopen(fileName, "rb"); + if (ifP == NULL) + endOfFiles = TRUE; + else { + if (!realQuiet) + pm_message("appending file: %s", fileName); + + AppendFile(ofP, ifP); + } + strfree(fileName); + } +} + + + +void +GOPsToMPEG(struct inputSource * const inputSourceP, + const char * const outputFileName, + FILE * const ofP) { +/*---------------------------------------------------------------------------- + Combine individual GOPs (one per file) into a single MPEG sequence file. +-----------------------------------------------------------------------------*/ + BitBucket * bb; + + { + /* Why is this reset called? */ + int x=Fsize_x, y=Fsize_y; + Fsize_Reset(); + Fsize_Note(0, yuvWidth, yuvHeight); + if (Fsize_x == 0 || Fsize_y == 0) + Fsize_Note(0, x, y); + } + + bb = Bitio_New(ofP); + + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ -1, + /* buf_size */ -1, /*c_param_flag */ 1, + /* iq_matrix */ customQtable, + /* niq_matrix */ customNIQtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + + /* it's byte-padded, so we can dump it now */ + Bitio_Flush(bb); + + if (inputSourceP->stdinUsed) + AppendFile(ofP, stdin); + else { + if (inputSourceP->numInputFiles > 0) + appendSpecifiedGopFiles(inputSourceP, currentGOPPath, ofP); + else + appendDefaultGopFiles(outputFileName, ofP); + } + bb = Bitio_New(ofP); + + /* SEQUENCE END CODE */ + Mhead_GenSequenceEnder(bb); + + Bitio_Flush(bb); + + fclose(ofP); +} + + + +static void +makeGOPHeader(FILE * const outputFileP, + unsigned int const totalFramesSent, + unsigned int const frameNumber, + unsigned int const seqWithinGop) { + + boolean closed = (totalFramesSent == frameNumber); + + BitBucket * bbP; + + if (!realQuiet) + fprintf(stdout, "Creating new GOP (closed = %d) after %d frames\n", + closed, seqWithinGop); + + /* new GOP */ + bbP = Bitio_New(outputFileP); + Mhead_GenGOPHeader(bbP, /* drop_frame_flag */ 0, + tc_hrs, tc_min, tc_sec, tc_pict, + closed, /* broken_link */ 0, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, + /* user_data_size */ 0); + Bitio_Flush(bbP); + SetGOPStartTime(frameNumber); +} + + + +void +FramesToMPEG(FILE * const outputFile, + void * const inputHandle, + fileAcquisitionFn acquireInputFile, + fileDispositionFn disposeInputFile) { +/*---------------------------------------------------------------------------- + Combine a bunch of frames, one per file, into a single MPEG + sequence file. + + acquireInputFile() opens a file that contains an encoded frame, + identified by frame number. It returns NULL when the frame number + is beyond the frames available. +-----------------------------------------------------------------------------*/ + unsigned int frameNumber; + BitBucket *bb; + FILE *inputFile; + int pastRefNum = -1; + int futureRefNum = -1; + boolean inputLeft; + unsigned int seqWithinGop; + /* The sequence of the current frame within its GOP. 0 is the + first frame of a GOP, etc. + */ + + tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0; + + { + /* Why is this reset called? */ + int x=Fsize_x, y=Fsize_y; + Fsize_Reset(); + Fsize_Note(0, yuvWidth, yuvHeight); + if (Fsize_x == 0 || Fsize_y == 0) + Fsize_Note(0, x, y); + } + SetBlocksPerSlice(); + + bb = Bitio_New(outputFile); + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ -1, + /* buf_size */ -1, /*c_param_flag */ 1, + /* iq_matrix */ qtable, /* niq_matrix */ niqtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + /* it's byte-padded, so we can dump it now */ + Bitio_Flush(bb); + + /* need to do these in the right order!!! */ + /* also need to add GOP headers */ + + seqWithinGop = 0; + totalFramesSent = 0; + + inputLeft = TRUE; + frameNumber = 0; + + makeGOPHeader(outputFile, totalFramesSent, frameNumber, seqWithinGop); + + while (inputLeft) { + if (FType_Type(frameNumber) != 'b') { + pastRefNum = futureRefNum; + futureRefNum = frameNumber; + + if ((FType_Type(frameNumber) == 'i') && seqWithinGop >= gopSize) { + makeGOPHeader(outputFile, + totalFramesSent, frameNumber, seqWithinGop); + seqWithinGop -= gopSize; + } + + acquireInputFile(inputHandle, frameNumber, &inputFile); + if (inputFile == NULL) + inputLeft = FALSE; + else { + AppendFile(outputFile, inputFile); + + disposeInputFile(inputHandle, frameNumber); + + ++seqWithinGop; + IncrementTCTime(); + + /* now, output the B-frames */ + if (pastRefNum != -1) { + unsigned int bNum; + + for (bNum = pastRefNum+1; bNum < futureRefNum; ++bNum) { + acquireInputFile(inputHandle, bNum, &inputFile); + + if (inputFile) { + AppendFile(outputFile, inputFile); + + disposeInputFile(inputHandle, bNum); + + ++seqWithinGop; + IncrementTCTime(); + } + } + } + } + } + ++frameNumber; + } + + if (!realQuiet) + fprintf(stdout, "Wrote %d frames\n", totalFramesSent); + + bb = Bitio_New(outputFile); + + /* SEQUENCE END CODE */ + Mhead_GenSequenceEnder(bb); + + Bitio_Flush(bb); + + fclose(outputFile); +} + + + diff --git a/converter/ppm/ppmtompeg/docs/EXTENSIONS b/converter/ppm/ppmtompeg/docs/EXTENSIONS new file mode 100644 index 00000000..c683fbf8 --- /dev/null +++ b/converter/ppm/ppmtompeg/docs/EXTENSIONS @@ -0,0 +1,41 @@ +EXTENSIONS +---------- + +This is a list of things that we'd like to incorporate into the encoder. +If you succeed in implementing any of them, please let us know! + +* better B-frame search technique +* use DCT-space when computing error terms +* vary the q-scale according to the error term +* other motion vector search techniques +* modify the program to have a finer-grained parallelism option -- we + can probably encode slices in parallel (this will only be useful if we + want to do a few B-frames using exhaustive search) +* include system layer +* VBV delay with rate control + + +CREATING YOUR OWN MOTION SEARCH ROUTINES +---------------------------------------- + +Adding your own special motion search routine is very easy. We'll explain +adding a P-frame search routine; adding a B-frame routine is similar. + +First, edit the procedures PMotionSearch and SetPSearchAlg (both in the +file psearch.c) to recognize your new search routine. You probably want +to define a constant + PSEARCH_<your search name> in headers/search.h + +Have PMotionSearch call your search procedure just as it calls the other +standard search procedures. Make sure your procedure follows the guidelines +in the comments for PMotionSearch. + +Note: The encoder uses MAD as its search criterion. The reason for this: + "Among the various criteria that can be used as a measure of the + match between the two blocks, the mean absolute difference (MAD) + is favored because it requires no multiplication and gives + similar performance as the mean squared error (MSE)." + - Liu and Zaccarin, + "New Fast Algorithms for the Estimation of Block Motion Vectors," + IEEE Transactions on Circuits and Systems for Video Technology + Volume 3 No. 2 (April 1993) diff --git a/converter/ppm/ppmtompeg/docs/INPUT.FORMAT b/converter/ppm/ppmtompeg/docs/INPUT.FORMAT new file mode 100644 index 00000000..8a663d3a --- /dev/null +++ b/converter/ppm/ppmtompeg/docs/INPUT.FORMAT @@ -0,0 +1,79 @@ + ---------------- + | FILE FORMATS | + ---------------- + +PPM FORMAT +---------- + +See http://netpbm.sourceforge.net/doc/ppm.html . + + +UCB YUV FORMAT +-------------- + +You should be aware that the YUV format used in the MPEG encoder is DIFFERENT +than the Abekas YUV format. The reason for this is that in MPEG, the U and +V components are subsampled 4:1. + +To give you an idea of what format the YUV file must be in, the following +code will read in a YUV file: + + unsigned char **y_data, **cr_data, **cb_data; + + void ReadYUV(char *fileName, int width, int height) + { + FILE *fpointer; + register int y; + + /* should allocate memory for y_data, cr_data, cb_data here */ + + fpointer = fopen(fileName, "r"); + + for (y = 0; y < height; y++) /* Y */ + fread(y_data[y], 1, width, fpointer); + + for (y = 0; y < height / 2; y++) /* U */ + fread(cb_data[y], 1, width / 2, fpointer); + + for (y = 0; y < height / 2; y++) /* V */ + fread(cr_data[y], 1, width / 2, fpointer); + + fclose(fpointer); + } + +There are two reasons why you'd want to use YUV files rather than PPM files: + 1) The YUV files are 50% the size of the corresponding PPM files + 2) The ENCODER will run slightly faster, since it doesn't have to + do the RGB to YUV conversion itself. + + +ABEKAS YUV FORMAT +----------------- + +The Abekas YUV Format interlaces the Y, U, and V values in a 4:2:2 format. +The interlacing pattern is + +UYVY + +for each group of 4 bytes in the file. + + +PHILLIPS YUV FORMAT +------------------- + +The Phillips YUV Format interlaces the Y, U, and V values in a 4:2:2 format. +The interlacing pattern is + +YVYU + +for each group of 4 bytes in the file. + + +You may specify either ABEKAS, PHILLIPS, or UCB as the YUV_FORMAT when +encoding ; the encoder defaults to UCB YUV_FORMAT if not specified. +In addition, if you've got a weird interlacing format, you can also +try and de-interlace it by giving the YUV pattern in the YUV_FORMAT. +So a YUV 4:4:4 format would be + +YUVYUV + diff --git a/converter/ppm/ppmtompeg/docs/parallel.param b/converter/ppm/ppmtompeg/docs/parallel.param new file mode 100644 index 00000000..0702d32c --- /dev/null +++ b/converter/ppm/ppmtompeg/docs/parallel.param @@ -0,0 +1,142 @@ +# parameter file template with parallel execution +# +# you can use this as a template, copying it to a separate file then modifying +# the copy +# +# +# any line beginning with '#' is a comment +# +# no line should be longer than 255 characters +# +# +# general format of each line is: +# <option> <spaces and/or tabs> <value> +# +# lines can generally be in any order +# +# only exception is the option 'INPUT' which must be followed by input +# files in the order in which they must appear, followed by 'END_INPUT' +# +# <option> MUST be in UPPER CASE +# + +PATTERN IBBPBBI +OUTPUT /n/picasso/users/keving/encode/output.mpg + +# mpeg_encode really only accepts 3 different file formats, but using a +# conversion statement it can effectively handle ANY file format +# +# you must specify whether you will convert to PNM or PPM or YUV format +# (must be upper case) +# +BASE_FILE_FORMAT YUV + +# +# if YUV format (or using parallel version), must provide width and height +# YUV_SIZE widthxheight +# this option is ignored if BASE_FILE_FORMAT is PPM or PNM and you're running +# on just one machine +# +YUV_SIZE 352x240 + +# the conversion statement +# +# Each occurrence of '*' will be replaced by the input file +# +# e.g., if you have a bunch of GIF files, then this might be: +# INPUT_CONVERT giftoppm * +# +# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then: +# INPUT_CONVERT cat *.Y *.U *.V +# +# e.g., if you are grabbing from laser disc you might have something like +# INPUT_CONVERT goto frame *; grabppm +# 'INPUT_CONVERT *' means the files are already in the base file format +# +INPUT_CONVERT * + +# number of frames in a GOP. +# +# since each GOP must have at least one I-frame, the encoder will find the +# the first I-frame after GOP_SIZE frames to start the next GOP +# +# later, will add more flexible GOP signalling +# +GOP_SIZE 6 + +# number of slices in a frame +# +# 1 is a good number. another possibility is the number of macroblock rows +# (which is the height divided by 16) +# +SLICES_PER_FRAME 1 + +# directory to get all input files from (makes this file easier to read) +# can't use stdin with parallel encoding +INPUT_DIR /n/picasso/users/keving/encode/input/tennis + +INPUT +# '*' is replaced by the numbers 01, 02, 03, 04 +# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11 +# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11 +# if I instead do [1-11+3], it would be 1, 4, 7, 10 +# the program assumes none of your input files has a name ending in ']' +# if you do, too bad!!! +# +# +stennis.*.yuv [0-7] +# can have more files here if you want...there is no limit on the number +# of files +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 10 + +# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC} +PSEARCH_ALG LOGARITHMIC + +# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE} +# +# note that EXHAUSTIVE is really, really, really slow +# +BSEARCH_ALG CROSS2 + +# +# these specify the q-scale for I, P, and B frames +# (values must be between 1 and 31) +# +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# this must be ORIGINAL or DECODED +REFERENCE_FRAME ORIGINAL + + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#REMOTE charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode ~keving/encode/examples/parallel.param +# remote machine: "REMOTE machine username executable param_file" +# mickey keving ~keving/encode/bin/dec-5000/mpeg_encode +#REMOTE mickey keving ~keving/encode/bin/dec-5000/mpeg_encode ~keving/encode/examples/parallel.param +#REMOTE mickey keving ~keving/encode/bin/dec-5000/mpeg_encode ~keving/encode/examples/parallel.param +REMOTE woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode ~keving/encode/examples/parallel.param +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/docs/param-summary b/converter/ppm/ppmtompeg/docs/param-summary new file mode 100644 index 00000000..d8322bfb --- /dev/null +++ b/converter/ppm/ppmtompeg/docs/param-summary @@ -0,0 +1,14 @@ +Different MPEG coding strategies +-------------------------------- + +Strategy Speed Compression Quality +-------- ----- ----------- ------- +Increase MV Search Range Down Up Up? +Increasing Q-Scale Same Up Down +Decreasing Q-Scale Same Down Up +Use half-pixel search Down Up Up? +Use pixel subsampling Up Down Down? +Use motion vector subsampling Up Down Down? +Use decoded frame as reference Same Unknown Up? +Varying q-scale Down Up Down + diff --git a/converter/ppm/ppmtompeg/docs/template.param b/converter/ppm/ppmtompeg/docs/template.param new file mode 100644 index 00000000..66b6dd98 --- /dev/null +++ b/converter/ppm/ppmtompeg/docs/template.param @@ -0,0 +1,154 @@ +# parameter file template with lots of comments to assist you +# +# you can use this as a template, copying it to a separate file then modifying +# the copy +# +# +# any line beginning with '#' is a comment +# +# no line should be longer than 255 characters +# +# +# general format of each line is: +# <option> <spaces and/or tabs> <value> +# +# lines can generally be in any order +# +# an exception is the option 'INPUT' which must be followed by input +# files in the order in which they must appear, followed by 'END_INPUT' +# +# Also, if you use the `command` method of generating input file names, +# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds +# the INPUT parameter. +# +# <option> MUST be in UPPER CASE +# + +PATTERN IBBPBBPBBPBBPBBP +OUTPUT output.mpg + +# mpeg_encode really only accepts 3 different file formats, but using a +# conversion statement it can effectively handle ANY file format +# +# You must specify the type of the input files. The choices are: +# YUV, PPM, JMOVIE, Y, JPEG, PNM +# (must be upper case) +# +BASE_FILE_FORMAT YUV + +# +# if YUV format (or using parallel version), must provide width and height +# YUV_SIZE widthxheight +# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running +# on just one machine +# +YUV_SIZE 352x240 + +# If you are using YUV, there are different supported file formats. +# EYUV or UCB are the same as previous versions of this encoder. +# (All the Y's, then U's then V's, in 4:2:0 subsampling.) +# Other formats, such as Abekas, Phillips, or a general format are +# permissible, the general format is a string of Y's, U's, and V's +# to specify the file order. + +INPUT_FORMAT UCB + +# the conversion statement +# +# Each occurrence of '*' will be replaced by the input file +# +# e.g., if you have a bunch of GIF files, then this might be: +# INPUT_CONVERT giftoppm * +# +# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then: +# INPUT_CONVERT cat *.Y *.U *.V +# +# e.g., if you are grabbing from laser disc you might have something like +# INPUT_CONVERT goto frame *; grabppm +# 'INPUT_CONVERT *' means the files are already in the base file format +# +INPUT_CONVERT * + +# number of frames in a GOP. +# +# since each GOP must have at least one I-frame, the encoder will find the +# the first I-frame after GOP_SIZE frames to start the next GOP +# +# later, will add more flexible GOP signalling +# +GOP_SIZE 16 + +# number of slices in a frame +# +# 1 is a good number. another possibility is the number of macroblock rows +# (which is the height divided by 16) +# +SLICES_PER_FRAME 1 + +# directory to get all input files from (makes this file easier to read) +INPUT_DIR ../input/tennis + +# There are a bunch of ways to specify the input files. +# from a simple one-per-line listing, to the following +# way of numbering them. See the manual for more information. +INPUT +# '*' is replaced by the numbers 01, 02, 03, 04 +# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11 +# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11 +# if I instead do [1-11+3], it would be 1, 4, 7, 10 +# the program assumes none of your input files has a name ending in ']' +# if you do, too bad!!! +# +# +stennis.*.yuv [0-23] +# can have more files here if you want...there is no limit on the number +# of files +END_INPUT + + + +# Many of the remaining options have to do with the motion search and qscale + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels for both P and B frame searches +# specify two numbers if you wish to serc different ranges in the two. +RANGE 10 + +# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC} +PSEARCH_ALG LOGARITHMIC + +# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE} +# +# note that EXHAUSTIVE is really, really, really slow +# +BSEARCH_ALG CROSS2 + +# +# these specify the q-scale for I, P, and B frames +# (values must be between 1 and 31) +# These are the Qscale values for the entire frame in variable bit-rate +# mode, and starting points (but not important) for constant bit rate +# +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# this must be ORIGINAL or DECODED +REFERENCE_FRAME ORIGINAL + +# for parallel parameters see parallel.param in the exmaples subdirectory + +# if you want constant bit-rate mode, specify it as follows (number is bits/sec): +BIT_RATE 1000000 + +# To specify the buffer size (327680 is default, measused in bits, for 16bit words) +BUFFER_SIZE 327680 + +# The frame rate is the number of frames/second (legal values: +# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60 +FRAME_RATE 30 + +# There are many more options, see the users manual for examples.... +# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc. diff --git a/converter/ppm/ppmtompeg/docs/users-guide.ps b/converter/ppm/ppmtompeg/docs/users-guide.ps new file mode 100644 index 00000000..2e39be0a --- /dev/null +++ b/converter/ppm/ppmtompeg/docs/users-guide.ps @@ -0,0 +1,3233 @@ +%! +%%BoundingBox: (atend) +%%Pages: (atend) +%%DocumentFonts: (atend) +%%EndComments +% +% FrameMaker PostScript Prolog 3.0, for use with FrameMaker 3.0 +% Copyright (c) 1986,87,89,90,91 by Frame Technology Corporation. +% All rights reserved. +% +% Known Problems: +% Due to bugs in Transcript, the 'PS-Adobe-' is omitted from line 1 +/FMversion (3.0) def +% Set up Color vs. Black-and-White + /FMPrintInColor systemdict /colorimage known + systemdict /currentcolortransfer known or def +% Uncomment this line to force b&w on color printer +% /FMPrintInColor false def +/FrameDict 195 dict def +systemdict /errordict known not {/errordict 10 dict def + errordict /rangecheck {stop} put} if +% The readline in 23.0 doesn't recognize cr's as nl's on AppleTalk +FrameDict /tmprangecheck errordict /rangecheck get put +errordict /rangecheck {FrameDict /bug true put} put +FrameDict /bug false put +mark +% Some PS machines read past the CR, so keep the following 3 lines together! +currentfile 5 string readline +00 +0000000000 +cleartomark +errordict /rangecheck FrameDict /tmprangecheck get put +FrameDict /bug get { + /readline { + /gstring exch def + /gfile exch def + /gindex 0 def + { + gfile read pop + dup 10 eq {exit} if + dup 13 eq {exit} if + gstring exch gindex exch put + /gindex gindex 1 add def + } loop + pop + gstring 0 gindex getinterval true + } def + } if +/FMVERSION { + FMversion ne { + /Times-Roman findfont 18 scalefont setfont + 100 100 moveto + (FrameMaker version does not match postscript_prolog!) + dup = + show showpage + } if + } def +/FMLOCAL { + FrameDict begin + 0 def + end + } def + /gstring FMLOCAL + /gfile FMLOCAL + /gindex FMLOCAL + /orgxfer FMLOCAL + /orgproc FMLOCAL + /organgle FMLOCAL + /orgfreq FMLOCAL + /yscale FMLOCAL + /xscale FMLOCAL + /manualfeed FMLOCAL + /paperheight FMLOCAL + /paperwidth FMLOCAL +/FMDOCUMENT { + array /FMfonts exch def + /#copies exch def + FrameDict begin + 0 ne dup {setmanualfeed} if + /manualfeed exch def + /paperheight exch def + /paperwidth exch def + /yscale exch def + /xscale exch def + currenttransfer cvlit /orgxfer exch def + currentscreen cvlit /orgproc exch def + /organgle exch def /orgfreq exch def + setpapername + manualfeed {true} {papersize} ifelse + {manualpapersize} {false} ifelse + {desperatepapersize} if + end + } def + /pagesave FMLOCAL + /orgmatrix FMLOCAL + /landscape FMLOCAL +/FMBEGINPAGE { + FrameDict begin + /pagesave save def + 3.86 setmiterlimit + /landscape exch 0 ne def + landscape { + 90 rotate 0 exch neg translate pop + } + {pop pop} + ifelse + xscale yscale scale + /orgmatrix matrix def + gsave + } def +/FMENDPAGE { + grestore + pagesave restore + end + showpage + } def +/FMFONTDEFINE { + FrameDict begin + findfont + ReEncode + 1 index exch + definefont + FMfonts 3 1 roll + put + end + } def +/FMFILLS { + FrameDict begin + array /fillvals exch def + end + } def +/FMFILL { + FrameDict begin + fillvals 3 1 roll put + end + } def +/FMNORMALIZEGRAPHICS { + newpath + 0.0 0.0 moveto + 1 setlinewidth + 0 setlinecap + 0 0 0 sethsbcolor + 0 setgray + } bind def + /fx FMLOCAL + /fy FMLOCAL + /fh FMLOCAL + /fw FMLOCAL + /llx FMLOCAL + /lly FMLOCAL + /urx FMLOCAL + /ury FMLOCAL +/FMBEGINEPSF { + end + /FMEPSF save def + /showpage {} def + FMNORMALIZEGRAPHICS + [/fy /fx /fh /fw /ury /urx /lly /llx] {exch def} forall + fx fy translate + rotate + fw urx llx sub div fh ury lly sub div scale + llx neg lly neg translate + } bind def +/FMENDEPSF { + FMEPSF restore + FrameDict begin + } bind def +FrameDict begin +/setmanualfeed { +%%BeginFeature *ManualFeed True + statusdict /manualfeed true put +%%EndFeature + } def +/max {2 copy lt {exch} if pop} bind def +/min {2 copy gt {exch} if pop} bind def +/inch {72 mul} def +/pagedimen { + paperheight sub abs 16 lt exch + paperwidth sub abs 16 lt and + {/papername exch def} {pop} ifelse + } def + /papersizedict FMLOCAL +/setpapername { + /papersizedict 14 dict def + papersizedict begin + /papername /unknown def + /Letter 8.5 inch 11.0 inch pagedimen + /LetterSmall 7.68 inch 10.16 inch pagedimen + /Tabloid 11.0 inch 17.0 inch pagedimen + /Ledger 17.0 inch 11.0 inch pagedimen + /Legal 8.5 inch 14.0 inch pagedimen + /Statement 5.5 inch 8.5 inch pagedimen + /Executive 7.5 inch 10.0 inch pagedimen + /A3 11.69 inch 16.5 inch pagedimen + /A4 8.26 inch 11.69 inch pagedimen + /A4Small 7.47 inch 10.85 inch pagedimen + /B4 10.125 inch 14.33 inch pagedimen + /B5 7.16 inch 10.125 inch pagedimen + end + } def +/papersize { + papersizedict begin + /Letter {lettertray letter} def + /LetterSmall {lettertray lettersmall} def + /Tabloid {11x17tray 11x17} def + /Ledger {ledgertray ledger} def + /Legal {legaltray legal} def + /Statement {statementtray statement} def + /Executive {executivetray executive} def + /A3 {a3tray a3} def + /A4 {a4tray a4} def + /A4Small {a4tray a4small} def + /B4 {b4tray b4} def + /B5 {b5tray b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + /FMdicttop countdictstack 1 add def + statusdict begin stopped end + countdictstack -1 FMdicttop {pop end} for + } def +/manualpapersize { + papersizedict begin + /Letter {letter} def + /LetterSmall {lettersmall} def + /Tabloid {11x17} def + /Ledger {ledger} def + /Legal {legal} def + /Statement {statement} def + /Executive {executive} def + /A3 {a3} def + /A4 {a4} def + /A4Small {a4small} def + /B4 {b4} def + /B5 {b5} def + /unknown {unknown} def + papersizedict dup papername known {papername} {/unknown} ifelse get + end + stopped + } def +/desperatepapersize { + statusdict /setpageparams known + { + paperwidth paperheight 0 1 + statusdict begin + {setpageparams} stopped pop + end + } if + } def +/savematrix { + orgmatrix currentmatrix pop + } bind def +/restorematrix { + orgmatrix setmatrix + } bind def +/dmatrix matrix def +/dpi 72 0 dmatrix defaultmatrix dtransform + dup mul exch dup mul add sqrt def +/freq dpi 18.75 div 8 div round dup 0 eq {pop 1} if 8 mul dpi exch div def +/sangle 1 0 dmatrix defaultmatrix dtransform exch atan def +/DiacriticEncoding [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl +/numbersign /dollar /percent /ampersand /quotesingle /parenleft +/parenright /asterisk /plus /comma /hyphen /period /slash /zero /one +/two /three /four /five /six /seven /eight /nine /colon /semicolon +/less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K +/L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash +/bracketright /asciicircum /underscore /grave /a /b /c /d /e /f /g /h +/i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar +/braceright /asciitilde /.notdef /Adieresis /Aring /Ccedilla /Eacute +/Ntilde /Odieresis /Udieresis /aacute /agrave /acircumflex /adieresis +/atilde /aring /ccedilla /eacute /egrave /ecircumflex /edieresis +/iacute /igrave /icircumflex /idieresis /ntilde /oacute /ograve +/ocircumflex /odieresis /otilde /uacute /ugrave /ucircumflex +/udieresis /dagger /.notdef /cent /sterling /section /bullet +/paragraph /germandbls /registered /copyright /trademark /acute +/dieresis /.notdef /AE /Oslash /.notdef /.notdef /.notdef /.notdef +/yen /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/ordfeminine /ordmasculine /.notdef /ae /oslash /questiondown +/exclamdown /logicalnot /.notdef /florin /.notdef /.notdef +/guillemotleft /guillemotright /ellipsis /.notdef /Agrave /Atilde +/Otilde /OE /oe /endash /emdash /quotedblleft /quotedblright +/quoteleft /quoteright /.notdef /.notdef /ydieresis /Ydieresis +/fraction /currency /guilsinglleft /guilsinglright /fi /fl /daggerdbl +/periodcentered /quotesinglbase /quotedblbase /perthousand +/Acircumflex /Ecircumflex /Aacute /Edieresis /Egrave /Iacute +/Icircumflex /Idieresis /Igrave /Oacute /Ocircumflex /.notdef /Ograve +/Uacute /Ucircumflex /Ugrave /dotlessi /circumflex /tilde /macron +/breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +] def +/ReEncode { + dup + length + dict begin + { + 1 index /FID ne + {def} + {pop pop} ifelse + } forall + 0 eq {/Encoding DiacriticEncoding def} if + currentdict + end + } bind def +/graymode true def + /bwidth FMLOCAL + /bpside FMLOCAL + /bstring FMLOCAL + /onbits FMLOCAL + /offbits FMLOCAL + /xindex FMLOCAL + /yindex FMLOCAL + /x FMLOCAL + /y FMLOCAL +/setpattern { + /bwidth exch def + /bpside exch def + /bstring exch def + /onbits 0 def /offbits 0 def + freq sangle landscape {90 add} if + {/y exch def + /x exch def + /xindex x 1 add 2 div bpside mul cvi def + /yindex y 1 add 2 div bpside mul cvi def + bstring yindex bwidth mul xindex 8 idiv add get + 1 7 xindex 8 mod sub bitshift and 0 ne + {/onbits onbits 1 add def 1} + {/offbits offbits 1 add def 0} + ifelse + } + setscreen + {} settransfer + offbits offbits onbits add div FMsetgray + /graymode false def + } bind def +/grayness { + FMsetgray + graymode not { + /graymode true def + orgxfer cvx settransfer + orgfreq organgle orgproc cvx setscreen + } if + } bind def + /HUE FMLOCAL + /SAT FMLOCAL + /BRIGHT FMLOCAL + /Colors FMLOCAL +FMPrintInColor + + { + /HUE 0 def + /SAT 0 def + /BRIGHT 0 def + % array of arrays Hue and Sat values for the separations [HUE BRIGHT] + /Colors + [[0 0 ] % black + [0 0 ] % white + [0.00 1.0] % red + [0.37 1.0] % green + [0.60 1.0] % blue + [0.50 1.0] % cyan + [0.83 1.0] % magenta + [0.16 1.0] % comment / yellow + ] def + + /BEGINBITMAPCOLOR { + BITMAPCOLOR} def + /BEGINBITMAPCOLORc { + BITMAPCOLORc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUECOLOR } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUECOLORc } def + /K { + Colors exch get dup + 0 get /HUE exch store + 1 get /BRIGHT exch store + HUE 0 eq BRIGHT 0 eq and + {1.0 SAT sub setgray} + {HUE SAT BRIGHT sethsbcolor} + ifelse + } def + /FMsetgray { + /SAT exch 1.0 exch sub store + HUE 0 eq BRIGHT 0 eq and + {1.0 SAT sub setgray} + {HUE SAT BRIGHT sethsbcolor} + ifelse + } bind def + } + + { + /BEGINBITMAPCOLOR { + BITMAPGRAY} def + /BEGINBITMAPCOLORc { + BITMAPGRAYc} def + /BEGINBITMAPTRUECOLOR { + BITMAPTRUEGRAY } def + /BEGINBITMAPTRUECOLORc { + BITMAPTRUEGRAYc } def + /FMsetgray {setgray} bind def + /K { + pop + } def + } +ifelse +/normalize { + transform round exch round exch itransform + } bind def +/dnormalize { + dtransform round exch round exch idtransform + } bind def +/lnormalize { + 0 dtransform exch cvi 2 idiv 2 mul 1 add exch idtransform pop + } bind def +/H { + lnormalize setlinewidth + } bind def +/Z { + setlinecap + } bind def + /fillvals FMLOCAL +/X { + fillvals exch get + dup type /stringtype eq + {8 1 setpattern} + {grayness} + ifelse + } bind def +/V { + gsave eofill grestore + } bind def +/N { + stroke + } bind def +/M {newpath moveto} bind def +/E {lineto} bind def +/D {curveto} bind def +/O {closepath} bind def + /n FMLOCAL +/L { + /n exch def + newpath + normalize + moveto + 2 1 n {pop normalize lineto} for + } bind def +/Y { + L + closepath + } bind def + /x1 FMLOCAL + /x2 FMLOCAL + /y1 FMLOCAL + /y2 FMLOCAL + /rad FMLOCAL +/R { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x1 y1 + x2 y1 + x2 y2 + x1 y2 + 4 Y + } bind def +/RR { + /rad exch def + normalize + /y2 exch def + /x2 exch def + normalize + /y1 exch def + /x1 exch def + newpath + x1 y1 rad add moveto + x1 y2 x2 y2 rad arcto + x2 y2 x2 y1 rad arcto + x2 y1 x1 y1 rad arcto + x1 y1 x1 y2 rad arcto + closepath + 16 {pop} repeat + } bind def +/C { + grestore + gsave + R + clip + } bind def + /FMpointsize FMLOCAL +/F { + FMfonts exch get + FMpointsize scalefont + setfont + } bind def +/Q { + /FMpointsize exch def + F + } bind def +/T { + moveto show + } bind def +/RF { + rotate + 0 ne {-1 1 scale} if + } bind def +/TF { + gsave + moveto + RF + show + grestore + } bind def +/P { + moveto + 0 32 3 2 roll widthshow + } bind def +/PF { + gsave + moveto + RF + 0 32 3 2 roll widthshow + grestore + } bind def +/S { + moveto + 0 exch ashow + } bind def +/SF { + gsave + moveto + RF + 0 exch ashow + grestore + } bind def +/B { + moveto + 0 32 4 2 roll 0 exch awidthshow + } bind def +/BF { + gsave + moveto + RF + 0 32 4 2 roll 0 exch awidthshow + grestore + } bind def +/G { + gsave + newpath + normalize translate 0.0 0.0 moveto + dnormalize scale + 0.0 0.0 1.0 5 3 roll arc + closepath fill + grestore + } bind def +/A { + gsave + savematrix + newpath + 2 index 2 div add exch 3 index 2 div sub exch + normalize 2 index 2 div sub exch 3 index 2 div add exch + translate + scale + 0.0 0.0 1.0 5 3 roll arc + restorematrix + stroke + grestore + } bind def + /x FMLOCAL + /y FMLOCAL + /w FMLOCAL + /h FMLOCAL + /xx FMLOCAL + /yy FMLOCAL + /ww FMLOCAL + /hh FMLOCAL + /FMsaveobject FMLOCAL + /FMoptop FMLOCAL + /FMdicttop FMLOCAL +/BEGINPRINTCODE { + /FMdicttop countdictstack 1 add def + /FMoptop count 4 sub def + /FMsaveobject save def + userdict begin + /showpage {} def + FMNORMALIZEGRAPHICS + 3 index neg 3 index neg translate + } bind def +/ENDPRINTCODE { + count -1 FMoptop {pop pop} for + countdictstack -1 FMdicttop {pop end} for + FMsaveobject restore + } bind def +/gn { + 0 + { 46 mul + cf read pop + 32 sub + dup 46 lt {exit} if + 46 sub add + } loop + add + } bind def + /str FMLOCAL +/cfs { + /str sl string def + 0 1 sl 1 sub {str exch val put} for + str def + } bind def +/ic [ + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0223 + 0 + {0 hx} {1 hx} {2 hx} {3 hx} {4 hx} {5 hx} {6 hx} {7 hx} {8 hx} {9 hx} + {10 hx} {11 hx} {12 hx} {13 hx} {14 hx} {15 hx} {16 hx} {17 hx} {18 hx} + {19 hx} {gn hx} {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12} + {13} {14} {15} {16} {17} {18} {19} {gn} {0 wh} {1 wh} {2 wh} {3 wh} + {4 wh} {5 wh} {6 wh} {7 wh} {8 wh} {9 wh} {10 wh} {11 wh} {12 wh} + {13 wh} {14 wh} {gn wh} {0 bl} {1 bl} {2 bl} {3 bl} {4 bl} {5 bl} {6 bl} + {7 bl} {8 bl} {9 bl} {10 bl} {11 bl} {12 bl} {13 bl} {14 bl} {gn bl} + {0 fl} {1 fl} {2 fl} {3 fl} {4 fl} {5 fl} {6 fl} {7 fl} {8 fl} {9 fl} + {10 fl} {11 fl} {12 fl} {13 fl} {14 fl} {gn fl} + ] def + /sl FMLOCAL + /val FMLOCAL + /ws FMLOCAL + /im FMLOCAL + /bs FMLOCAL + /cs FMLOCAL + /len FMLOCAL + /pos FMLOCAL +/ms { + /sl exch def + /val 255 def + /ws cfs + /im cfs + /val 0 def + /bs cfs + /cs cfs + } bind def +400 ms +/ip { + is + 0 + cf cs readline pop + { ic exch get exec + add + } forall + pop + + } bind def +/wh { + /len exch def + /pos exch def + ws 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/bl { + /len exch def + /pos exch def + bs 0 len getinterval im pos len getinterval copy pop + pos len + } bind def +/s1 1 string def +/fl { + /len exch def + /pos exch def + /val cf s1 readhexstring pop 0 get def + pos 1 pos len add 1 sub {im exch val put} for + pos len + } bind def +/hx { + 3 copy getinterval + cf exch readhexstring pop pop + } bind def + /h FMLOCAL + /w FMLOCAL + /d FMLOCAL + /lb FMLOCAL + /bitmapsave FMLOCAL + /is FMLOCAL + /cf FMLOCAL +/wbytes { + dup + 8 eq {pop} {1 eq {7 add 8 idiv} {3 add 4 idiv} ifelse} ifelse + } bind def +/BEGINBITMAPBWc { + 1 {} COMMONBITMAPc + } bind def +/BEGINBITMAPGRAYc { + 8 {} COMMONBITMAPc + } bind def +/BEGINBITMAP2BITc { + 2 {} COMMONBITMAPc + } bind def +/COMMONBITMAPc { + /r exch def + /d exch def + gsave + translate rotate scale /h exch def /w exch def + /lb w d wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + r + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {ip} image + bitmapsave restore + grestore + } bind def +/BEGINBITMAPBW { + 1 {} COMMONBITMAP + } bind def +/BEGINBITMAPGRAY { + 8 {} COMMONBITMAP + } bind def +/BEGINBITMAP2BIT { + 2 {} COMMONBITMAP + } bind def +/COMMONBITMAP { + /r exch def + /d exch def + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + r + /is w d wbytes string def + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {cf is readhexstring pop} image + bitmapsave restore + grestore + } bind def + /proc1 FMLOCAL + /proc2 FMLOCAL + /newproc FMLOCAL +/Fmcc { + /proc2 exch cvlit def + /proc1 exch cvlit def + /newproc proc1 length proc2 length add array def + newproc 0 proc1 putinterval + newproc proc1 length proc2 putinterval + newproc cvx +} bind def +/ngrayt 256 array def +/nredt 256 array def +/nbluet 256 array def +/ngreent 256 array def + /gryt FMLOCAL + /blut FMLOCAL + /grnt FMLOCAL + /redt FMLOCAL + /indx FMLOCAL + /cynu FMLOCAL + /magu FMLOCAL + /yelu FMLOCAL + /k FMLOCAL + /u FMLOCAL +/colorsetup { + currentcolortransfer + /gryt exch def + /blut exch def + /grnt exch def + /redt exch def + 0 1 255 { + /indx exch def + /cynu 1 red indx get 255 div sub def + /magu 1 green indx get 255 div sub def + /yelu 1 blue indx get 255 div sub def + /k cynu magu min yelu min def + /u k currentundercolorremoval exec def + nredt indx 1 0 cynu u sub max sub redt exec put + ngreent indx 1 0 magu u sub max sub grnt exec put + nbluet indx 1 0 yelu u sub max sub blut exec put + ngrayt indx 1 k currentblackgeneration exec sub gryt exec put + } for + {255 mul cvi nredt exch get} + {255 mul cvi ngreent exch get} + {255 mul cvi nbluet exch get} + {255 mul cvi ngrayt exch get} + setcolortransfer + {pop 0} setundercolorremoval + {} setblackgeneration + } bind def + /tran FMLOCAL +/fakecolorsetup { + /tran 256 string def + 0 1 255 {/indx exch def + tran indx + red indx get 77 mul + green indx get 151 mul + blue indx get 28 mul + add add 256 idiv put} for + currenttransfer + {255 mul cvi tran exch get 255.0 div} + exch Fmcc settransfer +} bind def +/BITMAPCOLOR { + /d 8 def + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + colorsetup + /is w d wbytes string def + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {cf is readhexstring pop} {is} {is} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPCOLORc { + /d 8 def + gsave + translate rotate scale /h exch def /w exch def + /lb w d wbytes def + sl lb lt {lb ms} if + /bitmapsave save def + colorsetup + /is im 0 lb getinterval def + ws 0 lb getinterval is copy pop + /cf currentfile def + w h d [w 0 0 h neg 0 h] + {ip} {is} {is} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLORc { + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + + /is w string def + + ws 0 w getinterval is copy pop + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + {ip} {gip} {bip} true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUECOLOR { + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + /is w string def + /gis w string def + /bis w string def + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + { cf is readhexstring pop } + { cf gis readhexstring pop } + { cf bis readhexstring pop } + true 3 colorimage + bitmapsave restore + grestore + } bind def +/BITMAPTRUEGRAYc { + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + + /is w string def + + ws 0 w getinterval is copy pop + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + {ip gip bip w gray} image + bitmapsave restore + grestore + } bind def +/ww FMLOCAL +/r FMLOCAL +/g FMLOCAL +/b FMLOCAL +/i FMLOCAL +/gray { + /ww exch def + /b exch def + /g exch def + /r exch def + 0 1 ww 1 sub { /i exch def r i get .299 mul g i get .587 mul + b i get .114 mul add add r i 3 -1 roll floor cvi put } for + r + } bind def +/BITMAPTRUEGRAY { + gsave + translate rotate scale /h exch def /w exch def + /bitmapsave save def + /is w string def + /gis w string def + /bis w string def + /cf currentfile def + w h 8 [w 0 0 h neg 0 h] + { cf is readhexstring pop + cf gis readhexstring pop + cf bis readhexstring pop w gray} image + bitmapsave restore + grestore + } bind def +/BITMAPGRAY { + 8 {fakecolorsetup} COMMONBITMAP + } bind def +/BITMAPGRAYc { + 8 {fakecolorsetup} COMMONBITMAPc + } bind def +/ENDBITMAP { + } bind def +end + /ALDsave FMLOCAL + /ALDmatrix matrix def ALDmatrix currentmatrix pop +/StartALD { + /ALDsave save def + savematrix + ALDmatrix setmatrix + } bind def +/InALD { + restorematrix + } bind def +/DoneALD { + ALDsave restore + } bind def +%%EndProlog +%%BeginSetup +(3.0) FMVERSION +1 1 612 792 0 1 12 FMDOCUMENT +0 0 /Times-Roman FMFONTDEFINE +1 0 /Times-Bold FMFONTDEFINE +2 0 /Courier FMFONTDEFINE +3 0 /Times-Italic FMFONTDEFINE +32 FMFILLS +0 0 FMFILL +1 .1 FMFILL +2 .3 FMFILL +3 .5 FMFILL +4 .7 FMFILL +5 .9 FMFILL +6 .97 FMFILL +7 1 FMFILL +8 <0f1e3c78f0e1c387> FMFILL +9 <0f87c3e1f0783c1e> FMFILL +10 <cccccccccccccccc> FMFILL +11 <ffff0000ffff0000> FMFILL +12 <8142241818244281> FMFILL +13 <03060c183060c081> FMFILL +14 <8040201008040201> FMFILL +16 1 FMFILL +17 .9 FMFILL +18 .7 FMFILL +19 .5 FMFILL +20 .3 FMFILL +21 .1 FMFILL +22 0.03 FMFILL +23 0 FMFILL +24 <f0e1c3870f1e3c78> FMFILL +25 <f0783c1e0f87c3e1> FMFILL +26 <3333333333333333> FMFILL +27 <0000ffff0000ffff> FMFILL +28 <7ebddbe7e7dbbd7e> FMFILL +29 <fcf9f3e7cf9f3f7e> FMFILL +30 <7fbfdfeff7fbfdfe> FMFILL +%%EndSetup +%%Page: "11" 11 +%%BeginPaperSize: Letter +%%EndPaperSize +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(11) 301 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +1 12 Q +0 X +(7. Fr) 56.69 727.31 T +(equently Asked Questions) 81.12 727.31 T +0 F +(7.1 Questions) 56.69 699.31 T +(1. How do I encode a sequence that can be) 82.49 672.31 T +(played by the Xing player?) 56.69 658.31 T +(2. I\325m using the Parallax XV) 82.49 644.31 T +(ideo card to) 220.34 644.31 T +(digitize; how do I MPEG-encode the resulting) 56.69 630.31 T +(data?) 56.69 616.31 T +(3. How do I convert the MPEG-encoder) 82.49 602.31 T +(YUV \336les into PPM \336les?) 56.69 588.31 T +(7.2 Answers) 56.69 546.31 T +-0.76 (1. The XING player samples video at 160x120 and) 56.69 518.31 P +(expands to output 320x240. This is where their) 56.69 504.31 T +(speed comes from. The player cannot buf) 56.69 490.31 T +(fer a) 255.32 490.31 T +(320x240 and thus had data overruns. The xing) 56.69 476.31 T +(player would \325) 56.69 462.31 T +(theoretically\325 handle 160x120 I) 126.42 462.31 T +(frames.) 56.69 448.31 T +(Thus, to encode, use P) 56.69 420.31 T +(A) 163.52 420.31 T +(TTERN I and 160x120) 170.85 420.31 T +(frames.) 56.69 406.31 T +(\050jboucher@\337ash.bu.edu\051) 56.69 392.31 T +(2. Use the type JMOVIE, or use the jmovie2jpeg) 56.69 364.31 T +(utility in the misc/ directory) 56.69 350.31 T +(.) 189.84 350.31 T +(3. Stanford\325) 56.69 322.31 T +(s CVv1.2.2.tar) 113.33 322.31 T +(.Z includes) 182.62 322.31 T +(cyuv2ppm.c.) 56.69 308.31 T +-0.2 (Which after you split the Y) 56.69 294.31 P +-0.2 (, U, and V components) 185.05 294.31 P +(out, works \336ne. \050curly@hsn.cftnet.com\051) 56.69 280.31 T +(This can be ftp\325d from) 56.69 252.31 T +2 F +(havefun.stanford.edu) 56.69 238.31 T +0 F +(, in the directory) 200.61 238.31 T +2 F +(/) 282.89 238.31 T +(pub/cv/) 56.69 224.31 T +0 F +(.) 107.07 224.31 T +314.36 54.99 552.76 735.31 R +7 X +V +FMENDPAGE +%%EndPage: "11" 10 +%%Page: "10" 10 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(10) 301 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +0 X +(Usage:) 85.04 728.64 T +2 F +(ppmtoeyuv < input.ppm > output.yuv) 85.04 715.64 T +0 F +0.33 (This takes as input a ppm file and outputs a subsam-) 85.04 689.64 P +(pled yuv file suitable for the encoder.) 56.69 678.64 T +0 12 Q +(6.2 jmovie2jpeg) 56.69 636.31 T +0 10 Q +(Usage:) 85.04 610.64 T +2 F +4.9 (jmovie2jpeg infile outfile start-) 85.04 597.64 P +(frame end-frame) 56.69 586.64 T +(infile) 85.04 560.64 T +0 F +( is a version 2 Parallax J_Movie) 121.02 560.64 T +2 F +(outfile) 85.04 547.64 T +0 F +( is a base file name for the output files) 127.02 547.64 T +2 F +5.44 (start-frame) 85.04 534.64 P +0 F +2.27 ( and) 151 534.64 P +2 F +5.44 (end-frame) 174.97 534.64 P +0 F +2.27 ( are the starting) 228.94 534.64 P +(and ending frame numbers) 56.69 523.64 T +1.39 (This takes as input a J_Movie and creates separate) 85.04 497.64 P +0.09 (JFIF compatible JPEG files with the names base<num>.jpg,) 56.69 486.64 P +(where base is outfile, and <num> are the frame numbers.) 56.69 475.64 T +9.6 (jmovie2jpeg was written by Jim Boucher) 85.04 462.64 P +(\050jboucher@\337ash.bu.edu\051.) 56.69 451.64 T +0 12 Q +(6.3 movieT) 56.69 424.31 T +(oV) 111.15 424.31 T +(id) 125.09 424.31 T +0 10 Q +(Usage:) 85.04 398.64 T +2 F +22.34 (movieToVid movieFile dataDir) 85.04 385.64 P +(indexDir srcHostName) 56.69 374.64 T +0 F +0.95 (This program is used to convert a Parallax J Movie) 85.04 348.64 P +0.58 (into a \322.vid\323 file, which is video only. vid files are used by) 56.69 337.64 P +(some of the programs described later.) 56.69 326.64 T +0.55 (See the README file in misc/mtv/ for more details) 85.04 313.64 P +(on usage.) 56.69 302.64 T +0.58 (movieToVid was written by Brian Smith \050bsmith@-) 85.04 289.64 P +(cs.berkeley.edu\051) 56.69 278.64 T +0 12 Q +(6.4 eyuvtojpeg) 56.69 236.31 T +0 10 Q +(Usage:) 85.04 210.64 T +2 F +(eyuvtojpeg infile outfile) 85.04 197.64 T +0 F +0.27 (This takes as input an encoder yuv file and outputs a) 85.04 171.64 P +(jpeg file. It uses cjpeg to do the compression.) 56.69 160.64 T +0 12 Q +(6.5 blockrun) 56.69 118.31 T +0 10 Q +(Usage:) 85.04 92.64 T +2 F +2.9 (blockrun command num_args firstnum) 85.04 79.64 P +(lastnum skip arg1 ... argn) 56.69 68.64 T +314.36 54.99 552.76 735.31 R +7 X +V +0 F +0 X +7.53 (This runs the given command \050which has) 342.71 715.64 P +2 F +0.32 (num_args) 314.36 704.64 P +0 F +0.13 ( args\051, with the args) 362.34 704.64 P +2 F +0.32 (arg1 ... argn) 444.61 704.64 P +0 F +0.13 (, where) 523.21 704.64 P +-0.04 (any \325=\325 character is replaced by a number from) 314.36 693.64 P +2 F +-0.09 (firstnum) 504.78 693.64 P +0 F +(to) 314.36 682.64 T +2 F +(lastnum) 324.64 682.64 T +0 F +( skipping by) 366.61 682.64 T +2 F +(skip) 418.54 682.64 T +0 F +(. For example:) 442.52 682.64 T +2 F +7.23 (blockrun eyuvtojpeg 2 13 19 3) 342.71 669.64 P +(flow=.yuv flow=.jpg) 314.36 658.64 T +0 F +(will run:) 342.71 632.64 T +2 F +(eyuvtojpeg flow13.yuv flow13.jpg) 342.71 606.64 T +(eyuvtojpeg flow16.yuv flow16.jpg) 342.71 593.64 T +(eyuvtojpeg flow19.yuv flow19.jpg) 342.71 580.64 T +0 12 Q +(6.6 vidtoppm) 314.36 553.31 T +0 10 Q +(Usage:) 342.71 527.64 T +2 F +10.05 (vidtoppm filename width height) 342.71 514.64 P +(start end outbase [quality]) 314.36 503.64 T +0 F +0.39 (This takes as input a .vid file of given) 342.71 477.64 P +2 F +0.94 (height) 499.45 477.64 P +0 F +0.39 ( and) 535.43 477.64 P +2 F +2.91 (width) 314.36 466.64 P +0 F +1.22 (, and turns them into a bunch of ppm files named) 344.35 466.64 P +2 F +(outbase) 314.36 455.64 T +0 F +(.N, where N is a number from) 356.34 455.64 T +2 F +(start) 478.74 455.64 T +0 F +( to) 508.73 455.64 T +2 F +(end) 521.5 455.64 T +0 F +(.) 539.49 455.64 T +0 12 Q +(6.7 vidtojpeg) 314.36 428.31 T +0 10 Q +(Usage:) 342.71 402.64 T +2 F +8.05 (vidtojpeg filename width height) 342.71 389.64 P +(start end outbase [quality]) 314.36 378.64 T +0 F +2.83 (This is the same as vidtoppm, except it outputs) 342.71 352.64 P +(JPEG files instead of PPM files.) 314.36 341.64 T +0 12 Q +(6.8 vidtoeyuv) 314.36 314.31 T +0 10 Q +(Usage:) 342.71 288.64 T +2 F +8.05 (vidtoeyuv filename width height) 342.71 275.64 P +(start nth outbase [quality]) 314.36 264.64 T +0 F +0.39 (This takes as input a .vid file of given) 342.71 238.64 P +2 F +0.94 (height) 499.45 238.64 P +0 F +0.39 ( and) 535.43 238.64 P +2 F +3.58 (width) 314.36 227.64 P +0 F +1.49 (, and turns them into a bunch of yuv files named) 344.35 227.64 P +2 F +2.87 (outbase) 314.36 216.64 P +0 F +1.2 (.N, where N is a number from) 356.34 216.64 P +2 F +2.87 (start) 487.12 216.64 P +0 F +1.2 ( to) 517.1 216.64 P +2 F +2.87 (end) 532.27 216.64 P +0 F +1.2 (,) 550.26 216.64 P +(skipping by) 314.36 205.64 T +2 F +(nth) 363.79 205.64 T +0 F +(.) 381.77 205.64 T +0 12 Q +(6.8 PBMPLUS) 314.36 176.31 T +0 10 Q +-0.04 (There is a very useful package called pbmplus avail-) 342.71 150.64 P +1.46 (able for ftp \050ee.utah.edu:/pbmplus for example\051. This has) 314.36 139.64 P +0.31 (conversions from TIFF, GIF, and many other common for-) 314.36 128.64 P +0.86 (mats to PPMs, which the encoder can read. You can even) 314.36 117.64 P +0.58 (keep the originals in their own format, and do conversions) 314.36 106.64 P +(via) 314.36 95.64 T +2 F +(INPUT_CONVERT.) 329.07 95.64 T +FMENDPAGE +%%EndPage: "10" 9 +%%Page: "9" 9 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(9) 303.5 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +0 X +0.08 (ating input files must work on the remote machine. Also the) 56.69 728.64 P +1.78 (USER_DATA and CDL_FILE files must be available on) 56.69 717.64 P +2.53 (the remote sites as specified in the parameter file. This) 56.69 706.64 P +(should be fixed in future versions.) 56.69 695.64 T +1 12 Q +(4. Performance) 56.69 668.31 T +0 10 Q +1.23 (Table seven shows a comparison of sequential per-) 85.04 641.64 P +(formance on different machine types.) 56.69 630.64 T +1.31 (Parallel performance is dependent not only on pro-) 85.04 422.64 P +1.87 (cessor performance, but network performance. If you are) 56.69 411.64 P +-0.21 (using a 10 Mb/s Ethernet, don\325t expect to get better than 4 or) 56.69 400.64 P +0.89 (5 frames per second -- no matter how fast your processors) 56.69 389.64 P +(are.) 56.69 378.64 T +2.5 (Parallel performance is also greatly dependent on) 85.04 365.64 P +1.16 (how big the input files are \050YUV is better than PPM, and) 56.69 354.64 P +0.81 (JPEG is better than both\051, and how big the output files are) 56.69 343.64 P +(\050better compression will lead to less I/O\051.) 56.69 332.64 T +1 12 Q +(5. Other Options) 56.69 305.31 T +0 10 Q +-0 (This section gives example of some more rarely used) 85.04 278.64 P +0.12 (options in the parameter \336le, such as customizing the Quan-) 56.69 267.64 P +(tization tables, or setting the aspect ratio.) 56.69 256.64 T +0 12 Q +(5.1 Custom Quantization T) 56.69 229.31 T +(ables \050parameter \336le\051) 186.45 229.31 T +0 10 Q +(You can specify your own custom quantization tables.) 56.69 206.64 T +-0.31 (Currently you can only do this once per MPEG file.) 56.69 194.64 P +-0.31 ( Y) 260.99 194.64 P +-0.31 (ou can) 269.39 194.64 P +-0.06 (specify both Intra- and Non-intra quantization tables. If you) 56.69 182.64 P +-0.44 (don\325) 56.69 170.64 P +-0.44 (t specify them, then the default tables are used \050c.f. page) 74.83 170.64 P +(D-16, D-17 of the standard\051.) 56.69 158.64 T +(Usage:) 85.04 141.64 T +2 F +(IQTABLE) 85.04 115.64 T +(table row 1) 85.04 102.64 T +(table row 2) 85.04 89.64 T +(...) 85.04 76.64 T +(table row 8) 85.04 63.64 T +100.63 478.31 253.7 484.31 C +0 0 612 792 C +0 10 Q +0 X +0 K +0.06 (a. Macroblocks per second; a) 118.63 471.64 P +1.5 (320x240 pixel image is 300) 118.63 459.64 P +(macroblocks per frame.) 118.63 447.64 T +1 12 Q +(T) 99.59 594.31 T +(able 7: Machine Comparison) 106.49 594.31 T +0 10 Q +(Machine) 121.41 572.64 T +(MPS) 203.66 572.64 T +0 8 Q +(a) 223.66 576.64 T +0 10 Q +(HP 9000/755) 120.13 554.64 T +(280) 207.94 554.64 T +(DEC 3000/400) 112.92 538.64 T +(247) 207.94 538.64 T +(HP 9000/750) 120.13 522.64 T +(191) 207.94 522.64 T +(Sparc 10) 137.91 506.64 T +(104) 207.94 506.64 T +(DEC 5000) 130.69 490.64 T +(68) 210.44 490.64 T +100.63 584.06 100.63 484.56 2 L +V +0.5 H +0 Z +N +177.16 584.56 177.16 484.06 2 L +V +N +253.7 584.06 253.7 484.56 2 L +V +N +100.38 584.31 253.95 584.31 2 L +V +N +100.88 565.56 253.45 565.56 2 L +V +N +100.88 563.06 253.45 563.06 2 L +V +N +100.38 548.31 253.95 548.31 2 L +V +N +100.38 532.31 253.95 532.31 2 L +V +N +100.38 516.31 253.95 516.31 2 L +V +N +100.38 500.31 253.95 500.31 2 L +V +N +100.38 484.31 253.95 484.31 2 L +V +N +314.36 54.99 552.76 735.31 R +7 X +V +0 X +0.96 (This specifies the intra-coding quantization table \050I) 342.71 715.64 P +0.01 (frames and I-blocks in P and B frames\051. Each) 314.36 704.64 P +2 F +0.03 (table row) 498.76 704.64 P +0 F +(is simply 8 integers, separated by tabs and/or spaces.) 314.36 693.64 T +(Usage:) 342.71 680.64 T +2 F +(NIQTABLE) 342.71 654.64 T +(table row 1) 342.71 641.64 T +(table row 2) 342.71 628.64 T +(...) 342.71 615.64 T +(table row 8) 342.71 602.64 T +0 F +4.63 (This specifies the non-intra-coding quantization) 342.71 576.64 P +(table \050difference vectors in P and B frames\051.) 314.36 565.64 T +0 12 Q +(5.2 Aspect Ratio \050parameter \336le\051) 314.36 538.31 T +0 10 Q +(Y) 340.16 512.64 T +(ou can specify the aspect ratio to be one of the) 346.37 512.64 T +(fourteen legal values as speci\336ed in the standard \050c.f.) 314.36 500.64 T +(Section 2.4.3.2\051. This sets the requested aspect ration for) 314.36 488.64 T +(playback.) 314.36 476.64 T +0 12 Q +(Usage:) 340.16 463.31 T +(ASPECT_RA) 340.16 449.31 T +(TIO \337oat) 406.13 449.31 T +2 10 Q +8.03 (float) 342.71 436.64 P +0 F +3.34 ( is one of {1.0, 0.6735, 0.7031, 0.7615,) 372.69 436.64 P +2.25 (0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695,) 314.36 425.64 P +(1.0950, 1.1575, 1.2015}.) 314.36 414.64 T +0 12 Q +(5.3 Frame Rate \050parameter \336le\051) 314.36 374.31 T +0 10 Q +-0 (You can specify the frame rate to be one of the eight) 342.71 348.64 P +1.97 (legal values \050c.f. Section 2.4.3.2\051. This is used by some) 314.36 337.64 P +(playback systems to gauge the playback rate.) 314.36 326.64 T +(Usage:) 342.71 313.64 T +2 F +(FRAME_RATE float) 342.71 300.64 T +4.91 (float) 342.71 287.64 P +0 F +2.05 ( is one of {23.976, 24, 25, 29.97, 30, 50,) 372.69 287.64 P +(59.94, 60}.) 314.36 276.64 T +0 12 Q +(5.4 Floating Point DCT \050command line\051) 314.36 249.31 T +0 10 Q +2.13 (The encoder normally uses a quick algorithm for) 342.71 236.64 P +2.06 (forward and reverse DCTs. However, in sequences with) 314.36 225.64 P +0.5 (many P frames, this can result in errors when decoded ref-) 314.36 214.64 P +0.4 (erence frames are used. To use the \050slow\051 double precision) 314.36 203.64 P +(accurate dcts, use the following flag:) 314.36 192.64 T +(Usage:) 342.71 179.64 T +(mpeg_encode -float_dct) 342.71 166.64 T +1 12 Q +(6. Other T) 314.36 139.31 T +(ools) 366.89 139.31 T +0 10 Q +(The misc/ directory contains several useful tools.) 314.36 112.64 T +0 12 Q +(6.1 ppmtoeyuv) 314.36 83.31 T +FMENDPAGE +%%EndPage: "9" 8 +%%Page: "8" 8 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(8) 303.5 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +0 X +(frame-to-I-frame scale.) 56.69 728.64 T +(Usage:) 85.04 715.64 T +2 F +(-bit_rate_info rate_file) 85.04 702.64 T +0 F +(This puts the bit rate info into the specified file) 85.04 689.64 T +(\050order of info, etc.\051) 85.04 676.64 T +1 12 Q +(3. Parallel Usage) 56.69 641.31 T +0 10 Q +1.03 (In parallel execution there are slave processes. You) 85.04 610.64 P +(can have those processes run nicely if you want.) 56.69 599.64 T +(Usage:) 85.04 586.64 T +2 F +(-nice) 85.04 573.64 T +0 F +3.56 (This makes all slave processes run nicely. This) 85.04 560.64 P +0.8 (means that interactive users take precedence, so they don\325t) 56.69 549.64 P +-0.2 (feel like they\325re running in molasses. If you want to be mean) 56.69 538.64 P +(to them, don\325t use this option. :-\051) 56.69 527.64 T +0 12 Q +(3.1 Architecture Overview) 56.69 500.31 T +0 10 Q +1.3 (Figure 1 shows a diagram of the system architecture. The) 56.69 474.64 P +-0.03 (slaves exist on the different slave machines which you spec-) 56.69 463.64 P +1.5 (ify \050see Section 3.2\051. The server processes all live on the) 56.69 452.64 P +(machine you run the encoder on.) 56.69 441.64 T +0 12 Q +(3.2 Specifying Slave Machines \050both\051) 56.69 412.31 T +0 10 Q +0.03 (You specify the slave machines in the parameter file.) 85.04 386.64 P +-0.2 (For each slave you must specify the username to use, as well) 56.69 375.64 P +0.06 (as the executable mpeg_encode program. If a slave does not) 56.69 364.64 P +1.52 (have NFS access, then it is REMOTE and you must also) 56.69 353.64 P +(specify where the parameter file is.) 56.69 342.64 T +(Usage:) 85.04 316.64 T +2 F +(PARALLEL) 85.04 303.64 T +(slave_specification) 85.04 290.64 T +(END_PARALLEL) 85.04 277.64 T +(slave_specification) 85.04 251.64 T +0 F +( can be either:) 198.98 251.64 T +2 F +(machine username executable) 85.04 238.64 T +0 F +(or) 85.04 225.64 T +2 F +2.9 (REMOTE machine username executable) 85.04 212.64 P +(param_file) 56.69 201.64 T +0 F +0.76 (You must have an account with the given username) 85.04 175.64 P +0.06 (on each machine, and you must place your machine/login in) 56.69 164.64 P +(the appropriate .rhosts files.) 56.69 153.64 T +1.59 (To make it easier to run experiments with varying) 85.04 127.64 P +1.35 (numbers of processors, there is a command-line argument) 56.69 116.64 P +(which limits the number of slave machines.) 56.69 105.64 T +(Usage:) 85.04 79.64 T +2 F +(-max_machines num_machines) 85.04 66.64 T +314.36 54.99 552.76 735.31 R +7 X +V +0 F +0 X +0.98 (This means that the encoder will use no more than) 342.71 728.64 P +2 F +(num_machines) 314.36 717.64 T +0 F +( machines as slaves.) 386.32 717.64 T +0 12 Q +(3.3 Remote Shell \050parameter \336le\051) 314.36 677.31 T +0 10 Q +0.98 (To run processes on the slave machines, mpeg_en-) 342.71 651.64 P +1.52 (code uses the remote shell command. On most machines) 314.36 640.64 P +-0.09 (this is the command) 314.36 629.64 P +2 F +-0.2 (rsh) 396.76 629.64 P +0 F +-0.09 (. On HP machines, however, rsh is) 414.75 629.64 P +0.39 (the restricted shell; on HP machines, the right command to) 314.36 618.64 P +(use is) 314.36 607.64 T +2 F +(remsh) 339.35 607.64 T +0 F +(, rather than) 369.33 607.64 T +2 F +(rsh) 419.84 607.64 T +0 F +(.) 437.83 607.64 T +(Usage:) 342.71 594.64 T +2 F +(RSH <rsh command>) 342.71 568.64 T +0 12 Q +(3.4 Scheduling Algorithms \050parameter \336le\051) 314.36 528.31 T +0 10 Q +0.87 (The encoder provides 3 different scheduling algorithms to) 314.36 502.64 P +(schedule which processors get which frames.) 314.36 491.64 T +2.03 (The first scheduling algorithm simply assigns N/P) 340.16 478.64 P +0.28 (frames to each processor, where N is the number of frames) 314.36 467.64 P +0.72 (and P is the number of processors. This has the advantage) 314.36 456.64 P +-0.01 (of minimal overhead, but only works well when all the pro-) 314.36 445.64 P +0.3 (cessors run at nearly the same speed. Also, since most pro-) 314.36 434.64 P +0.37 (cessors will finish at about the same time, you will have to) 314.36 423.64 P +1.41 (wait at the end while the Combine Server gathers all the) 314.36 412.64 P +(frame files together.) 314.36 401.64 T +(Usage:) 340.16 388.64 T +(PARALLEL_PERFECT) 340.16 375.64 T +3.6 (The second scheduling algorithm first assigns S) 340.16 349.64 P +-0.09 (frames to each processor. When a processor is finished, it is) 314.36 338.64 P +1.49 (assigned T seconds of work \050the scheduler estimates this) 314.36 327.64 P +1.97 (based on previous performance\051. S should be at least 3,) 314.36 316.64 P +0.37 (preferably at least 5 or 6, to insure a good estimate of each) 314.36 305.64 P +(processor\325s speed.) 314.36 294.64 T +(Usage:) 340.16 281.64 T +(PARALLEL_TEST_FRAMES S) 340.16 268.64 T +(PARALLEL_TIME_CHUNKS T) 340.16 255.64 T +0.79 (The third scheduling algorithm is probably the best.) 340.16 229.64 P +2.43 (It also first assigns S frames to each processor. Subse-) 314.36 218.64 P +3.44 (quently, however, whenever a processor finishes, it is) 314.36 207.64 P +1.1 (assigned enough work to keep it busy until almost every-) 314.36 196.64 P +2.04 (thing is done. Effectively, a processor is assigned many) 314.36 185.64 P +-0.06 (frames, and then fewer and fewer frames as more work gets) 314.36 174.64 P +2.92 (done. This insures good load balancing, while limiting) 314.36 163.64 P +(scheduling overhead.) 314.36 152.64 T +(Usage:) 340.16 139.64 T +(PARALLEL_TEST_FRAMES S) 340.16 126.64 T +(PARALLEL_CHUNK_TAPER) 340.16 113.64 T +0 12 Q +(3.5 Parallel problems \050parameter \336le\051) 314.36 86.31 T +0 10 Q +8.16 (There are some unsupported features using) 340.16 73.64 P +-0.18 (REMOTE to specify slaves: The \324command\324 form of gener-) 314.36 62.64 P +FMENDPAGE +%%EndPage: "8" 7 +%%Page: "7" 7 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(7) 303.5 34.15 T +56.69 54.99 297.64 477.36 R +7 X +V +0 X +(you can specify frame files to combine.) 56.69 470.69 T +1.11 (The parameter file may specify input frame files in) 85.04 457.69 P +0.94 (the same manner as normal input files -- except instead of) 56.69 446.69 P +7.11 (using INPUT_DIR, INPUT, and END_INPUT, use) 56.69 435.69 P +28.3 (FRAME_INPUT_DIR, FRAME_INPUT, and) 56.69 424.69 P +1.83 (FRAME_END_INPUT. If no input frame files are speci-) 56.69 413.69 P +0.16 (fied, then the default is to use the output file name with suf-) 56.69 402.69 P +(fix \322.frame.<frame_num>\323 starting from 0 as the input files.) 56.69 391.69 T +0 12 Q +(2.15 Stats and Other Options \050command line\051) 56.69 364.36 T +0 10 Q +0.43 (There are several options for printing or suppressing) 85.04 338.69 P +(useful information.) 56.69 327.69 T +0.75 (The encoder always prints \050to stdout\051 parameter file) 85.04 314.69 P +2.87 (information and statistics about how many I, P, and B) 56.69 303.69 P +0.8 (frames there were, and information about compression and) 56.69 292.69 P +2.31 (quality. You can send these statistics, in addition to the) 56.69 281.69 P +(screen, to a file.) 56.69 270.69 T +(Usage:) 85.04 257.69 T +2 F +( -stat stat_file) 110.83 244.69 T +0 F +2.56 (This appends the parameter file info and stats to) 85.04 231.69 P +2 F +(stat_file) 56.69 220.69 T +0 F +0.87 (Normally, the statistics do not include any informa-) 85.04 194.69 P +1.77 (tion about quality. This is because computing the quality) 56.69 183.69 P +2.02 (takes a little more time. If you wish to have the quality) 56.69 172.69 P +1.17 (included in the statistics, use the -snr command line argu-) 56.69 161.69 P +(ment.) 56.69 150.69 T +(Usage:) 85.04 137.69 T +2 F +(-snr) 85.04 124.69 T +0 F +1.78 (This prints the signal-to-noise ratio \050snr\051 and peak) 85.04 111.69 P +(snr.) 56.69 100.69 T +3.69 (An additional statistic measure is mean squared) 85.04 74.69 P +0.78 (error. If you wish to see the per-block mean squared error,) 56.69 63.69 P +314.36 54.99 552.76 477.36 R +7 X +V +0 X +(use the -mse command line flag \050sets -snr as a side effect\051.) 314.36 470.69 T +(Usage:) 342.71 457.69 T +2 F +(-mse) 342.71 444.69 T +0 F +(This prints the MSE for each block encoded) 342.71 431.69 T +1.02 (Another set of data which can be useful is a histo-) 342.71 418.69 P +0.44 (gram of the motion vectors. The encoder can keep track of) 314.36 407.69 P +-0.16 (P-frame motion vectors and forward and backward B-frame) 314.36 396.69 P +0.4 (motion vectors. The output is in the form of a matrix, each) 314.36 385.69 P +0.98 (entry corresponding to a motion vector in the search win-) 314.36 374.69 P +0.49 (dow. The center of the matrix represents \0500,0\051 motion vec-) 314.36 363.69 P +(tors.) 314.36 352.69 T +(Usage:) 342.71 339.69 T +2 F +(-mv_histogram) 342.71 326.69 T +0 F +1.47 (During normal execution, the encoder outputs two) 342.71 300.69 P +0.58 (kinds of information. It prints a single line for each frame,) 314.36 289.69 P +0.86 (summarizing block type and time info. It also prints, after) 314.36 278.69 P +-0.07 (each frame, an estimate of the remaining running time. You) 314.36 267.69 P +(can modify how often or if this information is to be shown.) 314.36 256.69 T +(Usage:) 342.71 243.69 T +2 F +( -quiet num) 342.71 230.69 T +( -no_frame_summary) 342.71 217.69 T +(-realquiet) 349.8 204.69 T +0 F +-0.13 (If) 342.71 191.69 P +2 F +-0.31 (num) 351.74 191.69 P +0 F +-0.13 ( is negative, the time estimate is never shown;) 369.73 191.69 P +1.94 (otherwise, it reports a time estimate no more often than) 314.36 180.69 P +1.22 (every) 314.36 169.69 P +2 F +2.92 (num) 340.27 169.69 P +0 F +1.22 ( seconds \050unless the time estimate rises, which) 358.26 169.69 P +1 (will happen near the beginning of the run\051. The default is) 314.36 158.69 P +2 F +(num) 314.36 147.69 T +0 F +( = 0, which means report after every frame.) 332.35 147.69 T +1.08 (If) 342.71 134.69 P +2 F +2.59 (-no_frame_summary) 352.94 134.69 P +0 F +1.08 ( is given, then informa-) 454.89 134.69 P +(tion about each frame is not printed.) 314.36 123.69 T +2 F +10.05 (-realquiet stops all printing,) 342.71 110.69 P +(other than error messages.) 314.36 99.69 T +0 F +1 (Another nice feature is that the encoder can output) 342.71 73.69 P +0.75 (the bit rate, on both a frame-to-frame scale, and also an I-) 314.36 62.69 P +385.51 518.46 470.55 575.15 R +7 X +V +0.5 H +0 Z +0 X +N +141.05 721.49 294.05 766.49 18 RR +7 X +V +0 X +N +1 18 Q +(Master Server) 165.05 738.43 T +102.05 623.49 181.05 660.49 R +7 X +V +0 X +N +(Slave) 121.05 637.49 T +452.05 625.49 531.05 662.49 R +7 X +V +0 X +N +(Slave) 471.05 639.49 T +333.05 624.49 412.05 661.49 R +7 X +V +0 X +N +(Slave) 352.05 638.49 T +218.05 623.49 297.05 660.49 R +7 X +V +0 X +N +(Slave) 237.05 637.49 T +147.47 523.06 300.47 568.06 18 RR +7 X +V +0 X +N +(Combine Server) 165.31 539.33 T +498.64 673.25 501.04 661.49 492.77 670.19 495.71 671.72 4 Y +V +472.44 709.73 470.04 721.49 478.31 712.79 475.37 711.26 4 Y +V +495.71 671.72 475.38 711.26 2 L +7 X +V +0 X +N +137.07 670.41 129.04 661.49 131.12 673.31 134.09 671.86 4 Y +V +149.02 710.57 157.04 719.49 154.97 707.67 151.99 709.12 4 Y +V +134.1 671.86 152 709.12 2 L +7 X +V +0 X +N +164.04 661.55 152.04 661.49 162.18 667.9 163.11 664.73 4 Y +V +344.03 719.43 356.03 719.49 345.89 713.08 344.96 716.26 4 Y +V +163.12 664.72 344.98 716.25 2 L +7 X +V +0 X +N +392.55 667.26 382.02 661.5 387.89 671.96 390.22 669.61 4 Y +V +430.5 714.73 441.02 720.49 435.15 710.03 432.82 712.38 4 Y +V +390.24 669.6 432.85 712.37 2 L +7 X +V +0 X +N +277.89 664.38 266.04 662.49 275.09 670.37 276.49 667.37 4 Y +V +377.19 717.6 389.04 719.49 379.98 711.61 378.59 714.61 4 Y +V +276.5 667.37 378.6 714.61 2 L +7 X +V +0 X +N +241.78 672.73 248.04 662.49 237.31 667.86 239.55 670.29 4 Y +V +192.3 709.25 186.04 719.49 196.78 714.12 194.54 711.69 4 Y +V +239.55 670.29 194.54 711.69 2 L +7 X +V +0 X +N +353.94 670.32 363.03 662.49 351.17 664.31 352.56 667.32 4 Y +V +245.13 712.66 236.04 720.49 247.9 718.67 246.52 715.67 4 Y +V +352.57 667.31 246.52 715.66 2 L +7 X +V +0 X +N +470.93 667.95 481.05 661.49 469.05 661.61 469.99 664.78 4 Y +V +287.16 714.03 277.05 720.49 289.05 720.37 288.1 717.2 4 Y +V +469.99 664.78 288.1 717.2 2 L +7 X +V +0 X +N +336.05 720.49 489.05 765.49 18 RR +7 X +V +0 X +N +(Decode Server) 360.05 737.43 T +134.71 613.56 130.39 624.76 139.99 617.55 137.35 615.56 4 Y +V +168.59 579.26 172.91 568.07 163.31 575.27 165.95 577.27 4 Y +V +137.35 615.56 165.96 577.26 2 L +7 X +V +0 X +N +234.18 617.55 243.77 624.76 239.45 613.56 236.82 615.56 4 Y +V +210.85 575.27 201.26 568.07 205.58 579.26 208.21 577.27 4 Y +V +236.82 615.56 208.22 577.26 2 L +7 X +V +0 X +N +352.39 622.81 364.23 624.77 355.23 616.83 353.81 619.82 4 Y +V +255.6 570.03 243.76 568.08 252.77 576.01 254.18 573.02 4 Y +V +353.83 619.81 254.2 573.01 2 L +7 X +V +0 X +N +465.63 624.68 477.63 624.76 467.5 618.33 466.56 621.51 4 Y +V +291.21 568.14 279.21 568.07 289.34 574.49 290.28 571.32 4 Y +V +466.57 621.51 290.28 571.31 2 L +7 X +V +0 X +N +393.94 616.24 385.49 624.76 397.17 622.01 395.55 619.12 4 Y +V +440.83 597.86 449.27 589.33 437.59 592.09 439.21 594.98 4 Y +V +395.57 619.11 439.23 594.97 2 L +7 X +V +0 X +N +281.34 617.08 272.12 624.76 284.01 623.14 282.67 620.11 4 Y +V +376.28 582.84 385.5 575.16 373.61 576.78 374.94 579.81 4 Y +V +282.68 620.1 374.96 579.8 2 L +7 X +V +0 X +N +168.9 618.38 158.74 624.76 170.74 624.73 169.82 621.56 4 Y +V +375.34 567.36 385.51 560.98 373.51 561 374.43 564.18 4 Y +V +169.82 621.55 374.43 564.18 2 L +7 X +V +0 X +N +312.01 543.5 300.47 546.8 312.01 550.11 312.01 546.8 4 Y +V +373.98 550.11 385.51 546.8 373.98 543.5 373.98 546.8 4 Y +V +312.01 546.8 373.98 546.8 2 L +7 X +V +0 X +N +302.9 498.61 259.93 498.61 2 L +V +1.14 H +N +1 12 Q +(Figure 1) 259.93 499.8 T +385.51 498.49 302.9 498.49 2 L +V +0.59 H +N +0 F +(: Network Model) 302.9 499.8 T +495.43 619 505.95 624.77 500.08 614.3 497.76 616.65 4 Y +V +473.96 588.02 463.44 582.25 469.3 592.72 471.63 590.37 4 Y +V +497.79 616.64 471.66 590.35 2 L +7 X +V +0.5 H +0 X +N +1 18 Q +(Disk) 410.52 530.49 T +7 X +90 450 42.52 14.17 428.03 575.15 G +0 X +90 450 42.52 14.17 428.03 575.15 A +7 X +180 270 42.94 21.26 428.45 521.28 G +2 Z +0 X +180 270 42.94 21.26 428.45 521.28 A +7 X +270 360 42.94 21.26 427.68 521.61 G +0 X +270 360 42.94 21.26 427.68 521.61 A +FMENDPAGE +%%EndPage: "7" 6 +%%Page: "6" 6 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(6) 303.5 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +0 X +3.03 (number\051. This field entry can be changed by adding a) 56.69 728.64 P +1.27 (USER_DATA parameter whose vale is the name of a file) 56.69 717.64 P +(continuing the data to add to the header.) 56.69 706.64 T +(Usage:) 85.04 693.64 T +(USER_DATA ./user_data.txt) 85.04 667.64 T +0 12 Q +(2.1) 56.69 640.31 T +(1 Compression Decision List \050CDL, also) 71.24 640.31 T +(Speci\336cs File \050parameter \336le\051\051) 56.69 626.31 T +0 10 Q +0.18 (If you want to be very exact in what is set during the) 85.04 599.64 P +1.71 (encoding, use CDL_FILE \050the older SPECIFICS_FILE is) 56.69 588.64 P +0.18 (supported as well\051 to point to a file describing the exact set-) 56.69 577.64 P +0.22 (tings wished for the encoding. The version 1.0 of CDL sup-) 56.69 566.64 P +(port has the following format:) 56.69 555.64 T +(version 1) 85.04 542.64 T +(frame FN T Q) 85.04 529.64 T +(slice SN Q) 85.04 516.64 T +(block BN Q | BN Q skip | BN Q bi fx fy bx by |) 85.04 503.64 T +(BN Q forw fx fy | BN Q back bx by) 109.7 490.64 T +3.51 (FN, SN, and BN signal which frame/slice/block) 85.04 477.64 P +1.64 (number the command applies to. Note that if you have a) 56.69 466.64 P +2.22 (block or slice command, must be proceeded by a frame) 56.69 455.64 P +0.63 (command for that frame. T sets the type of the frame \050I, P,) 56.69 444.64 P +-0.06 (B, or - to not set\051. Q sets the q-scale \0501-31 or +N -N for rela-) 56.69 433.64 P +0.17 (tive scaling, or 0 for no change\051. The detailed block specifi-) 56.69 422.64 P +2.81 (cations set the motion vectors \050in half-pixel units\051. See) 56.69 411.64 P +(specifications.c for more information.) 56.69 400.64 T +2.25 (Version 2 CDL files have relative Qscales, so \3222) 85.04 387.64 P +1.89 (\322means decrease the Qscale by 2, \3222\323 means increase it.) 56.69 376.64 P +(Unsigned numbers like \3224\323 set the Qscale \050to 4\051.) 56.69 365.64 T +(Usage:) 85.04 352.64 T +(CDL_FILE filename) 85.04 326.64 T +(CDL_DEFINES string) 85.04 313.64 T +3 (where filename contains the specifics, and string) 85.04 300.64 P +0.61 (\050optional\051 are defines to be passed to the C preprocessor to) 56.69 289.64 P +(use on the file \050-Db=block for example\051.) 56.69 278.64 T +0 12 Q +(2.12 Gamma Correction \050parameter \336le\051) 56.69 251.31 T +0 10 Q +-0.13 (If your movies are too light or too dark for your play-) 85.04 224.64 P +(back system, you can pre-gamma correct them.) 56.69 213.64 T +(Usage:) 85.04 200.64 T +2 F +(GAMMA gamma-val) 85.04 174.64 T +0 F +1.5 (gamma-corrects by raising each luminance fraction) 85.04 161.64 P +(to the power) 56.69 150.64 T +2 F +(gamma-val) 109.15 150.64 T +0 F +(\050a float\051) 169.12 150.64 T +0.18 (This works by converting the luminance \050brightness\051) 85.04 137.64 P +-0.17 (of the input image to a fraction zero to one, and then raises it) 56.69 126.64 P +-0.17 (to the power) 56.69 115.64 P +2 F +-0.4 (gamma-val) 108.65 115.64 P +0 F +-0.17 (. Thus values less than 1 brighten,) 162.62 115.64 P +2.36 (and greater than 1 dim. If your output device has good) 56.69 104.64 P +0.92 (brightness controls, it is better to control brightness at that) 56.69 93.64 P +(end.) 56.69 82.64 T +314.36 54.99 552.76 735.31 R +7 X +V +0 12 Q +0 X +(2.13 Encoding GOPs at a T) 314.36 727.31 T +(ime \050command line\051) 445.86 727.31 T +0 10 Q +2.65 (Instead of encoding an entire sequence, you can) 342.71 700.64 P +1.57 (encode a single GOP. GOPs can later be joined together) 314.36 689.64 P +(with the encoder to form an MPEG file.) 314.36 678.64 T +(Usage:) 342.71 665.64 T +2 F +(-gop num) 342.71 652.64 T +0 F +1.81 (This only encodes the numbered GOP \050which are) 342.71 639.64 P +(numbered beginning at 0.) 314.36 628.64 T +1.2 (The output file will be the normal output filename) 342.71 615.64 P +(with the suffix \322.gop.<gop_num>\323) 314.36 604.64 T +1.18 (GOP files can be joined at any time using the fol-) 342.71 578.64 P +(lowing command-line argument.) 314.36 567.64 T +(Usage:) 342.71 554.64 T +2 F +(-combine_gops) 342.71 541.64 T +0 F +2.05 (This causes the encoder to simply combine some) 342.71 528.64 P +0.52 (GOP files into a single MPEG stream. A sequence header/) 314.36 517.64 P +0.03 (ender are inserted. In this case, the parameter file need only) 314.36 506.64 P +0.18 (contain the YUV_SIZE value, an output file, and perhaps a) 314.36 495.64 P +0.21 (list of input GOP files. If no list of input GOP files is used,) 314.36 484.64 P +0.45 (then the encoder assumes you\325re using the same parameter) 314.36 473.64 P +-0.08 (file you used with the) 314.36 462.64 P +2 F +-0.19 (-gop) 403.08 462.64 P +0 F +-0.08 (option, and calculates the cor-) 432.88 462.64 P +0.52 (responding gop filenames itself. If this is not the case, you) 314.36 451.64 P +0.58 (can specify input GOP files in the same manner as normal) 314.36 440.64 P +0.44 (input files -- except instead of using INPUT_DIR, INPUT,) 314.36 429.64 P +1.79 (and END_INPUT, use GOP_INPUT_DIR, GOP_INPUT,) 314.36 418.64 P +1.38 (and GOP_END_INPUT. If no input GOP files are speci-) 314.36 407.64 P +-0.05 (fied, then the default is to use the output file name with suf-) 314.36 396.64 P +(fix \322.gop.<gop_num>\323 starting from 0 as the input files.) 314.36 385.64 T +4.1 (Thus, to summarize, unless you\325re mixing and) 342.71 372.64 P +0.2 (matching GOP files from different sources, you can simply) 314.36 361.64 P +1.37 (use the same parameter file for the) 314.36 350.64 P +2 F +3.28 (-gop) 464.63 350.64 P +0 F +1.37 ( and) 488.62 350.64 P +2 F +3.28 (-combi-) 510.78 350.64 P +(ne_gops) 314.36 339.64 T +0 F +( options.) 356.34 339.64 T +0 12 Q +(2.14 Encoding Frames at a T) 314.36 299.31 T +(ime \050command line\051) 452.51 299.31 T +0 10 Q +2.65 (Instead of encoding an entire sequence, you can) 342.71 273.64 P +0.34 (encode individual frames. These frames can later be joined) 314.36 262.64 P +(together to form an MPEG file.) 314.36 251.64 T +(Usage:) 342.71 238.64 T +(-frames first_frame last_frame) 342.71 225.64 T +2.37 (This causes the encoder to encode the numbered) 342.71 212.64 P +(frames in the given range, inclusive.) 314.36 201.64 T +0.89 (The output will be placed in separate files, one per) 342.71 188.64 P +0.21 (frame, with the filenames being the normal output file with) 314.36 177.64 P +(the suffix \322.frame.<frame num>\323) 314.36 166.64 T +(The frame files can later be combined as follows:) 342.71 140.64 T +(Usage:) 342.71 127.64 T +(-combine_frames) 342.71 114.64 T +2.05 (This causes the encoder to simply combine some) 342.71 101.64 P +2.21 (frames into a single MPEG stream. Sequence and GOP) 314.36 90.64 P +1.11 (headers are inserted appropriately. You can either use the) 314.36 79.64 P +1.39 (same parameter file for -frames and -combine_frames, or) 314.36 68.64 P +FMENDPAGE +%%EndPage: "6" 5 +%%Page: "5" 5 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(5) 303.5 34.15 T +72 72 297 732.47 R +7 X +V +2 F +0 X +(sflowg.07.yuv) 100.35 725.81 T +(sflowg.08.yuv) 100.35 712.81 T +(sflowg.09.yuv) 100.35 699.81 T +(sflowg.10.yuv) 100.35 686.81 T +0 F +1.37 (If there is no star, then the file name is simple) 100.35 660.81 P +0.99 (repeated the appropriate number of times \050[1-10] is 10) 72 649.81 P +(times\051.) 72 638.81 T +-0.18 (Commands can be used to dynamically create the) 100.35 625.81 P +(list of files, for example:) 72 614.81 T +2 F +(INPUT) 100.35 588.81 T +(\324ls July-*.ppm\324) 100.35 575.81 T +(\324cat file-list\324) 100.35 562.81 T +(END_INPUT) 100.35 549.81 T +0 F +1.41 (The command\050s\051 will be executed in the direc-) 100.35 523.81 P +0.44 (tory named by INPUT_DIR if it appears before INPUT) 72 512.81 P +2.09 (in the parameter file. Note that the encoder-provided) 72 501.81 P +(filling in of *\325s is not supported in this mode.) 72 490.81 T +0.36 (The encoder allows you to use other file formats) 100.35 477.81 P +1.61 (by providing an input conversion specifier. You must) 72 466.81 P +0.18 (describe how to convert the input format into one of the) 72 455.81 P +(base file types.) 72 444.81 T +2 F +(Usage:) 100.35 431.81 T +(INPUT_CONVERT conversion) 100.35 405.81 T +3.25 (conversion) 100.35 379.81 P +0 F +1.35 ( must be a multi-star expression.) 160.31 379.81 P +-0.16 (If) 72 368.81 P +2 F +-0.37 (conversion) 81 368.81 P +0 F +-0.16 ( is simply \324*\325, then no conversion takes) 140.97 368.81 P +0.92 (place. Otherwise, each of the file lines are replaced by) 72 357.81 P +0.3 (the conversion line with the file name wherever there is) 72 346.81 P +0.88 (a \324*\325. The conversion line must send the output to std-) 72 335.81 P +-0.12 (out. For example, suppose we have a bunch of GIF files.) 72 324.81 P +(Then we would do:) 72 313.81 T +2 F +(BASE_FILE_FORMAT) 100.35 300.81 T +( PPM) 196.29 300.81 T +(INPUT) 100.35 287.81 T +(pictures.*.gif [0-10]) 100.35 274.81 T +(END_INPUT) 100.35 261.81 T +(INPUT_CONVERT giftoppm *) 100.35 248.81 T +0 F +0.9 (Another example: Suppose we have separate Y,) 100.35 222.81 P +1.18 (U, and V files \050where the U and V have already been) 72 211.81 P +(subsampled\051. Then we might have:) 72 200.81 T +2 F +(BASE_FILE_FORMAT) 100.35 187.81 T +( YUV) 196.29 187.81 T +(INPUT) 100.35 174.81 T +(pictures.* [0-10]) 100.35 161.81 T +(END_INPUT) 100.35 148.81 T +(INPUT_CONVERT cat *.Y *.U *.V) 100.35 135.81 T +(YUV_FORMAT UCB) 100.35 122.81 T +0 F +0.68 (As you can see, the \322files\323 between) 100.35 109.81 P +2 F +1.63 (INPUT) 249.41 109.81 P +0 F +0.68 ( and) 279.39 109.81 P +2 F +2.41 (END_INPUT) 72 98.81 P +0 F +1 ( don\325t have to be files at all! This can be) 125.97 98.81 P +(very useful.) 72 87.81 T +315 72 540 732.47 R +7 X +V +0 X +(To read data from standard input, set:) 343.35 712.81 T +2 F +(INPUT_DIR stdin) 343.35 699.81 T +0 F +1.05 (Note that you cannot use the stdin option when) 343.35 686.81 P +0.07 (coding in parallel. \050Use GOPINPUTDIR or FRAMEIN-) 315 675.81 P +(PUTDIR if combining frames/GOPs.\051) 315 664.81 T +(The output file is specified by:) 343.35 638.81 T +2 F +(OUTPUT filename) 343.35 625.81 T +0 F +(for example:) 343.35 612.81 T +2 F +(OUTPUT /u/keving/mpg/flowers.mpg) 343.35 599.81 T +0 12 Q +(2.8 Original or Decoded \050parameter \336le\051) 315 559.47 T +0 10 Q +0.09 (The encoder can use either the original frames as) 343.35 532.81 P +3 (reference frames, or the decoded frames. Using the) 315 521.81 P +2.48 (decoded frames gives better playback quality, but is) 315 510.81 P +1.93 (slower and seems to give worse compression. It also) 315 499.81 P +0.63 (causes some complications with parallel encoding. \050see) 315 488.81 P +0.95 (the section on parallel encoding\051 One recommendation) 315 477.81 P +0.52 (is to use original, and lower the q-scale if the quality is) 315 466.81 P +(not good enough. Table six shows the trade-offs.) 315 455.81 T +(Usage:) 343.35 429.81 T +2 F +(REFERENCE_FRAME ORIGINAL) 343.35 403.81 T +0 12 Q +(2.9 Bit-rate Control \050parameter \336le\051) 315 272.47 T +0 10 Q +1.53 (The default encoding uses variable bit rate. To) 343.35 245.81 P +0.33 (limit the bit rate, the MPEG-2 Standard\325s algorithm has) 315 234.81 P +2.39 (been implemented \050suitably adjusted\051. There are two) 315 223.81 P +(parameters which must be set to use bit-rate control:) 315 212.81 T +2 F +(BUFFER_SIZE N \050in bits\051) 343.35 199.81 T +(BIT_RATE M \050in bytes/sec\051) 343.35 186.81 T +0 F +-0.09 (N sets the largest required buffer, M specifies the) 343.35 173.81 P +1 (continual rate. N is set in number of bits, the buffer is) 315 162.81 P +(actually in 16bit ints.) 315 151.81 T +0 12 Q +(2.10 Userdata \050parameter \336le\051) 315 124.47 T +0 10 Q +0.01 (An identification string is added by default to the) 343.35 97.81 P +2.96 (Sequence layer user-data field. It is \322UCB Encoder) 315 86.81 P +1.41 (Vers\323 \050where Vers is replaced by the encoder version) 315 75.81 P +1 12 Q +-0.15 (T) 315 380.47 P +-0.15 (able 6: Original or Decoded? \050Normalized\051) 321.9 380.47 P +0 10 Q +(Reference) 323.62 352.81 T +(Compress) 373.49 358.81 T +(ion) 387.1 346.81 T +(Speed) 429.46 352.81 T +(Quality) 486.21 358.81 T +(I/P/B) 490.65 346.81 T +(Decoded) 329.87 328.81 T +(1000) 383.49 328.81 T +(1000) 431.68 328.81 T +(1000/969/919) 473.44 328.81 T +(Original) 332.08 312.81 T +(885) 385.99 312.81 T +(1373) 431.68 312.81 T +(1000/912/884) 473.44 312.81 T +318.37 370.22 318.37 306.72 2 L +V +0.5 H +0 Z +N +369.39 370.72 369.39 306.22 2 L +V +N +417.58 370.72 417.58 306.22 2 L +V +N +465.77 370.72 465.77 306.22 2 L +V +N +536.63 370.22 536.63 306.72 2 L +V +N +318.12 370.47 536.88 370.47 2 L +V +N +318.62 339.72 536.38 339.72 2 L +V +N +318.62 337.22 536.38 337.22 2 L +V +N +318.12 322.47 536.88 322.47 2 L +V +N +318.12 306.47 536.88 306.47 2 L +V +N +FMENDPAGE +%%EndPage: "5" 4 +%%Page: "4" 4 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(4) 303.5 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +0 X +(A standard sequence is IBBPBBPBBPBBPB) 85.04 715.64 T +(Usage:) 85.04 702.64 T +2 F +(PATTERN) 85.04 676.64 T +( <IPB pattern>) 127.02 676.64 T +0 F +1.84 (Note that if the last frame in an encoding is a B-) 85.04 650.64 P +0.07 (frame, it will not be encoded \050since it has no future frame to) 56.69 639.64 P +1.81 (reference from\051. Pre-I patters like BBIBBP are legal, but) 56.69 628.64 P +0 (seem to have bugs, so watch out! To insure that every frame) 56.69 617.64 P +0.63 (is encoded, the encoder can force the last frame to be an I-) 56.69 606.64 P +(frame.) 56.69 595.64 T +(Usage:) 85.04 582.64 T +2 F +(FORCE_ENCODE_LAST_FRAME) 85.04 556.64 T +0 12 Q +(2.7 Specifying Input Files \050parameter \336le\051) 56.69 516.31 T +0 10 Q +0.03 (The encoder can accept five base types of input files:) 85.04 489.64 P +0.08 (PPM, PNM, JMOVIE, JPEG, and YUV. Note that PPM is a) 56.69 478.64 P +1.38 (subset of PNM; the PPM option is available because it is) 56.69 467.64 P +0.49 (faster to read if the files are known to be PPM. JMOVIE is) 56.69 456.64 P +0.19 (the format created by the Parallax video grabber. JPEGs are) 56.69 445.64 P +-0.06 (a standard image format. YUV formats are described below.) 56.69 434.64 P +0.98 (If you use YUV format, you must specify the pixel) 85.04 421.64 P +0.61 (size of the image in the parameter file and the YUV_FOR-) 56.69 410.64 P +(MAT.) 56.69 399.64 T +(Usage:) 85.04 386.64 T +2 F +(BASE_FILE_FORMAT format) 85.04 360.64 T +(YUV_SIZE widthxheight) 85.04 347.64 T +(YUV_FORMAT yuv_format) 85.04 334.64 T +0.1 (format) 85.04 308.64 P +0 F +0.04 ( is one of {) 121.02 308.64 P +2 F +0.1 (YUV, PPM, PNM, JMOVIE,) 165.4 308.64 P +(JPEG) 56.69 297.64 T +0 F +(}) 80.68 297.64 T +2 F +(width) 85.04 284.64 T +0 F +( and) 115.02 284.64 T +2 F +(height) 134.45 284.64 T +0 F +( are integers \050like 320x240\051) 170.43 284.64 T +2 F +5.81 (yuv_format) 85.04 271.64 P +0 F +2.42 (is one of) 156.81 271.64 P +2 F +5.81 ( {ABEKAS, EYUV,) 196.07 271.64 P +1.66 (PHILLIPS, UCB, {SPECIAL}},) 56.69 260.64 P +0 F +0.69 (where) 223.59 260.64 P +2 F +1.66 ( SPECIAL) 248 260.64 P +0 F +1.83 (is a specification of the pattern of Y, U, and V, such as) 56.69 249.64 P +2 F +-0.57 (UYVY) 56.69 238.64 P +0 F +-0.24 (for) 86.1 238.64 P +2 F +-0.57 ( ABEKAS. The pattern can be of any) 97.76 238.64 P +1.18 (length, or order, but must consist only) 56.69 227.64 P +0.15 (of Ys, Us, andVs, and must represent two) 56.69 216.64 P +3.18 (pixels of data \050thus YUVYUV for 4:4:4) 56.69 205.64 P +(source\051.) 56.69 194.64 T +0 F +1.73 (You must specify the directory in which the input) 85.04 168.64 P +-0.12 (files are located. You can use \324.\325 to specify the current direc-) 56.69 157.64 P +(tory.) 56.69 146.64 T +(Usage:) 85.04 133.64 T +(INPUT_DIR directory) 85.04 107.64 T +1.08 (You must also specify the names of the files them-) 85.04 81.64 P +1.11 (selves. You list them sequentially, one per line, in display) 56.69 70.64 P +2.12 (order. There are shortcuts, however, which allow you to) 56.69 59.64 P +314.36 54.99 552.76 735.31 R +7 X +V +0 X +(condense many files into one line.) 314.36 728.64 T +(Usage:) 342.71 715.64 T +2 F +(INPUT) 342.71 689.64 T +(file) 342.71 676.64 T +2 8 Q +(1) 366.7 674.14 T +2 10 Q +(file) 342.71 663.64 T +2 8 Q +(2) 366.7 661.14 T +2 10 Q +(...) 342.71 650.64 T +(file) 342.71 637.64 T +2 8 Q +(n) 366.7 635.14 T +2 10 Q +(END_INPUT) 342.71 624.64 T +8.17 (file) 342.71 598.64 P +2 8 Q +6.53 (i) 366.7 596.14 P +0 10 Q +3.4 ( can be either a file name, a single-star) 371.49 598.64 P +0.28 (expression followed by a bracketed expansion for star, or a) 314.36 587.64 P +0.28 (command to be executed. There are two types of bracketed) 314.36 576.64 P +(expansions. For example:) 314.36 565.64 T +2 F +(sflowg.*.yuv [0-10]) 342.71 539.64 T +0 F +(is expanded to:) 342.71 513.64 T +2 F +(sflowg.0.yuv) 342.71 487.64 T +(sflowg.1.yuv) 342.71 474.64 T +(sflowg.2.yuv) 342.71 461.64 T +(sflowg.3.yuv) 342.71 448.64 T +(sflowg.4.yuv) 342.71 435.64 T +(sflowg.5.yuv) 342.71 422.64 T +(sflowg.6.yuv) 342.71 409.64 T +(sflowg.7.yuv) 342.71 396.64 T +(sflowg.8.yuv) 342.71 383.64 T +(sflowg.9.yuv) 342.71 370.64 T +(sflowg.10.yuv) 342.71 357.64 T +(sflowg.*.yuv [0-10+3]) 342.71 331.64 T +0 F +(is expanded to:) 342.71 305.64 T +2 F +(sflowg.0.yuv) 342.71 279.64 T +(sflowg.3.yuv) 342.71 266.64 T +(sflowg.6.yuv) 342.71 253.64 T +(sflowg.9.yuv) 342.71 240.64 T +0 F +(Also, the encoder will pad with 0\325s if necessary:) 342.71 214.64 T +2 F +(sflowg.*.yuv [00-10]) 342.71 188.64 T +0 F +(is expanded to:) 342.71 162.64 T +2 F +(sflowg.00.yuv) 342.71 136.64 T +(sflowg.01.yuv) 342.71 123.64 T +(sflowg.02.yuv) 342.71 110.64 T +(sflowg.03.yuv) 342.71 97.64 T +(sflowg.04.yuv) 342.71 84.64 T +(sflowg.05.yuv) 342.71 71.64 T +(sflowg.06.yuv) 342.71 58.64 T +FMENDPAGE +%%EndPage: "4" 3 +%%Page: "3" 3 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(3) 303.5 34.15 T +56.69 54.99 297.64 735.31 R +7 X +V +0 X +1.31 (For some reason Simple seems to give better com-) 85.04 616.64 P +(pression, but it depends on the image sequence.) 56.69 605.64 T +(Usage:) 85.04 579.64 T +2 F +(PSEARCH_ALG ptechnique) 85.04 553.64 T +(BSEARCH_ALG btechnique) 85.04 540.64 T +0 F +0.87 (where) 85.04 514.64 P +2 F +2.08 (ptechnique) 112.82 514.64 P +0 F +0.87 (is one of {LOGARITHMIC,) 180.87 514.64 P +(SUBSAMPLE, TWOLEVEL, EXHAUSTIVE}) 56.69 503.64 T +3.14 (where) 85.04 490.64 P +2 F +7.54 (btechnique) 115.1 490.64 P +0 F +3.14 ( is one of {EXHAUSTIVE,) 175.07 490.64 P +(CROSS2, SIMPLE}) 56.69 479.64 T +0 12 Q +(2.3 GOP \050parameter \336le\051) 56.69 439.31 T +0 10 Q +1.94 (A Group of Pictures \050GOP\051 is a roughly indepen-) 85.04 412.64 P +3.02 (dently decodable sequence of frames. An MPEG video) 56.69 401.64 P +0 (stream is made of one or more GOPs. You may specify how) 56.69 390.64 P +0.8 (many frames each GOP should be. A GOP must start with) 56.69 379.64 P +0.2 (an I-frame, and the encoder will enforce that by taking your) 56.69 368.64 P +(number as the) 56.69 357.64 T +3 F +(minimum) 115.26 357.64 T +0 F +( number of frames in a GOP.) 152.46 357.64 T +(Usage:) 85.04 331.64 T +2 F +(GOP_SIZE) 85.04 305.64 T +( num) 133.01 305.64 T +0 F +(where) 85.04 292.64 T +2 F +(num) 111.96 292.64 T +0 F +( = the number of frames in a GOP) 129.95 292.64 T +0 12 Q +(2.4 Slice \050parameter \336le\051) 56.69 252.31 T +0 10 Q +-0.25 (A slice is an independently decodable unit in a frame.) 85.04 226.64 P +0.54 (It can be as small as one macroblock, or it can be as big as) 56.69 215.64 P +1.47 (the entire frame. Barring transmission error, adding slices) 56.69 204.64 P +0.55 (does not change quality or speed; the only effect is slightly) 56.69 193.64 P +-0.1 (worse compression. More slices are used for noisy transmis-) 56.69 182.64 P +2.81 (sion so that errors are more recoverable. Because most) 56.69 171.64 P +0.28 (transmission systems have more sophisticated error correct-) 56.69 160.64 P +(ing routines, we usually just use one slice per frame.) 56.69 149.64 T +(Usage:) 85.04 123.64 T +2 F +(SLICES_PER_FRAME) 85.04 97.64 T +( num) 180.99 97.64 T +0 F +(where) 85.04 84.64 T +2 F +(num) 111.96 84.64 T +0 F +( is the number of slices in a frame) 129.95 84.64 T +2.31 (Note: Some MPEG playback systems require that) 85.04 58.64 P +1 12 Q +(T) 76.29 727.31 T +(able 4: B-frame Motion V) 83.18 727.31 T +(ector Sear) 213.99 727.31 T +(ch) 266.05 727.31 T +(\050Normalized\051) 143.19 713.31 T +0 10 Q +(T) 84.14 691.64 T +(echnique) 89.54 691.64 T +(Compression) 139.45 691.64 T +(Speed) 204.64 691.64 T +(Quality) 242.96 691.64 T +(Exhaustive) 86.23 673.64 T +(1000) 155.83 673.64 T +(?) 214.63 673.64 T +(1000) 247.96 673.64 T +(Cross2) 102.88 657.64 T +(975) 158.33 657.64 T +(1000) 206.86 657.64 T +(996) 250.46 657.64 T +(Simple) 102.32 641.64 T +(938) 158.33 641.64 T +(1765) 206.86 641.64 T +(991) 250.46 641.64 T +75.12 703.06 75.12 635.56 2 L +V +0.5 H +0 Z +N +134.65 703.56 134.65 635.06 2 L +V +N +197.01 703.56 197.01 635.06 2 L +V +N +236.69 703.56 236.69 635.06 2 L +V +N +279.21 703.06 279.21 635.56 2 L +V +N +74.87 703.31 279.46 703.31 2 L +V +N +75.37 684.56 278.96 684.56 2 L +V +N +75.37 682.06 278.96 682.06 2 L +V +N +74.87 667.31 279.46 667.31 2 L +V +N +74.87 651.31 279.46 651.31 2 L +V +N +74.87 635.31 279.46 635.31 2 L +V +N +314.36 54.99 552.76 735.31 R +7 X +V +0 X +1.26 (each slice must consist of whole rows of macroblocks. If) 314.36 728.64 P +0.55 (this is the case, then if the height of the image is H pixels,) 314.36 717.64 P +1.97 (then you should set the SLICES_PER_FRAME to some) 314.36 706.64 P +0.32 (number which divides H/16. For example, if H = 240, then) 314.36 695.64 P +0.82 (you should only use SLICES_PER_FRAME values of 15,) 314.36 684.64 P +(5, 3, or 1.) 314.36 673.64 T +0.3 (Note to the note: these MPEG playback systems are) 342.71 660.64 P +1.07 (really at fault, since the MPEG standard says this doesn\325t) 314.36 649.64 P +(have to be so.) 314.36 638.64 T +0 12 Q +(2.5 Search W) 314.36 611.31 T +(indow \050parameter \336le\051) 378.83 611.31 T +0 10 Q +0.65 (The search window is the window in which motion) 342.71 585.64 P +0.47 (vectors are searched for. The window is a square. You can) 314.36 574.64 P +1.22 (specify the size of the square, and whether to allow half-) 314.36 563.64 P +(pixel motion vectors or not.) 314.36 552.64 T +(Usage:) 342.71 526.64 T +2 F +(PIXEL) 342.71 500.64 T +( <FULL or HALF>) 372.69 500.64 T +(RANGE num [numB]) 342.71 487.64 T +-0.54 (HALF) 342.71 461.64 P +0 F +-0.22 ( means that half-pixel vectors are allowed. The) 366.7 461.64 P +0.19 (search window is +/-) 314.36 450.64 P +2 F +0.47 (num) 401.27 450.64 P +0 F +0.19 ( pixels in the X and Y directions.) 419.26 450.64 P +-0.02 (It is usually important that you use) 314.36 439.64 P +2 F +-0.05 (HALF) 455.54 439.64 P +0 F +-0.02 (, because it results) 479.53 439.64 P +2.12 (in both better quality and better compression. It is only) 314.36 428.64 P +(undesirable for computer-generated images.) 314.36 417.64 T +2 F +-0.25 (num) 342.71 404.64 P +0 F +-0.1 ( should probably be set to at least 8 or 10 pixels.) 360.7 404.64 P +2.35 (This number depends on the image. Using much larger) 314.36 393.64 P +0.68 (numbers such as 20 or 30 doesn\325t seem to help much, and) 314.36 382.64 P +0.02 (increases the CPU cost drastically. The optional numB is in) 314.36 371.64 P +2.67 (case you wish to specify different ranges for predicted) 314.36 360.64 P +3.37 (frames \050P-frames, num\051, and Bi-directional frames \050B-) 314.36 349.64 P +0.31 (frames, numB\051. B-frame limits are optional as indicated by) 314.36 338.64 P +-0 (the braces above \050so \322RANGE 10 6\323 is a valid command as) 314.36 327.64 P +(is \322RANGE 9\323\051.) 314.36 316.64 T +0 12 Q +(2.6 IPB Pattern \050parameter \336le\051) 314.36 276.31 T +0 10 Q +2.24 (You can set the sequence of I, P, and B-frames.) 342.71 249.64 P +0.45 (Later versions will allow you to do more than set a repeat-) 314.36 238.64 P +2.49 (ing IPB pattern. The pattern affects speed, quality, and) 314.36 227.64 P +(compression. Table five shows some of the trade-offs.) 314.36 216.64 T +(\050this is given a certain Q-scale\051) 342.71 59.64 T +1 12 Q +(T) 337.17 193.31 T +(able 5: Comparison of I/P/B-Frames) 344.06 193.31 T +(\050Normalized\051) 399.59 179.31 T +0 F +(Frame) 331.84 156.31 T +(T) 335.26 142.31 T +(ype) 341.74 142.31 T +(Compress) 384.37 156.31 T +(ion) 400.7 142.31 T +(Speed) 451.3 149.31 T +(Quality) 505.57 149.31 T +(I-frames) 334.94 122.31 T +(1000) 396.36 122.31 T +(1000) 453.96 122.31 T +(1000) 511.57 122.31 T +(P-frames) 332.26 104.31 T +(409) 399.36 104.31 T +(601) 456.96 104.31 T +(969) 514.56 104.31 T +(B-frames) 330.93 86.31 T +(72) 402.36 86.31 T +(260) 456.96 86.31 T +(919) 514.56 86.31 T +314.76 169.06 314.76 79.56 2 L +V +N +379.56 169.56 379.56 79.06 2 L +V +N +437.16 169.56 437.16 79.06 2 L +V +N +494.76 169.56 494.76 79.06 2 L +V +N +552.36 169.06 552.36 79.56 2 L +V +N +314.51 169.31 552.61 169.31 2 L +V +N +315.01 134.56 552.11 134.56 2 L +V +N +315.01 132.06 552.11 132.06 2 L +V +N +314.51 115.31 552.61 115.31 2 L +V +N +314.51 97.31 552.61 97.31 2 L +V +N +314.51 79.31 552.61 79.31 2 L +V +N +FMENDPAGE +%%EndPage: "3" 2 +%%Page: "2" 2 +612 792 0 FMBEGINPAGE +57.97 26.65 554.03 40.82 R +7 X +0 K +V +0 10 Q +0 X +(2) 303.5 34.15 T +72 72 297 720 R +7 X +V +0 X +2.84 (Here is a description of the different command-line) 72 700.33 P +0.03 (options available and parameter-file options available in) 72 689.33 P +2.37 (sequential \050one-machine\051 encoding. You should defi-) 72 678.33 P +3.43 (nitely read sections 2.1-2.9. The other sections are) 72 667.33 P +(optional.) 72 656.33 T +0.21 (In the following, whenever a space in the parameter file) 72 630.33 P +4.29 (appears, it can be represented by any amount of) 72 619.33 P +(whitespace \050tabs or spaces\051.) 72 608.33 T +0 12 Q +(2.1 Q-Scale \050parameter \336le\051) 72 581 T +0 10 Q +1.78 (The quantization scale values \050Q-Scale\051 give a) 100.35 554.33 P +1.37 (trade-off between quality and compression. Using dif-) 72 543.33 P +-0.16 (ferent Q-Scale values has very little effect on speed. The) 72 532.33 P +1.74 (Q-Scale values can be set separately for I, P, and B-) 72 521.33 P +(frames.) 72 510.33 T +(Usage:) 100.35 484.33 T +2 F +(IQ-Scale) 126.21 471.33 T +( num) 174.18 471.33 T +(PQ-Scale num) 125.5 458.33 T +(BQ-Scale num) 126.21 445.33 T +0 F +(num in all three cases is a number from 1 to 31.) 100.35 432.33 T +3.47 (Larger numbers give better compression, but) 100.35 406.33 P +0.3 (worse quality. In the following, the quality numbers are) 72 395.33 P +(peak signal-to-noise ratio, defined as:) 72 384.33 T +(where MSE is the mean squared error.) 100.35 332.18 T +0.12 (Tables one and two show the Q-scale vs. Quality) 100.35 306.18 P +(relationship for the flower-garden sequence.) 72 295.18 T +1.84 (Note that when rate-control \050Section 2.9\051 is in) 100.35 282.18 P +0.19 (use, the rate control mechanism will change the Q-scale) 72 271.18 P +1.37 (throughout the blocks of the frame, so these specified) 72 260.18 P +(values are merely starting points.) 72 249.18 T +1 12 Q +(T) 95.77 212.85 T +(able 1: Q-Scale vs. Quality \050SNR\051) 102.66 212.85 T +0 10 Q +(Q-Scale) 91.87 191.18 T +(I-Frames) 140.95 191.18 T +(P-Frames) 190.86 191.18 T +(B-Frames) 241.33 191.18 T +(1) 124.48 173.18 T +(43.2) 150.24 173.18 T +(46.3) 201.27 173.18 T +(46.5) 252.29 173.18 T +(6) 124.48 157.18 T +(32.6) 150.24 157.18 T +(34.6) 201.27 157.18 T +(34.3) 252.29 157.18 T +(1) 119.85 141.18 T +(1) 124.48 141.18 T +(28.6) 150.24 141.18 T +(29.5) 201.27 141.18 T +(30.0) 252.29 141.18 T +(16) 119.48 125.18 T +(26.3) 150.24 125.18 T +(26.8) 201.27 125.18 T +(28.6) 252.29 125.18 T +(21) 119.48 109.18 T +(24.7) 150.24 109.18 T +(25.0) 201.27 109.18 T +(27.9) 252.29 109.18 T +(26) 119.48 93.18 T +(23.5) 150.24 93.18 T +(23.9) 201.27 93.18 T +(27.5) 252.29 93.18 T +82.45 202.6 82.45 87.1 2 L +V +0.5 H +0 Z +N +133.48 203.1 133.48 86.6 2 L +V +N +184.5 203.1 184.5 86.6 2 L +V +N +235.52 203.1 235.52 86.6 2 L +V +N +286.55 202.6 286.55 87.1 2 L +V +N +82.2 202.85 286.8 202.85 2 L +V +N +82.7 184.1 286.3 184.1 2 L +V +N +82.7 181.6 286.3 181.6 2 L +V +N +82.2 166.85 286.8 166.85 2 L +V +N +82.2 150.85 286.8 150.85 2 L +V +N +82.2 134.85 286.8 134.85 2 L +V +N +82.2 118.85 286.8 118.85 2 L +V +N +82.2 102.85 286.8 102.85 2 L +V +N +82.2 86.85 286.8 86.85 2 L +V +N +72 72 297 720 C +72 341.85 297 381 C +0 12 Q +0 X +0 K +(2) 148.86 360.39 T +(0) 154.85 360.39 T +3 F +(l) 161.56 360.39 T +(o) 165.6 360.39 T +(g) 172.3 360.39 T +0 9 Q +(1) 178.76 356.63 T +(0) 183.25 356.63 T +0 12 Q +(2) 196.32 367.58 T +(5) 202.32 367.58 T +(5) 208.31 367.58 T +3 F +(M) 196.45 349.78 T +(S) 207.15 349.78 T +(E) 213.85 349.78 T +221.18 360.98 196.45 360.98 2 L +0.33 H +0 Z +N +196.45 360.98 193.45 347.78 2 L +N +193.45 347.78 191.45 351.58 2 L +N +191.45 351.58 190.45 349.68 2 L +N +189.45 362.98 220.93 362.98 2 L +N +72 72 297 720 C +0 0 612 792 C +315 72 540 720 R +7 X +0 K +V +0 12 Q +0 X +(2.2 Search T) 315 471 T +(echniques \050parameter \336le\051) 375.11 471 T +0 10 Q +0.77 (There are several different motion vector search) 343.35 445.33 P +2.44 (techniques available for both P-frame search and B-) 315 434.33 P +0.54 (frame search. Using different search techniques present) 315 423.33 P +-0.04 (little difference in quality, but a large difference in com-) 315 412.33 P +(pression and speed.) 315 401.33 T +0.26 (There are 4 types of P-frame search: Exhaustive,) 343.35 388.33 P +(TwoLevel, SubSample, and Logarithmic.) 315 377.33 T +0.1 (There are 3 types of B-frame search: Exhaustive,) 343.35 364.33 P +(Cross2, and Simple.) 315 353.33 T +1.53 (The suggested search techniques are TwoLevel) 343.35 340.33 P +2.17 (and Logarithmic for P-frame search, and Cross2 and) 315 329.33 P +0.68 (Simple for B-frame search. Tables three and four com-) 315 318.33 P +(pare the different search methods:) 315 307.33 T +318.37 170 536.63 176 C +0 0 612 792 C +0 10 Q +0 X +0 K +(a. Smaller numbers mean better compression) 336.37 163.33 T +(b. Larger numbers mean faster execution) 336.37 151.33 T +(c. Larger numbers mean better quality) 336.37 139.33 T +(31) 362.48 672.33 T +(22.6) 393.24 672.33 T +(23.0) 444.27 672.33 T +(27.3) 495.29 672.33 T +1 12 Q +(T) 342.04 646 T +(able 2: Q-Scale vs. Compr) 348.94 646 T +(ession) 482.3 646 T +0 10 Q +(Q-Scale) 334.87 624.33 T +(I-Frames) 383.95 624.33 T +(P-Frames) 433.86 624.33 T +(B-Frames) 484.33 624.33 T +(1) 367.48 606.33 T +(2:1) 395.6 606.33 T +(2:1) 446.62 606.33 T +(2:1) 497.65 606.33 T +(6) 367.48 590.33 T +(7) 399.49 590.33 T +(10) 448.01 590.33 T +(15) 499.04 590.33 T +(1) 362.85 574.33 T +(1) 367.48 574.33 T +(1) 397.18 574.33 T +(1) 401.8 574.33 T +(18) 448.01 574.33 T +(43) 499.04 574.33 T +(16) 362.48 558.33 T +(15) 396.99 558.33 T +(29) 448.01 558.33 T +(97) 499.04 558.33 T +(21) 362.48 542.33 T +(19) 396.99 542.33 T +(41) 448.01 542.33 T +(173) 496.54 542.33 T +(26) 362.48 526.33 T +(24) 396.99 526.33 T +(56) 448.01 526.33 T +(256) 496.54 526.33 T +(31) 362.48 510.33 T +(28) 396.99 510.33 T +(73) 448.01 510.33 T +(330) 496.54 510.33 T +1 12 Q +(T) 326.96 284 T +(able 3: P-frame Motion V) 333.86 284 T +(ector Sear) 463.98 284 T +(ch) 516.05 284 T +(\050Normalized\051) 393.53 270 T +0 10 Q +(T) 327.39 248.33 T +(echnique) 332.79 248.33 T +(Compression) 382.34 248.33 T +0 8 Q +(a) 435.09 252.33 T +0 10 Q +(Speed) 454.39 248.33 T +0 8 Q +(b) 478.82 252.33 T +0 10 Q +(Quality) 498.61 248.33 T +0 8 Q +(c) 528.59 252.33 T +0 10 Q +(Exhaustive) 329.48 230.33 T +(1000) 400.5 230.33 T +(1000) 458.61 230.33 T +(1000) 505.38 230.33 T +(SubSample) 328.36 214.33 T +(1008) 400.5 214.33 T +(2456) 458.61 214.33 T +(1000) 505.38 214.33 T +(T) 333.52 198.33 T +(woLevel) 338.92 198.33 T +(1009) 400.5 198.33 T +(3237) 458.61 198.33 T +(1000) 505.38 198.33 T +(Logarithmic) 324.48 182.33 T +(1085) 400.5 182.33 T +(8229) 458.61 182.33 T +(998) 507.88 182.33 T +1 12 Q +(T) 338.77 712 T +(able 1: Q-Scale vs. Quality \050SNR\051) 345.66 712 T +0 10 Q +(Q-Scale) 334.87 690.33 T +(I-Frames) 383.95 690.33 T +(P-Frames) 433.86 690.33 T +(B-Frames) 484.33 690.33 T +325.45 701.75 325.45 666.25 2 L +V +0.5 H +0 Z +N +376.48 702.25 376.48 665.75 2 L +V +N +427.5 702.25 427.5 665.75 2 L +V +N +478.52 702.25 478.52 665.75 2 L +V +N +529.55 701.75 529.55 666.25 2 L +V +N +325.2 702 529.8 702 2 L +V +N +325.7 683.25 529.3 683.25 2 L +V +N +325.7 680.75 529.3 680.75 2 L +V +N +325.2 666 529.8 666 2 L +V +N +325.45 635.75 325.45 504.25 2 L +V +N +376.48 636.25 376.48 503.75 2 L +V +N +427.5 636.25 427.5 503.75 2 L +V +N +478.52 636.25 478.52 503.75 2 L +V +N +529.55 635.75 529.55 504.25 2 L +V +N +325.2 636 529.8 636 2 L +V +N +325.7 617.25 529.3 617.25 2 L +V +N +325.7 614.75 529.3 614.75 2 L +V +N +325.2 600 529.8 600 2 L +V +N +325.2 584 529.8 584 2 L +V +N +325.2 568 529.8 568 2 L +V +N +325.2 552 529.8 552 2 L +V +N +325.2 536 529.8 536 2 L +V +N +325.2 520 529.8 520 2 L +V +N +325.2 504 529.8 504 2 L +V +N +318.37 259.75 318.37 176.25 2 L +V +N +377.89 260.25 377.89 175.75 2 L +V +N +443.09 260.25 443.09 175.75 2 L +V +N +494.11 260.25 494.11 175.75 2 L +V +N +536.63 259.75 536.63 176.25 2 L +V +N +318.12 260 536.88 260 2 L +V +N +318.62 241.25 536.38 241.25 2 L +V +N +318.62 238.75 536.38 238.75 2 L +V +N +318.12 224 536.88 224 2 L +V +N +318.12 208 536.88 208 2 L +V +N +318.12 192 536.88 192 2 L +V +N +318.12 176 536.88 176 2 L +V +N +FMENDPAGE +%%EndPage: "2" 1 +%%Page: "1" 1 +612 792 0 FMBEGINPAGE +56.69 111.69 297.64 565.23 R +7 X +0 K +V +1 12 Q +0 X +(Contents) 56.69 557.23 T +0 10 Q +(0. Contacts/History) 56.69 539.56 T +(1. Installation) 56.69 526.56 T +(2. Sequential Usage) 56.69 513.56 T +(2.1 Q-Scale) 85.04 500.56 T +(2.2 Search Techniques) 85.04 487.56 T +(2.3 GOP) 85.04 474.56 T +(2.4 Slices) 85.04 461.56 T +(2.5) 85.04 448.56 T +( Search window) 97.53 448.56 T +(2.6 IPB pattern) 85.04 435.56 T +(2.7 Specifying Input Files) 85.04 422.56 T +(2.8) 85.04 409.56 T +( Original or Decoded) 97.53 409.56 T +(2.9 Bit-rate Control) 85.04 396.56 T +(2.10 User-data) 85.04 383.56 T +(2.11 Compression Decision List \050CDL\051) 85.04 370.56 T +(2.12 Gamma Correction) 85.04 357.56 T +(2.13 Encoding GOPs at a time) 85.04 344.56 T +(2.14) 85.04 331.56 T +( Encoding Frames at a time) 102.53 331.56 T +(2.15) 85.04 318.56 T +( Stats and other info) 102.53 318.56 T +(3. Parallel Usage) 56.69 305.56 T +(3.1) 85.04 292.56 T +( Architecture) 97.53 292.56 T +(3.2 Specifying slave machines) 85.04 279.56 T +(3.3) 85.04 266.56 T +( Remote Shell) 97.53 266.56 T +(3.4 Scheduling Algorithms) 85.04 253.56 T +(3.5 Parallel Problems) 85.04 240.56 T +0 12 Q +(4. Performance) 56.69 226.23 T +0 10 Q +(5. Other Options) 56.69 213.56 T +(5.1) 85.04 200.56 T +( Custom Quantization Tables) 97.53 200.56 T +(5.2 Aspect Ratio) 85.04 187.56 T +(5.3) 85.04 174.56 T +( Frame Rate) 97.53 174.56 T +(6. Other Tools) 56.69 161.56 T +(6.1) 85.04 148.56 T +(ppmtoeyuv) 100.03 148.56 T +(6.2 jmovie2jpeg) 85.04 135.56 T +(6.3 movieToVid) 85.04 122.56 T +314.36 54.99 552.76 565.23 R +7 X +V +0 X +(6.4) 342.71 558.56 T +(yuvtojpeg) 357.7 558.56 T +(6.5) 342.71 545.56 T +( blockrun) 355.2 545.56 T +(6.6) 342.71 532.56 T +( vidtoppm) 355.2 532.56 T +(6.7 vidtojpeg) 342.71 519.56 T +(6.8 vidtoeyuv) 342.71 506.56 T +(7. Frequently Asked Questions) 314.36 493.56 T +(7.1 Questions) 342.71 480.56 T +(7.2 Answers) 342.71 467.56 T +1 12 Q +(0. Contacts/History) 314.36 432.23 T +0 10 Q +2.56 (The Berkeley MPEG encoder was written by Kevin L.) 314.36 414.56 P +0.59 (Gong in the Berkeley Plateau Multimedia Research group,) 314.36 403.56 P +2.29 (headed by Professor Lawrence Rowe. It has since been) 314.36 392.56 P +2.69 (modified by Stephen Smoot, Eugene Hung, and Darryl) 314.36 381.56 P +0.69 (Brown. Please use the following e-mail addresses to reach) 314.36 370.56 P +(us:) 314.36 359.56 T +-0.23 (mpeg-bugs@plateau.cs.berkeley.edu \050bug reports and ques-) 314.36 346.56 P +(tions\051 larry@cs.berkeley.edu \050research funding!\051) 314.36 335.56 T +1 12 Q +(1. Installation) 314.36 300.23 T +0 10 Q +(To install, read the directions in doc/INSTALL.) 342.71 282.56 T +1.32 (Note that the) 342.71 269.56 P +2 F +3.17 (bin/) 400.8 269.56 P +0 F +1.32 ( directory contains binaries for) 424.79 269.56 P +0.35 (several different platforms. The program has been success-) 314.36 258.56 P +(fully ported to the following platforms:) 314.36 247.56 T +(SunOS 4.x) 342.71 234.56 T +(DEC Alpha running OSF1) 342.71 221.56 T +(DECstation 5000 running Ultrix) 342.71 208.56 T +(HP 9000 series) 342.71 195.56 T +-0.06 (If you are successful in porting to a new platform, or) 342.71 169.56 P +0.15 (have problems installing, please let us know \050at the address) 314.36 158.56 P +(above\051.) 314.36 147.56 T +1 12 Q +(2. Sequential Usage) 314.36 112.23 T +0 10 Q +(The encoder is invoked in the following manner:) 314.36 81.56 T +1 F +(mpeg_encode) 352.7 68.56 T +0 F +( <options> parameter_file) 410.44 68.56 T +56.69 570.9 552.76 735.31 R +7 X +V +1 18 Q +0 X +(Berkeley MPEG-1 V) 174.89 723.31 T +(ideo Encoder) 333.11 723.31 T +290.64 685.53 254.68 685.53 2 L +V +1.71 H +0 Z +N +(User) 254.68 687.31 T +296.95 685.53 290.96 685.53 2 L +V +N +(\325) 290.96 687.31 T +354.77 685.53 296.29 685.53 2 L +V +N +(s Guide) 296.29 687.31 T +3 12 Q +(Plateau Resear) 245.54 657.31 T +(ch Gr) 318.71 657.31 T +(oup) 345.92 657.31 T +(Computer Science Division) 239.1 643.31 T +(University of California) 247.08 629.31 T +(Berkeley) 239.59 615.31 T +(, California 94720) 280.89 615.31 T +(mpeg-bugs@cs.berkeley) 236.26 596.31 T +(.edu) 352.87 596.31 T +56.69 54.99 297.64 104.6 R +7 X +V +56.69 94.59 297.64 104.6 C +56.69 94.59 297.64 104.6 R +7 X +0 K +V +56.69 103.59 525.7 103.59 2 L +V +1 H +2 Z +0 X +N +0 0 612 792 C +0 9 Q +0 X +0 K +(Last Updated: 30 January 1995) 56.69 88.59 T +FMENDPAGE +%%EndPage: "1" 0 +%%Trailer +%%BoundingBox: 0 0 612 792 +%%Pages: 11 -1 +%%DocumentFonts: Times-Roman +%%+ Times-Bold +%%+ Courier +%%+ Times-Italic diff --git a/converter/ppm/ppmtompeg/examples/basicspeed.param b/converter/ppm/ppmtompeg/examples/basicspeed.param new file mode 100644 index 00000000..94b03de7 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/basicspeed.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/speed.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/decoded.test b/converter/ppm/ppmtompeg/examples/decoded.test new file mode 100644 index 00000000..7496524c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/decoded.test @@ -0,0 +1,81 @@ +# speed test parameter file + +PATTERN ibpbpb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR /n/picasso/users/keving/links/flowg + +INPUT +sflowg.* [0-6] +END_INPUT + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#elmer-fudd keving ~keving/encode/bin/sun/mpeg_encode +#zonker keving ~keving/encode/bin/sun/mpeg_encode +#roger-rabbit keving ~keving/encode/bin/sun/mpeg_encode +#tweety keving ~keving/encode/bin/sun/mpeg_encode +#mickey keving ~keving/encode/bin/mickey/mpeg_encode +# +# these guys are pretty fast: +# +#big-bird keving ~keving/encode/bin/hp/mpeg_encode +#gumby keving ~keving/encode/bin/hp/mpeg_encode +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +# +# remotes +# +#REMOTE anaconda keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE adder keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE moccasin keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cobra keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE boa keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE asp keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE rattler keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE viper keving ~keving/mpeg_encode ~keving/parallel.test +# mamba doesn't seem to work for whatever reason...don't know why +#REMOTE mamba keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cse.lbl.gov kevin ~kevin/mpeg_encode ~kevin/parallel.test +#REMOTE roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/parallel.test +END_PARALLEL + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 1 +PQSCALE 1 +BQSCALE 25 + +REFERENCE_FRAME DECODED +#REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/decoded2.test b/converter/ppm/ppmtompeg/examples/decoded2.test new file mode 100644 index 00000000..b5e9a865 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/decoded2.test @@ -0,0 +1,81 @@ +# speed test parameter file + +PATTERN ibbbpbbbbbp +OUTPUT /tmp/ts.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 512x512 + +INPUT_CONVERT giftoppm * + +INPUT_DIR ../test/ts + +INPUT +med*.gif [030-039] +END_INPUT + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#elmer-fudd keving ~keving/encode/bin/sun/mpeg_encode +#zonker keving ~keving/encode/bin/sun/mpeg_encode +#roger-rabbit keving ~keving/encode/bin/sun/mpeg_encode +#tweety keving ~keving/encode/bin/sun/mpeg_encode +#mickey keving ~keving/encode/bin/mickey/mpeg_encode +# +# these guys are pretty fast: +# +#big-bird keving ~keving/encode/bin/hp/mpeg_encode +#gumby keving ~keving/encode/bin/hp/mpeg_encode +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +# +# remotes +# +#REMOTE anaconda keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE adder keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE moccasin keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cobra keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE boa keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE asp keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE rattler keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE viper keving ~keving/mpeg_encode ~keving/parallel.test +# mamba doesn't seem to work for whatever reason...don't know why +#REMOTE mamba keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cse.lbl.gov kevin ~kevin/mpeg_encode ~kevin/parallel.test +#REMOTE roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/parallel.test +END_PARALLEL + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME DECODED +#REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/decorig.param b/converter/ppm/ppmtompeg/examples/decorig.param new file mode 100644 index 00000000..3c570bcd --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/decorig.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBP + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-3] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/default.param b/converter/ppm/ppmtompeg/examples/default.param new file mode 100644 index 00000000..17d8fe5d --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/default.param @@ -0,0 +1,34 @@ +# parameter file with good default values +# +# use this as a guideline for any parameters you don't really understand +# or don't care about +# + +PATTERN IBBPBBPBBPBBPBB +OUTPUT output.mpg + +BASE_FILE_FORMAT YUV +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +PIXEL HALF +RANGE 10 +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL + +# +# you really need to understand the following +# +YUV_SIZE 352x240 +INPUT_CONVERT * + +INPUT_DIR input/flowg + +INPUT +sflowg.*.yuv [0-23] +END_INPUT diff --git a/converter/ppm/ppmtompeg/examples/fastspeed.param b/converter/ppm/ppmtompeg/examples/fastspeed.param new file mode 100644 index 00000000..c45e0341 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/fastspeed.param @@ -0,0 +1,46 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR /n/picasso/project/mm/mpeg/mpeg_encode/input/flowg + +INPUT +sflowg.* [0-149] +END_INPUT + +PARALLEL_TEST_FRAMES 3 +PARALLEL_TIME_CHUNKS 15 + +PARALLEL +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/foobar.param b/converter/ppm/ppmtompeg/examples/foobar.param new file mode 100644 index 00000000..1ba6f029 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/foobar.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard20.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [000-027] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/frame.test b/converter/ppm/ppmtompeg/examples/frame.test new file mode 100644 index 00000000..fbefb8c4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/frame.test @@ -0,0 +1,37 @@ +# speed test parameter file + +PATTERN IBPB +OUTPUT output/food +GOP_SIZE 20 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR links/flowg + +INPUT +sflowg.* [0-4] +END_INPUT + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 10 +PQSCALE 31 +BQSCALE 31 + diff --git a/converter/ppm/ppmtompeg/examples/gop.combine b/converter/ppm/ppmtompeg/examples/gop.combine new file mode 100644 index 00000000..6b5c3e89 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/gop.combine @@ -0,0 +1,11 @@ +# speed test parameter file + +OUTPUT output/gop.mpg + +YUV_SIZE 352x240 + +INPUT_DIR . + +INPUT +output/food.gop.* [0-2] +END_INPUT diff --git a/converter/ppm/ppmtompeg/examples/gop.test b/converter/ppm/ppmtompeg/examples/gop.test new file mode 100644 index 00000000..c2ae346b --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/gop.test @@ -0,0 +1,43 @@ +# speed test parameter file + +PATTERN IBPBP + +OUTPUT output/food +GOP_SIZE 5 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR links/flowg + +INPUT +sflowg.* [0-14] +END_INPUT + + +GOP_INPUT_DIR output +GOP_INPUT +food.gop.* [1-2] +GOP_END_INPUT + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 10 +PQSCALE 31 +BQSCALE 31 + diff --git a/converter/ppm/ppmtompeg/examples/gop1.param b/converter/ppm/ppmtompeg/examples/gop1.param new file mode 100644 index 00000000..c89a5b9a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/gop1.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 6 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/hello.param b/converter/ppm/ppmtompeg/examples/hello.param new file mode 100644 index 00000000..579b01ed --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/hello.param @@ -0,0 +1,60 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/hello.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-49] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +#REFERENCE_FRAME DECODED +REFERENCE_FRAME ORIGINAL + +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + +PARALLEL +#big-bird keving ~keving/encode/bin/hp/mpeg_encode +#gumby keving ~keving/encode/bin/hp/mpeg_encode +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#REMOTE cory keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE scorpius.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE monoceros.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE lepus.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE fornax.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE delphinus.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE cephus.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE carina.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE bootes.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +REMOTE aquila.EECS.Berkeley.EDU keving ~keving/bin/mpeg_encode ~keving/hello.param +# +END_PARALLEL + +# FORCE_I_ALIGN diff --git a/converter/ppm/ppmtompeg/examples/i.test b/converter/ppm/ppmtompeg/examples/i.test new file mode 100644 index 00000000..af62afae --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/i.test @@ -0,0 +1,37 @@ +# speed test parameter file + +PATTERN I +OUTPUT output/food +GOP_SIZE 20 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR links/flowg + +INPUT +sflowg.* [0-5] +END_INPUT + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 10 +PQSCALE 31 +BQSCALE 31 + diff --git a/converter/ppm/ppmtompeg/examples/ispeed.jpeg.param b/converter/ppm/ppmtompeg/examples/ispeed.jpeg.param new file mode 100644 index 00000000..ce3d4ed3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/ispeed.jpeg.param @@ -0,0 +1,48 @@ +# speed test parameter file + +PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/flowgard1.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg/jpeg + +INPUT +sflowg.*.jpeg [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL + + +PARALLEL_TEST_FRAMES 3 +PARALLEL_TIME_CHUNKS 30 + +PARALLEL +big-bird keving ~keving/encode/bin/hp/mpeg_encode +gumby keving ~keving/encode/bin/hp/mpeg_encode +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +IO_SERVER_CONVERT * +SLAVE_CONVERT djpeg * diff --git a/converter/ppm/ppmtompeg/examples/ispeed.param b/converter/ppm/ppmtompeg/examples/ispeed.param new file mode 100644 index 00000000..01381e85 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/ispeed.param @@ -0,0 +1,45 @@ +# speed test parameter file + +PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/flowgard1.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL + + +PARALLEL_TEST_FRAMES 3 +PARALLEL_TIME_CHUNKS 30 + +PARALLEL +big-bird keving ~keving/encode/bin/hp/mpeg_encode +gumby keving ~keving/encode/bin/hp/mpeg_encode +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/examples/jpeg.test b/converter/ppm/ppmtompeg/examples/jpeg.test new file mode 100644 index 00000000..75e3eb8f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/jpeg.test @@ -0,0 +1,66 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.jpeg.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR /n/picasso/project/mm/mpeg/mpeg_encode/input/flowg/jpeg + +INPUT +sflowg.*.jpeg [1-20] +END_INPUT + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + +# specifies what the IO server must do before transmitting to remote sites +IO_SERVER_CONVERT * + +# specifies what the remote slave must do after receiving from IO server +SLAVE_CONVERT djpeg * + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#elmer-fudd keving ~keving/encode/bin/sun/mpeg_encode +#roger-rabbit keving ~keving/encode/bin/sun/mpeg_encode +#tweety keving ~keving/encode/bin/sun/mpeg_encode +#mickey keving ~keving/encode/bin/mickey/mpeg_encode +# +# these guys are pretty fast: +# +#big-bird keving ~keving/encode/bin/hp/mpeg_encode +#gumby keving ~keving/encode/bin/hp/mpeg_encode +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +# +# remotes +# +END_PARALLEL + + +# motion vector search parameters + +PIXEL HALF +RANGE 8 +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/jpeg19.param b/converter/ppm/ppmtompeg/examples/jpeg19.param new file mode 100644 index 00000000..15013895 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/jpeg19.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT JPEG +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg/jpeg + +INPUT +sflowg.*.jpeg [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/jpegout19.param b/converter/ppm/ppmtompeg/examples/jpegout19.param new file mode 100644 index 00000000..d31383d3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/jpegout19.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR ../input/flowg/jpeg + +INPUT +sflowg.*.jpeg [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/localdisk.param b/converter/ppm/ppmtompeg/examples/localdisk.param new file mode 100644 index 00000000..e7f49f33 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/localdisk.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN I +OUTPUT /usr/tmp/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /usr/tmp + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/localremote.test b/converter/ppm/ppmtompeg/examples/localremote.test new file mode 100644 index 00000000..6c91721f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/localremote.test @@ -0,0 +1,80 @@ +# speed test parameter file + +#PATTERN ibbpbbpbbpbbpbb +PATTERN iiiiiiii +OUTPUT /n/picasso/users/keving/src/encode/output/good +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR /n/picasso/users/keving/links/flowg + +INPUT +sflowg.* [0-149] +END_INPUT + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#REMOTE charlie-brown keving ~keving/src/encode/bin/dec/mpeg_encode ~keving/src/encode/ParamExamples/localremote.test +#REMOTE woodstock keving ~keving/src/encode/bin/dec/mpeg_encode ~keving/src/encode/ParamExamples/localremote.test +#REMOTE gumby keving ~keving/src/encode/bin/hp/mpeg_encode ~keving/src/encode/ParamExamples/localremote.test +#REMOTE big-bird keving ~keving/src/encode/bin/hp/mpeg_encode ~keving/src/encode/ParamExamples/localremote.test +#REMOTE elmer-fudd keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/localremote.test +#REMOTE mickey keving ~keving/src/encode/bin/mickey/mpeg_encode ~keving/src/encode/ParamExamples/localremote.test +#zonker keving ~keving/src/encode/bin/sun/mpeg_encode +#roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode +#tweety keving ~keving/src/encode/bin/sun/mpeg_encode +# +# these guys are pretty fast: +# +#bugs-bunny keving ~keving/src/encode/bin/sun/mpeg_encode +# +# remotes +# +#REMOTE anaconda keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE adder keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE moccasin keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cobra keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE boa keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE asp keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE rattler keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE viper keving ~keving/mpeg_encode ~keving/parallel.test +# mamba doesn't seem to work for whatever reason...don't know why +#REMOTE mamba keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cse.lbl.gov kevin ~kevin/mpeg_encode ~kevin/parallel.test +#REMOTE roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/parallel.test +END_PARALLEL + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/luxo.param b/converter/ppm/ppmtompeg/examples/luxo.param new file mode 100644 index 00000000..6c92dca1 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/luxo.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 20 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/luxo18.param b/converter/ppm/ppmtompeg/examples/luxo18.param new file mode 100644 index 00000000..4a020325 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo18.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/luxo19.5.param b/converter/ppm/ppmtompeg/examples/luxo19.5.param new file mode 100644 index 00000000..edacc7c7 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo19.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1216] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo19.param b/converter/ppm/ppmtompeg/examples/luxo19.param new file mode 100644 index 00000000..7accb23a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo19.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo2.param b/converter/ppm/ppmtompeg/examples/luxo2.param new file mode 100644 index 00000000..f75b7e1c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo2.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/luxo2.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo1399.yuv +luxo1400.yuv +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 20 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/luxo48.param b/converter/ppm/ppmtompeg/examples/luxo48.param new file mode 100644 index 00000000..599f6d8c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo48.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo49.param b/converter/ppm/ppmtompeg/examples/luxo49.param new file mode 100644 index 00000000..5a493e40 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo49.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo50.param b/converter/ppm/ppmtompeg/examples/luxo50.param new file mode 100644 index 00000000..f3afe8e8 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo50.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo52.5.param b/converter/ppm/ppmtompeg/examples/luxo52.5.param new file mode 100644 index 00000000..f3f16854 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo52.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1216] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo52.param b/converter/ppm/ppmtompeg/examples/luxo52.param new file mode 100644 index 00000000..8874ad97 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo52.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1400] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxo53.param b/converter/ppm/ppmtompeg/examples/luxo53.param new file mode 100644 index 00000000..d084b18b --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxo53.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/luxo19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo + +INPUT +luxo*.yuv [1201-1216] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG EXHAUSTIVE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/luxobug.param b/converter/ppm/ppmtompeg/examples/luxobug.param new file mode 100644 index 00000000..73e9de9f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxobug.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/luxobug.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo-skip10 + +INPUT +luxo*.yuv [1351-1701+5] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/luxoskip.param b/converter/ppm/ppmtompeg/examples/luxoskip.param new file mode 100644 index 00000000..12768ed4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/luxoskip.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/luxoskip.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/luxo-skip10 + +INPUT +luxo*1 [1-307] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 20 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/med.param b/converter/ppm/ppmtompeg/examples/med.param new file mode 100644 index 00000000..0e3bbd8d --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/med.param @@ -0,0 +1,36 @@ +# 'med' parameter file + +PATTERN IBBPBBPBBPBBPBBI +OUTPUT output/med.mpg +GOP_SIZE 20 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +INPUT_CONVERT giftoppm * + +INPUT_DIR links/gcmovie + +INPUT +med*.gif [001-073] +END_INPUT + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + + +IQSCALE 13 +PQSCALE 16 +BQSCALE 26 + diff --git a/converter/ppm/ppmtompeg/examples/med18.param b/converter/ppm/ppmtompeg/examples/med18.param new file mode 100644 index 00000000..b8ad664c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/med18.param @@ -0,0 +1,34 @@ +# 'med' parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/med18.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +INPUT_CONVERT giftoppm * + +INPUT_DIR /n/picasso/users/keving/encode/input/gcmovie + +INPUT +med*.gif [001-073] +END_INPUT + + +# motion vector search parameters + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/medspeed.param b/converter/ppm/ppmtompeg/examples/medspeed.param new file mode 100644 index 00000000..d91f4dda --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/medspeed.param @@ -0,0 +1,38 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR /n/picasso/project/mm/mpeg/mpeg_encode/input/flowg + +INPUT +sflowg.* [0-149] +END_INPUT + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/nametest.param b/converter/ppm/ppmtompeg/examples/nametest.param new file mode 100644 index 00000000..445622fb --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/nametest.param @@ -0,0 +1,60 @@ +# test suite parameter file + +PATTERN IBBBPBBBBP +OUTPUT /tmp/foobar.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +INPUT_CONVERT cat *.Y *.U *.V +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR /n/picasso/users/keving/encode/input/tennis + +INPUT +stennis.0 +stennis.* [1-3] +stennis.* [4-5] +stennis.* [6-6] +stennis.7 +stennis.* [8-15] +stennis.16 +stennis.17 +stennis.* [18-34] +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale +# +# change this only if you're unsatisfied with the CPU time or quality, or +# are experimenting +# + +# if this appears in the file, then in addition to testing luminance when +# computing motion vectors, program will also take into account chrominance +# +# this option MUST appear before ERROR option, or it will be ignored +# +# CHROMINANCE + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG LOGARITHMIC + +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/nosearch.param b/converter/ppm/ppmtompeg/examples/nosearch.param new file mode 100644 index 00000000..453356c0 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/nosearch.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/flowgard1.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/par3.param b/converter/ppm/ppmtompeg/examples/par3.param new file mode 100644 index 00000000..ca664334 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/par3.param @@ -0,0 +1,43 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-39] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL + +PARALLEL_TEST_FRAMES 3 +PARALLEL_TIME_CHUNKS 30 + +PARALLEL +bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +linus keving ~keving/encode/bin/sun/mpeg_encode +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/examples/par4.param b/converter/ppm/ppmtompeg/examples/par4.param new file mode 100644 index 00000000..95a72c34 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/par4.param @@ -0,0 +1,45 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-49] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL + +PARALLEL_TEST_FRAMES 3 +# PARALLEL_TIME_CHUNKS 20 +PARALLEL_CHUNK_TAPER + +PARALLEL +bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +linus keving ~keving/encode/bin/sun/mpeg_encode +zonker keving ~keving/encode/bin/sun/mpeg_encode +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/examples/par5.param b/converter/ppm/ppmtompeg/examples/par5.param new file mode 100644 index 00000000..ad51a519 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/par5.param @@ -0,0 +1,47 @@ +# speed test parameter file + +#PATTERN IBBPBBPBBPBBPBB +PATTERN I + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL + +PARALLEL_TEST_FRAMES 3 +PARALLEL_CHUNK_TAPER + +PARALLEL +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +gumby keving ~keving/encode/bin/hp/mpeg_encode +big-bird keving ~keving/encode/bin/hp/mpeg_encode +roger-rabbit keving ~keving/encode/bin/sun/mpeg_encode +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/examples/parallel.2 b/converter/ppm/ppmtompeg/examples/parallel.2 new file mode 100644 index 00000000..0ab153fb --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/parallel.2 @@ -0,0 +1,87 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR /n/picasso/project/mm/mpeg/mpeg_encode/input/flowg/jpeg + +INPUT +sflowg.*.jpeg [1-30] +END_INPUT + +# the following are optional + +PARALLEL_PERFECT + + + +# specifies what the IO server must do before transmitting to remote sites +IO_SERVER_CONVERT * + +# specifies what the remote slave must do after receiving from IO server +SLAVE_CONVERT djpeg * + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#elmer-fudd keving ~keving/encode/bin/sun/mpeg_encode +#elmer-fudd keving ~keving/encode/bin/sun/mpeg_encode +#bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +#REMOTE bugs-bunny keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/parallel.test +#roger-rabbit keving ~keving/encode/bin/sun/mpeg_encode +#tweety keving ~keving/encode/bin/sun/mpeg_encode +#mickey keving ~keving/encode/bin/mickey/mpeg_encode +# +# these guys are pretty fast: +# +#big-bird keving ~keving/encode/bin/hp/mpeg_encode +#gumby keving ~keving/encode/bin/hp/mpeg_encode +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +# +# remotes +# +#REMOTE anaconda keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE adder keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE moccasin keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cobra keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE boa keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE asp keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE rattler keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE viper keving ~keving/mpeg_encode ~keving/parallel.test +# mamba doesn't seem to work for whatever reason...don't know why +#REMOTE mamba keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cse.lbl.gov kevin ~kevin/mpeg_encode ~kevin/parallel.test +#REMOTE roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/parallel.test +END_PARALLEL + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + + +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/parallel.param b/converter/ppm/ppmtompeg/examples/parallel.param new file mode 100644 index 00000000..a158eae5 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/parallel.param @@ -0,0 +1,141 @@ +# parameter file template with parallel execution +# +# you can use this as a template, copying it to a separate file then modifying +# the copy +# +# +# any line beginning with '#' is a comment +# +# no line should be longer than 255 characters +# +# +# general format of each line is: +# <option> <spaces and/or tabs> <value> +# +# lines can generally be in any order +# +# only exception is the option 'INPUT' which must be followed by input +# files in the order in which they must appear, followed by 'END_INPUT' +# +# <option> MUST be in UPPER CASE +# + +PATTERN IBBPBBPBBPBBP +OUTPUT /n/picasso/users/keving/encode/output.mpg + +# mpeg_encode really only accepts 3 different file formats, but using a +# conversion statement it can effectively handle ANY file format +# +# you must specify whether you will convert to PNM or PPM or YUV format +# (must be upper case) +# +BASE_FILE_FORMAT YUV + +# +# if YUV format (or using parallel version), must provide width and height +# YUV_SIZE widthxheight +# this option is ignored if BASE_FILE_FORMAT is PPM or PNM and you're running +# on just one machine +# +YUV_SIZE 352x240 + +# the conversion statement +# +# Each occurrence of '*' will be replaced by the input file +# +# e.g., if you have a bunch of GIF files, then this might be: +# INPUT_CONVERT giftoppm * +# +# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then: +# INPUT_CONVERT cat *.Y *.U *.V +# +# e.g., if you are grabbing from laser disc you might have something like +# INPUT_CONVERT goto frame *; grabppm +# 'INPUT_CONVERT *' means the files are already in the base file format +# +INPUT_CONVERT * + +# number of frames in a GOP. +# +# since each GOP must have at least one I-frame, the encoder will find the +# the first I-frame after GOP_SIZE frames to start the next GOP +# +# later, will add more flexible GOP signalling +# +GOP_SIZE 6 + +# number of slices in a frame +# +# 1 is a good number. another possibility is the number of macroblock rows +# (which is the height divided by 16) +# +SLICES_PER_FRAME 1 + +# directory to get all input files from (makes this file easier to read) +INPUT_DIR /n/picasso/users/keving/encode/input/tennis + +INPUT +# '*' is replaced by the numbers 01, 02, 03, 04 +# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11 +# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11 +# if I instead do [1-11+3], it would be 1, 4, 7, 10 +# the program assumes none of your input files has a name ending in ']' +# if you do, too bad!!! +# +# +stennis.*.yuv [0-7] +# can have more files here if you want...there is no limit on the number +# of files +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 10 + +# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC} +PSEARCH_ALG LOGARITHMIC + +# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE} +# +# note that EXHAUSTIVE is really, really, really slow +# +BSEARCH_ALG CROSS2 + +# +# these specify the q-scale for I, P, and B frames +# (values must be between 1 and 31) +# +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# this must be ORIGINAL or DECODED +REFERENCE_FRAME ORIGINAL + + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +#REMOTE charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode ~keving/encode/examples/parallel.param +# remote machine: "REMOTE machine username executable param_file" +# mickey keving ~keving/encode/bin/dec-5000/mpeg_encode +#REMOTE mickey keving ~keving/encode/bin/dec-5000/mpeg_encode ~keving/encode/examples/parallel.param +#REMOTE mickey keving ~keving/encode/bin/dec-5000/mpeg_encode ~keving/encode/examples/parallel.param +REMOTE woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode ~keving/encode/examples/parallel.param +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/examples/parallel.test b/converter/ppm/ppmtompeg/examples/parallel.test new file mode 100644 index 00000000..2489d847 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/parallel.test @@ -0,0 +1,85 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR /n/picasso/project/mm/mpeg/mpeg_encode/input/flowg/jpeg + +INPUT +sflowg.*.jpeg [1-30] +END_INPUT + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + +# specifies what the IO server must do before transmitting to remote sites +IO_SERVER_CONVERT * + +# specifies what the remote slave must do after receiving from IO server +SLAVE_CONVERT djpeg * + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#REMOTE bugs-bunny keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/parallel.test +#mickey keving ~keving/encode/bin/mickey/mpeg_encode +# +# these guys are pretty fast: +# +#big-bird keving ~keving/encode/bin/hp/mpeg_encode +#gumby keving ~keving/encode/bin/hp/mpeg_encode +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +#roger-rabbit keving ~keving/encode/bin/sun/mpeg_encode +# +# remotes +# +#REMOTE anaconda keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE adder keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE moccasin keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cobra keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE boa keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE asp keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE rattler keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE viper keving ~keving/mpeg_encode ~keving/parallel.test +# mamba doesn't seem to work for whatever reason...don't know why +#REMOTE mamba keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cse.lbl.gov kevin ~kevin/mpeg_encode ~kevin/parallel.test +#REMOTE roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/parallel.test +END_PARALLEL + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + + +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/param.template b/converter/ppm/ppmtompeg/examples/param.template new file mode 100644 index 00000000..ce81e474 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/param.template @@ -0,0 +1,107 @@ +# parameter file template +# +# any line beginning with '#' is a comment +# +# no line should be longer than 255 characters +# +# +# general format of each line is: +# <option> <spaces and/or tabs> <value> +# +# lines can generally be in any order +# +# only exception is the option 'INPUT' which must be followed by input +# files in the order in which they must appear, followed by 'END_INPUT' +# +# <option> MUST be in UPPER CASE +# + +PATTERN IBBPBBPBBPBBP +OUTPUT output/food + +# mpeg_encode really only accepts 2 different file formats, but using a +# conversion statement it can effectively handle ANY file format +# +# you must specify whether you will convert to PPM or YUV format +# (must be upper case) +# +BASE_FILE_FORMAT YUV + +# +# if YUV format, must provide width and height +# YUV_SIZE width height +# this option is ignored if BASE_FILE_FORMAT is PPM +# +YUV_SIZE 352x240 + +# the conversion statement +# +# Each occurrence of '*' will be replaced by the input file +# +# e.g., if you have a bunch of GIF files, then this might be: +# INPUT_CONVERT giftoppm * +# +# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then: +# INPUT_CONVERT cat *.Y *.U *.V +# +# e.g., if you are grabbing from laser disc you might have something like +# INPUT_CONVERT goto frame *; grabppm +# 'INPUT_CONVERT *' means the files are already in the base file format +# +INPUT_CONVERT cat *.Y *.U *.V + +# number of frames in a GOP. +# +# since each GOP must have at least one I-frame, the encoder will find the +# the first I-frame after GOP_SIZE frames to start the next GOP +# +# later, will add more flexible GOP signalling +# +GOP_SIZE 30 + +# directory to get all input files from (makes this file easier to read) +INPUT_DIR links/payam + +INPUT +# '*' is replaced by the numbers 01, 02, 03, 04 +# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11 +# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11 +# the program assumes none of your input files has a name ending in ']' +# if you do, too bad!!! +# +# +stennis.* [0-23] +# can have more files here if you want...as many as you want +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale +# +# change this only if you're unsatisfied with the CPU time or quality, or +# are experimenting +# + +# if this appears in the file, then in addition to testing luminance when +# computing motion vectors, program will also take into account chrominance +# +# this option MUST appear before ERROR option, or it will be ignored +# +# CHROMINANCE + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +# YES or NO -- must be upper case +SUBSAMPLE NO + +IQSCALE 10 +PQSCALE 15 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/payam.param b/converter/ppm/ppmtompeg/examples/payam.param new file mode 100644 index 00000000..ce886914 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/payam.param @@ -0,0 +1,37 @@ +# parameter file for payam's images + +#PATTERN IBBPBBPBBPBBPBBI +PATTERN II +OUTPUT output/payam.mpg +GOP_SIZE 20 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PNM + +INPUT_CONVERT * +INPUT_DIR links/payam + +INPUT +kh*.pnm [1-3] +END_INPUT + + +# motion vector search paramters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + + +IQSCALE 10 +PQSCALE 15 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/payam18.param b/converter/ppm/ppmtompeg/examples/payam18.param new file mode 100644 index 00000000..7f7b767e --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/payam18.param @@ -0,0 +1,34 @@ +# parameter file for payam's images + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/payam18.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PNM + +INPUT_CONVERT * +INPUT_DIR /n/picasso/users/keving/encode/input/payam + +INPUT +kh*.pnm [1-39] +END_INPUT + + +# motion vector search paramters + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/pnm.param b/converter/ppm/ppmtompeg/examples/pnm.param new file mode 100644 index 00000000..6fce2be4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/pnm.param @@ -0,0 +1,37 @@ +# speed test parameter file + +PATTERN I +OUTPUT output/food +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR links/flowg + +INPUT +sflowg.*.ppm [01-10] +END_INPUT + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 31 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/ppm.param b/converter/ppm/ppmtompeg/examples/ppm.param new file mode 100644 index 00000000..6fce2be4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/ppm.param @@ -0,0 +1,37 @@ +# speed test parameter file + +PATTERN I +OUTPUT output/food +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR links/flowg + +INPUT +sflowg.*.ppm [01-10] +END_INPUT + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 31 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/prof.b.param b/converter/ppm/ppmtompeg/examples/prof.b.param new file mode 100644 index 00000000..2b8253fd --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof.b.param @@ -0,0 +1,48 @@ +# test suite parameter file + +PATTERN IBBBBBBBBI +OUTPUT output/food + +BASE_FILE_FORMAT PPM +INPUT_CONVERT giftoppm * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR Test/ts + +INPUT +med*.gif [030-039] +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale +# +# change this only if you're unsatisfied with the CPU time or quality, or +# are experimenting +# + +# if this appears in the file, then in addition to testing luminance when +# computing motion vectors, program will also take into account chrominance +# +# this option MUST appear before ERROR option, or it will be ignored +# +# CHROMINANCE + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 8 + +# YES or NO -- must be upper case +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/prof.bhalf.param b/converter/ppm/ppmtompeg/examples/prof.bhalf.param new file mode 100644 index 00000000..8d6de83a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof.bhalf.param @@ -0,0 +1,48 @@ +# test suite parameter file + +PATTERN IBBBBBBBBI +OUTPUT output/food + +BASE_FILE_FORMAT PPM +INPUT_CONVERT giftoppm * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR Test/ts + +INPUT +med*.gif [030-039] +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale +# +# change this only if you're unsatisfied with the CPU time or quality, or +# are experimenting +# + +# if this appears in the file, then in addition to testing luminance when +# computing motion vectors, program will also take into account chrominance +# +# this option MUST appear before ERROR option, or it will be ignored +# +# CHROMINANCE + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 8 + +# YES or NO -- must be upper case +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/prof.param b/converter/ppm/ppmtompeg/examples/prof.param new file mode 100644 index 00000000..591eaa67 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof.param @@ -0,0 +1,36 @@ +# speed test parameter file + +PATTERN I +#PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +#REFERENCE_FRAME DECODED +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/prof.ss.param b/converter/ppm/ppmtompeg/examples/prof.ss.param new file mode 100644 index 00000000..ef339e7a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof.ss.param @@ -0,0 +1,48 @@ +# test suite parameter file + +PATTERN IPPPPPPPPP +OUTPUT output/food + +BASE_FILE_FORMAT PPM +INPUT_CONVERT giftoppm * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR Test/ts + +INPUT +med*.gif [030-039] +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale +# +# change this only if you're unsatisfied with the CPU time or quality, or +# are experimenting +# + +# if this appears in the file, then in addition to testing luminance when +# computing motion vectors, program will also take into account chrominance +# +# this option MUST appear before ERROR option, or it will be ignored +# +# CHROMINANCE + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 16 + +# YES or NO -- must be upper case +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/prof2.param b/converter/ppm/ppmtompeg/examples/prof2.param new file mode 100644 index 00000000..4073606a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof2.param @@ -0,0 +1,36 @@ +# speed test parameter file + +PATTERN IPPP +#PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED + diff --git a/converter/ppm/ppmtompeg/examples/prof3.param b/converter/ppm/ppmtompeg/examples/prof3.param new file mode 100644 index 00000000..4581eade --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof3.param @@ -0,0 +1,36 @@ +# speed test parameter file + +PATTERN IBB +#PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED + diff --git a/converter/ppm/ppmtompeg/examples/prof4.param b/converter/ppm/ppmtompeg/examples/prof4.param new file mode 100644 index 00000000..583fb43c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/prof4.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED + diff --git a/converter/ppm/ppmtompeg/examples/remote.test b/converter/ppm/ppmtompeg/examples/remote.test new file mode 100644 index 00000000..d548510f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/remote.test @@ -0,0 +1,85 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/good.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR /n/picasso/users/keving/links/flowg + +INPUT +sflowg.* [0-40] +END_INPUT + +# the following two are optional (default = 10, 60) + +# number of frames to do initially to gauge speed of machine +PARALLEL_TEST_FRAMES 3 + +# number of seconds per chunk thereafter +PARALLEL_TIME_CHUNKS 30 + + +PARALLEL +# lines must be of form "machine <whitespace> username <whitespace> executable" +# these guys are sorta slow: +#elmer-fudd keving ~keving/src/encode/bin/sun/mpeg_encode +#zonker keving ~keving/src/encode/bin/sun/mpeg_encode +#roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode +#tweety keving ~keving/src/encode/bin/sun/mpeg_encode +#mickey keving ~keving/src/encode/bin/mickey/mpeg_encode +# +REMOTE zonker keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/remote.test +REMOTE linus keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/remote.test +REMOTE roger-rabbit keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/remote.test +REMOTE bugs-bunny keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/remote.test +REMOTE elmer-fudd keving ~keving/encode/src/mpeg_encode ~keving/encode/examples/remote.test +# these guys are pretty fast: +# +#big-bird keving ~keving/src/encode/bin/hp/mpeg_encode +#gumby keving ~keving/src/encode/bin/hp/mpeg_encode +#charlie-brown keving ~keving/src/encode/bin/dec/mpeg_encode +#woodstock keving ~keving/src/encode/bin/dec/mpeg_encode +#bugs-bunny keving ~keving/src/encode/bin/sun/mpeg_encode +# +# remotes +# +#REMOTE anaconda keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE adder keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE moccasin keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cobra keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE boa keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE asp keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE rattler keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE viper keving ~keving/mpeg_encode ~keving/parallel.test +# mamba doesn't seem to work for whatever reason...don't know why +#REMOTE mamba keving ~keving/mpeg_encode ~keving/parallel.test +#REMOTE cse.lbl.gov kevin ~kevin/mpeg_encode ~kevin/parallel.test +#REMOTE roger-rabbit keving ~keving/src/encode/bin/sun/mpeg_encode ~keving/src/encode/ParamExamples/parallel.test +END_PARALLEL + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL FULL + +# means +/- this many pixels +RANGE 4 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search1.param b/converter/ppm/ppmtompeg/examples/search1.param new file mode 100644 index 00000000..779ffa0f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search1.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard1.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search10.param b/converter/ppm/ppmtompeg/examples/search10.param new file mode 100644 index 00000000..c44c7c72 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search10.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard10.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search11.param b/converter/ppm/ppmtompeg/examples/search11.param new file mode 100644 index 00000000..78935268 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search11.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard11.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search12.param b/converter/ppm/ppmtompeg/examples/search12.param new file mode 100644 index 00000000..d7a115c3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search12.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard12.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search13.param b/converter/ppm/ppmtompeg/examples/search13.param new file mode 100644 index 00000000..80bb57f5 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search13.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard13.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search14.param b/converter/ppm/ppmtompeg/examples/search14.param new file mode 100644 index 00000000..af0ebb9c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search14.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search15.param b/converter/ppm/ppmtompeg/examples/search15.param new file mode 100644 index 00000000..1df18350 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search15.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard15.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search16.param b/converter/ppm/ppmtompeg/examples/search16.param new file mode 100644 index 00000000..3523dce3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search16.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard16.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search17.param b/converter/ppm/ppmtompeg/examples/search17.param new file mode 100644 index 00000000..89c3cb91 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search17.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard17.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search18.param b/converter/ppm/ppmtompeg/examples/search18.param new file mode 100644 index 00000000..d659d914 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search18.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard18.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search19.5.param b/converter/ppm/ppmtompeg/examples/search19.5.param new file mode 100644 index 00000000..22827fce --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search19.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-15] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search19.param b/converter/ppm/ppmtompeg/examples/search19.param new file mode 100644 index 00000000..88f9d613 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search19.param @@ -0,0 +1,42 @@ +# speed test parameter file + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/charlie-brown/project/mm/mpeg/mpeg_encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + + + + +PATTERN IBBPBBPBBPBBPBB + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +# LOGARITHMIC, TWOLEVEL, SUBSAMPLE, EXHAUSTIVE +PSEARCH_ALG LOGARITHMIC + +# CROSS2, SIMPLE +BSEARCH_ALG CROSS2 + +# DECODED or ORIGINAL +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search2.param b/converter/ppm/ppmtompeg/examples/search2.param new file mode 100644 index 00000000..c4f6300c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search2.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard2.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search20.param b/converter/ppm/ppmtompeg/examples/search20.param new file mode 100644 index 00000000..efd05f6d --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search20.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard20.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search21.param b/converter/ppm/ppmtompeg/examples/search21.param new file mode 100644 index 00000000..6acb79ac --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search21.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard21.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search22.param b/converter/ppm/ppmtompeg/examples/search22.param new file mode 100644 index 00000000..252cb25b --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search22.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard22.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search23.param b/converter/ppm/ppmtompeg/examples/search23.param new file mode 100644 index 00000000..5e7a7620 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search23.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard23.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search24.param b/converter/ppm/ppmtompeg/examples/search24.param new file mode 100644 index 00000000..0ca71e6d --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search24.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard24.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search25.param b/converter/ppm/ppmtompeg/examples/search25.param new file mode 100644 index 00000000..724ce5a4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search25.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard25.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search26.param b/converter/ppm/ppmtompeg/examples/search26.param new file mode 100644 index 00000000..1a7081cd --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search26.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard26.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search27.param b/converter/ppm/ppmtompeg/examples/search27.param new file mode 100644 index 00000000..49da7e7a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search27.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard27.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 20 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search28.param b/converter/ppm/ppmtompeg/examples/search28.param new file mode 100644 index 00000000..f78331aa --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search28.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard28.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search29.param b/converter/ppm/ppmtompeg/examples/search29.param new file mode 100644 index 00000000..52f89a90 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search29.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard29.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search3.param b/converter/ppm/ppmtompeg/examples/search3.param new file mode 100644 index 00000000..4c00af6c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search3.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard3.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search30.param b/converter/ppm/ppmtompeg/examples/search30.param new file mode 100644 index 00000000..5664dbb8 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search30.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard30.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search31.param b/converter/ppm/ppmtompeg/examples/search31.param new file mode 100644 index 00000000..3d8bc0cd --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search31.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search32.param b/converter/ppm/ppmtompeg/examples/search32.param new file mode 100644 index 00000000..a4675cee --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search32.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard32.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search33.param b/converter/ppm/ppmtompeg/examples/search33.param new file mode 100644 index 00000000..465132c6 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search33.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard33.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search34.param b/converter/ppm/ppmtompeg/examples/search34.param new file mode 100644 index 00000000..f53a91f3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search34.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard34.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search35.param b/converter/ppm/ppmtompeg/examples/search35.param new file mode 100644 index 00000000..5a7fa27f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search35.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard35.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search36.param b/converter/ppm/ppmtompeg/examples/search36.param new file mode 100644 index 00000000..66fb8e7f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search36.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard36.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search37.param b/converter/ppm/ppmtompeg/examples/search37.param new file mode 100644 index 00000000..f5f5d4d3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search37.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard37.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search38.param b/converter/ppm/ppmtompeg/examples/search38.param new file mode 100644 index 00000000..b8186ce2 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search38.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard38.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search39.param b/converter/ppm/ppmtompeg/examples/search39.param new file mode 100644 index 00000000..ab18d28b --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search39.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard39.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 4 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search4.param b/converter/ppm/ppmtompeg/examples/search4.param new file mode 100644 index 00000000..68285e6d --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search4.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard4.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search40.param b/converter/ppm/ppmtompeg/examples/search40.param new file mode 100644 index 00000000..3fd65b6e --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search40.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard40.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search41.param b/converter/ppm/ppmtompeg/examples/search41.param new file mode 100644 index 00000000..3a47baf7 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search41.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard41.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search42.param b/converter/ppm/ppmtompeg/examples/search42.param new file mode 100644 index 00000000..3ade2c85 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search42.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard42.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search43.param b/converter/ppm/ppmtompeg/examples/search43.param new file mode 100644 index 00000000..e2c044a4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search43.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard43.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search44.param b/converter/ppm/ppmtompeg/examples/search44.param new file mode 100644 index 00000000..47c97e89 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search44.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard44.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search45.param b/converter/ppm/ppmtompeg/examples/search45.param new file mode 100644 index 00000000..c4131d33 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search45.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard45.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search46.param b/converter/ppm/ppmtompeg/examples/search46.param new file mode 100644 index 00000000..cc9c67bf --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search46.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard46.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search47.param b/converter/ppm/ppmtompeg/examples/search47.param new file mode 100644 index 00000000..7527228e --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search47.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard47.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search48.param b/converter/ppm/ppmtompeg/examples/search48.param new file mode 100644 index 00000000..3d75a6a2 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search48.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search49.param b/converter/ppm/ppmtompeg/examples/search49.param new file mode 100644 index 00000000..c25ab724 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search49.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search5.param b/converter/ppm/ppmtompeg/examples/search5.param new file mode 100644 index 00000000..5a1ad629 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search5.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard5.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search50.param b/converter/ppm/ppmtompeg/examples/search50.param new file mode 100644 index 00000000..6711ebb7 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search50.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search51.param b/converter/ppm/ppmtompeg/examples/search51.param new file mode 100644 index 00000000..6609e381 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search51.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-19] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG EXHAUSTIVE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search52.5.param b/converter/ppm/ppmtompeg/examples/search52.5.param new file mode 100644 index 00000000..be34be4b --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search52.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-15] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search52.param b/converter/ppm/ppmtompeg/examples/search52.param new file mode 100644 index 00000000..246aa978 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search52.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search53.param b/converter/ppm/ppmtompeg/examples/search53.param new file mode 100644 index 00000000..81afb3bc --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search53.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-15] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG EXHAUSTIVE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search6.param b/converter/ppm/ppmtompeg/examples/search6.param new file mode 100644 index 00000000..47c36a0c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search6.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard6.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/search7.param b/converter/ppm/ppmtompeg/examples/search7.param new file mode 100644 index 00000000..f5d1224d --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search7.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard7.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search8.param b/converter/ppm/ppmtompeg/examples/search8.param new file mode 100644 index 00000000..f3b17e96 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search8.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard8.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 20 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/search9.param b/converter/ppm/ppmtompeg/examples/search9.param new file mode 100644 index 00000000..80051112 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/search9.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard9.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL FULL + +RANGE 20 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/seq.param b/converter/ppm/ppmtompeg/examples/seq.param new file mode 100644 index 00000000..665c22a7 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/seq.param @@ -0,0 +1,36 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/zonker/video/sequoia.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT /n/zonker/video/getframe * + +INPUT_DIR /n/zonker/video/seqframes + +INPUT +# really goes up to 200 +* [0-1000] +END_INPUT + +# quality parameters + +IQSCALE 15 +PQSCALE 18 +BQSCALE 30 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/sequoia.param b/converter/ppm/ppmtompeg/examples/sequoia.param new file mode 100644 index 00000000..1b93d880 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/sequoia.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/sequoia.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR /n/zonker/video/seqframes + +INPUT +sequoia*.jpeg [378-600] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 22 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/sequoia19.param b/converter/ppm/ppmtompeg/examples/sequoia19.param new file mode 100644 index 00000000..52e5a72b --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/sequoia19.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/charlie-brown/project/mm/mpeg/mpeg_encode/output/seq.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT /n/zonker/video/seqframes/gframe /n/video/video/sequoia * 640x480.100 352 240 + +INPUT_DIR /n/zonker/video + +INPUT +* [0-199] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/sequoia2.param b/converter/ppm/ppmtompeg/examples/sequoia2.param new file mode 100644 index 00000000..676cc2e4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/sequoia2.param @@ -0,0 +1,36 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/sequoia.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT djpeg * + +INPUT_DIR /n/zonker/video/seqframes + +INPUT +# really goes up to 200 +sequoia*.jpeg [001-200] +END_INPUT + +# quality parameters + +IQSCALE 15 +PQSCALE 18 +BQSCALE 30 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/simple.param b/converter/ppm/ppmtompeg/examples/simple.param new file mode 100644 index 00000000..14964829 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/simple.param @@ -0,0 +1,40 @@ +# Simple parameter file + +OUTPUT ./test.mpg +GOP_SIZE 15 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/charlie-brown/project/mm/mpeg/mpeg_encode/input/flowg + +INPUT +sflowg.*.yuv [0-14] +END_INPUT + +PATTERN IBBPBBPBBPBBPBBPBBPBBP + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 4 + +# LOGARITHMIC, TWOLEVEL, SUBSAMPLE, EXHAUSTIVE +PSEARCH_ALG LOGARITHMIC + +# CROSS2, SIMPLE +BSEARCH_ALG CROSS2 + +# DECODED or ORIGINAL +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/slice.param b/converter/ppm/ppmtompeg/examples/slice.param new file mode 100644 index 00000000..308d2053 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/slice.param @@ -0,0 +1,47 @@ +# test suite parameter file + +PATTERN IIIIIIIII +OUTPUT ts.mpg + +BASE_FILE_FORMAT PPM +INPUT_CONVERT giftoppm * +GOP_SIZE 1 +SLICES_PER_FRAME 170000 + +INPUT_DIR ts + +INPUT +med*.gif [030-034] +END_INPUT + + + +# all of the remaining options have to do with the motion search and qscale +# +# change this only if you're unsatisfied with the CPU time or quality, or +# are experimenting +# + +# if this appears in the file, then in addition to testing luminance when +# computing motion vectors, program will also take into account chrominance +# +# this option MUST appear before ERROR option, or it will be ignored +# +# CHROMINANCE + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 4 + +# YES or NO -- must be upper case +SUBSAMPLE NO + +IQSCALE 31 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/slimed.param b/converter/ppm/ppmtompeg/examples/slimed.param new file mode 100644 index 00000000..b5938b94 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/slimed.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/slimed.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 480x360 + +INPUT_CONVERT djpeg * + +INPUT_DIR ../input/slimed + +INPUT +slimed.*.jpeg [1-100] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 20 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/slowspeed.param b/converter/ppm/ppmtompeg/examples/slowspeed.param new file mode 100644 index 00000000..321313be --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/slowspeed.param @@ -0,0 +1,38 @@ +# speed test parameter file + +PATTERN ibbpbbpbbpbbpbb +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR /n/picasso/project/mm/mpeg/mpeg_encode/input/flowg + +INPUT +sflowg.* [0-149] +END_INPUT + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 12 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL + diff --git a/converter/ppm/ppmtompeg/examples/stanford.param b/converter/ppm/ppmtompeg/examples/stanford.param new file mode 100644 index 00000000..4c87334c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/stanford.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/stanford.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 4 +PQSCALE 4 +BQSCALE 8 + +# motion vector search parameters + +PIXEL HALF + +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/subtest.param b/converter/ppm/ppmtompeg/examples/subtest.param new file mode 100644 index 00000000..7fb4f585 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/subtest.param @@ -0,0 +1,34 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/flowgard18.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT SUB4 +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg/yuvsub + +INPUT +* [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/temp.param b/converter/ppm/ppmtompeg/examples/temp.param new file mode 100644 index 00000000..209fdfb4 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/temp.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flow.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/flowg + +INPUT +sflowg.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/template.param b/converter/ppm/ppmtompeg/examples/template.param new file mode 100644 index 00000000..66b6dd98 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/template.param @@ -0,0 +1,154 @@ +# parameter file template with lots of comments to assist you +# +# you can use this as a template, copying it to a separate file then modifying +# the copy +# +# +# any line beginning with '#' is a comment +# +# no line should be longer than 255 characters +# +# +# general format of each line is: +# <option> <spaces and/or tabs> <value> +# +# lines can generally be in any order +# +# an exception is the option 'INPUT' which must be followed by input +# files in the order in which they must appear, followed by 'END_INPUT' +# +# Also, if you use the `command` method of generating input file names, +# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds +# the INPUT parameter. +# +# <option> MUST be in UPPER CASE +# + +PATTERN IBBPBBPBBPBBPBBP +OUTPUT output.mpg + +# mpeg_encode really only accepts 3 different file formats, but using a +# conversion statement it can effectively handle ANY file format +# +# You must specify the type of the input files. The choices are: +# YUV, PPM, JMOVIE, Y, JPEG, PNM +# (must be upper case) +# +BASE_FILE_FORMAT YUV + +# +# if YUV format (or using parallel version), must provide width and height +# YUV_SIZE widthxheight +# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running +# on just one machine +# +YUV_SIZE 352x240 + +# If you are using YUV, there are different supported file formats. +# EYUV or UCB are the same as previous versions of this encoder. +# (All the Y's, then U's then V's, in 4:2:0 subsampling.) +# Other formats, such as Abekas, Phillips, or a general format are +# permissible, the general format is a string of Y's, U's, and V's +# to specify the file order. + +INPUT_FORMAT UCB + +# the conversion statement +# +# Each occurrence of '*' will be replaced by the input file +# +# e.g., if you have a bunch of GIF files, then this might be: +# INPUT_CONVERT giftoppm * +# +# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then: +# INPUT_CONVERT cat *.Y *.U *.V +# +# e.g., if you are grabbing from laser disc you might have something like +# INPUT_CONVERT goto frame *; grabppm +# 'INPUT_CONVERT *' means the files are already in the base file format +# +INPUT_CONVERT * + +# number of frames in a GOP. +# +# since each GOP must have at least one I-frame, the encoder will find the +# the first I-frame after GOP_SIZE frames to start the next GOP +# +# later, will add more flexible GOP signalling +# +GOP_SIZE 16 + +# number of slices in a frame +# +# 1 is a good number. another possibility is the number of macroblock rows +# (which is the height divided by 16) +# +SLICES_PER_FRAME 1 + +# directory to get all input files from (makes this file easier to read) +INPUT_DIR ../input/tennis + +# There are a bunch of ways to specify the input files. +# from a simple one-per-line listing, to the following +# way of numbering them. See the manual for more information. +INPUT +# '*' is replaced by the numbers 01, 02, 03, 04 +# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11 +# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11 +# if I instead do [1-11+3], it would be 1, 4, 7, 10 +# the program assumes none of your input files has a name ending in ']' +# if you do, too bad!!! +# +# +stennis.*.yuv [0-23] +# can have more files here if you want...there is no limit on the number +# of files +END_INPUT + + + +# Many of the remaining options have to do with the motion search and qscale + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels for both P and B frame searches +# specify two numbers if you wish to serc different ranges in the two. +RANGE 10 + +# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC} +PSEARCH_ALG LOGARITHMIC + +# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE} +# +# note that EXHAUSTIVE is really, really, really slow +# +BSEARCH_ALG CROSS2 + +# +# these specify the q-scale for I, P, and B frames +# (values must be between 1 and 31) +# These are the Qscale values for the entire frame in variable bit-rate +# mode, and starting points (but not important) for constant bit rate +# +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# this must be ORIGINAL or DECODED +REFERENCE_FRAME ORIGINAL + +# for parallel parameters see parallel.param in the exmaples subdirectory + +# if you want constant bit-rate mode, specify it as follows (number is bits/sec): +BIT_RATE 1000000 + +# To specify the buffer size (327680 is default, measused in bits, for 16bit words) +BUFFER_SIZE 327680 + +# The frame rate is the number of frames/second (legal values: +# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60 +FRAME_RATE 30 + +# There are many more options, see the users manual for examples.... +# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc. diff --git a/converter/ppm/ppmtompeg/examples/tennis.param b/converter/ppm/ppmtompeg/examples/tennis.param new file mode 100644 index 00000000..978e1904 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis.param @@ -0,0 +1,37 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT cat *.Y *.U *.V + +INPUT_DIR links/tennis + +INPUT +stennis.* [0-149] +END_INPUT + + +# motion vector search parameters + +# MAD or MSE -- must be upper case +ERROR MAD + +# FULL or HALF -- must be upper case +PIXEL HALF + +# means +/- this many pixels +RANGE 8 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + diff --git a/converter/ppm/ppmtompeg/examples/tennis18.param b/converter/ppm/ppmtompeg/examples/tennis18.param new file mode 100644 index 00000000..48979f3e --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis18.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/tennis19.5.param b/converter/ppm/ppmtompeg/examples/tennis19.5.param new file mode 100644 index 00000000..196b7a28 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis19.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-15] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis19.param b/converter/ppm/ppmtompeg/examples/tennis19.param new file mode 100644 index 00000000..542c237c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis19.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis48.param b/converter/ppm/ppmtompeg/examples/tennis48.param new file mode 100644 index 00000000..9db63638 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis48.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis49.param b/converter/ppm/ppmtompeg/examples/tennis49.param new file mode 100644 index 00000000..cbecb035 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis49.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis50.param b/converter/ppm/ppmtompeg/examples/tennis50.param new file mode 100644 index 00000000..bbfe3cb0 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis50.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis52.5.param b/converter/ppm/ppmtompeg/examples/tennis52.5.param new file mode 100644 index 00000000..a00e4322 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis52.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-15] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis52.param b/converter/ppm/ppmtompeg/examples/tennis52.param new file mode 100644 index 00000000..0ae84f00 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis52.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-149] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennis53.param b/converter/ppm/ppmtompeg/examples/tennis53.param new file mode 100644 index 00000000..bc311376 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennis53.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-15] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG EXHAUSTIVE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/tennisbug.param b/converter/ppm/ppmtompeg/examples/tennisbug.param new file mode 100644 index 00000000..4a655b4a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/tennisbug.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IPPPPPPPPPPP + +OUTPUT /n/picasso/users/keving/encode/output/tennis.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR ../input/tennis + +INPUT +stennis.*.yuv [0-49] +END_INPUT + +# quality parameters + +IQSCALE 1 +PQSCALE 1 +BQSCALE 1 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/testp.param b/converter/ppm/ppmtompeg/examples/testp.param new file mode 100644 index 00000000..ea8dee18 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/testp.param @@ -0,0 +1,45 @@ +# speed test parameter file + +PATTERN IPPPPPPPPP + +OUTPUT /n/picasso/users/keving/encode/output/testp.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input + +INPUT +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +me.0.ppm +END_INPUT + +# quality parameters + +IQSCALE 4 +PQSCALE 4 +BQSCALE 4 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/walk.param b/converter/ppm/ppmtompeg/examples/walk.param new file mode 100644 index 00000000..52be9d2e --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk.param @@ -0,0 +1,61 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/walk1.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-1800] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/walk1.param b/converter/ppm/ppmtompeg/examples/walk1.param new file mode 100644 index 00000000..52be9d2e --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk1.param @@ -0,0 +1,61 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/walk1.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-1800] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/walk18.param b/converter/ppm/ppmtompeg/examples/walk18.param new file mode 100644 index 00000000..80ed48f3 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk18.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-200] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/walk19.5.param b/converter/ppm/ppmtompeg/examples/walk19.5.param new file mode 100644 index 00000000..7fb724d1 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk19.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-16] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk19.param b/converter/ppm/ppmtompeg/examples/walk19.param new file mode 100644 index 00000000..acc8f627 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk19.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-200] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk2.param b/converter/ppm/ppmtompeg/examples/walk2.param new file mode 100644 index 00000000..cbb28705 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk2.param @@ -0,0 +1,61 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/walk2.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-1800] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 6 +PQSCALE 8 +BQSCALE 15 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/examples/walk3.param b/converter/ppm/ppmtompeg/examples/walk3.param new file mode 100644 index 00000000..86a30812 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk3.param @@ -0,0 +1,61 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/walk3.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-1800] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 6 +PQSCALE 8 +BQSCALE 15 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk4.param b/converter/ppm/ppmtompeg/examples/walk4.param new file mode 100644 index 00000000..12d1f505 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk4.param @@ -0,0 +1,61 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +OUTPUT /n/picasso/users/keving/encode/output/walk4.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-1800] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 4 +PQSCALE 6 +BQSCALE 10 + +# motion vector search parameters + +PIXEL HALF + +RANGE 7 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk48.param b/converter/ppm/ppmtompeg/examples/walk48.param new file mode 100644 index 00000000..2c6df697 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk48.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-200] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG SUBSAMPLE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk49.param b/converter/ppm/ppmtompeg/examples/walk49.param new file mode 100644 index 00000000..72c17a94 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk49.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-200] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk5.param b/converter/ppm/ppmtompeg/examples/walk5.param new file mode 100644 index 00000000..e792064f --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk5.param @@ -0,0 +1,62 @@ +# speed test parameter file + +#PATTERN IBBPBBPBBPBBPBB +PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/walk5.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PNM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-80] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 1 +PQSCALE 6 +BQSCALE 10 + +# motion vector search parameters + +PIXEL HALF + +RANGE 7 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk50.param b/converter/ppm/ppmtompeg/examples/walk50.param new file mode 100644 index 00000000..8f4d27e6 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk50.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-200] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG EXHAUSTIVE +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk52.5.param b/converter/ppm/ppmtompeg/examples/walk52.5.param new file mode 100644 index 00000000..f9d038f6 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk52.5.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-16] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk52.param b/converter/ppm/ppmtompeg/examples/walk52.param new file mode 100644 index 00000000..69626d2c --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk52.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-200] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk53.param b/converter/ppm/ppmtompeg/examples/walk53.param new file mode 100644 index 00000000..72f57c7a --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk53.param @@ -0,0 +1,35 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/walk19.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +f.*.Z [1-16] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG EXHAUSTIVE + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/examples/walk93.param b/converter/ppm/ppmtompeg/examples/walk93.param new file mode 100644 index 00000000..243d6032 --- /dev/null +++ b/converter/ppm/ppmtompeg/examples/walk93.param @@ -0,0 +1,62 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB +#PATTERN I +OUTPUT /n/picasso/users/keving/encode/output/walk93.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +BASE_FILE_FORMAT PPM +YUV_SIZE 320x240 + +INPUT_CONVERT zcat * + +INPUT_DIR /n/zonker/cluster/keving/walk + +INPUT +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +title.ppm.Z +f.*.Z [1-2] +END_INPUT + +PARALLEL_TEST_FRAMES 10 +PARALLEL_TIME_CHUNKS 30 + + +IO_SERVER_CONVERT * +SLAVE_CONVERT zcat * + +PARALLEL +#charlie-brown keving ~keving/encode/bin/dec-alpha/mpeg_encode +#woodstock keving ~keving/encode/bin/dec-alpha/mpeg_encode +END_PARALLEL + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 7 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME DECODED diff --git a/converter/ppm/ppmtompeg/file.c b/converter/ppm/ppmtompeg/file.c new file mode 100644 index 00000000..ae741962 --- /dev/null +++ b/converter/ppm/ppmtompeg/file.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/file.c,v 1.2 1993/06/30 20:06:09 keving Exp $ + * $Log: file.c,v $ + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/06/03 21:08:08 keving + * nothing + * + */ + +#include "tk.h" + +#include "all.h" + +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <time.h> +#include <string.h> +#include <dirent.h> +#include <strings.h> + +#define MAX_FILES 1000 +#define MAX_NAME_LEN 256 +#define MAX_STRING_LEN MAX_NAME_LEN + +typedef int boolean; +#define TRUE 1 +#define FALSE 0 + +extern char currentPath[MAXPATHLEN]; + +char globString[1024]; + +static DIR *dfd; + +void ResetPath(void); +int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, + char **argv); +int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, + char **argv); +void SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN], + boolean *dirList, int permute[]); + +static void UpdatePath(Tcl_Interp *interp, char *directory); +static boolean MatchesGlob(char *string, char *glob); + + + +void ResetPath() +{ + if ( getwd(currentPath) == 0 ) + { + fprintf(stderr, "Error getting pathname!!!\n"); + exit(1); + } + + strcpy(¤tPath[strlen(currentPath)], "/"); + + dfd = opendir(currentPath); + if ( dfd == NULL ) + { + fprintf(stderr, "can't open '%s'\n", currentPath); + exit(1); + } +} + + +static void UpdatePath(Tcl_Interp *interp, char *directory) +{ + int length; + char *charPtr; + + length = strlen(currentPath); + + if ( strcmp(directory, "./") == 0 ) + return /* nothing */ ; + else if ( strcmp(directory, "../") == 0 ) + { + /* delete backwards up to '/' */ + + if ( length < 2 ) + { + fprintf(stderr, "Error: backing up from root directory!!!\n"); + exit(1); + } + + charPtr = ¤tPath[length-2]; + while ( (charPtr != currentPath) && (*charPtr != '/') ) + charPtr--; + charPtr++; /* leave the '/' */ + *charPtr = '\0'; + } + else + { + strcpy(¤tPath[length], directory); + } +} + + +int ChangeDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, + char **argv) +{ + char *directory = argv[1]; + + UpdatePath(interp, directory); + + fprintf(stdout, "Opening directory: '%s'\n", currentPath); + + dfd = opendir(currentPath); + if ( dfd == NULL ) + { + fprintf(stderr, "can't open '%s'\n", currentPath); + return TCL_OK; /* shouldn't, really */ + } + + return TCL_OK; +} + + +int ListDirectory(ClientData nulldata, Tcl_Interp *interp, int argc, + char **argv) +{ + struct dirent *dp; + struct stat stbuf; + char command[256]; + char fileName[MAX_FILES][MAX_NAME_LEN]; + boolean dirList[MAX_FILES]; + int permute[MAX_FILES]; + int fileCount = 0; + register int index; + char fullName[MAXPATHLEN]; + char *restPtr; + + sprintf(command, "ShowCurrentDirectory %s", currentPath); + Tcl_Eval(interp, command, 0, (char **) NULL); + + if ( dfd == NULL ) + { + fprintf(stderr, "TRIED TO LIST NULL DIRECTORY\n"); + + return TCL_OK; + } + +/* check if root directory */ + if ( strlen(currentPath) != 1 ) + { + sprintf(fileName[fileCount], "../"); + dirList[fileCount] = TRUE; + fileCount++; + } + + strcpy(fullName, currentPath); + restPtr = &fullName[strlen(fullName)]; + + while ( (dp = readdir(dfd)) != NULL ) + { + strcpy(restPtr, dp->d_name); + stat(fullName, &stbuf); + + if ( dp->d_name[0] != '.' ) + { + if ( S_ISDIR(stbuf.st_mode) ) + { + sprintf(fileName[fileCount], "%s/", dp->d_name); + dirList[fileCount] = TRUE; + fileCount++; + } + else + { + if ( MatchesGlob(dp->d_name, globString) ) + { + strcpy(fileName[fileCount], dp->d_name); + dirList[fileCount] = FALSE; + fileCount++; + } + } + } + } + + SortFiles(fileCount, fileName, dirList, permute); + + for ( index = 0; index < fileCount; index++ ) + { + sprintf(command, "AddBrowseFile %s", fileName[permute[index]]); + Tcl_Eval(interp, command, 0, (char **) NULL); + } + + closedir(dfd); + + return TCL_OK; +} + + +void SortFiles(int numStrings, char strings[MAX_FILES][MAX_NAME_LEN], + boolean *dirList, int permute[]) +{ + register int i, j; + int temp; + int numDirs; + int ptr; + + for ( i = 0; i < numStrings; i++ ) + permute[i] = i; + + /* put all directories at front */ + numDirs = 0; + ptr = numStrings-1; + while ( numDirs != ptr ) + { + /* go past dirs */ + while ( (numDirs < ptr) && (dirList[permute[numDirs]]) ) + numDirs++; + + /* go past non-dirs */ + while ( (numDirs < ptr) && (! dirList[permute[ptr]]) ) + ptr--; + + if ( numDirs != ptr ) + { + temp = permute[numDirs]; + permute[numDirs] = ptr; + permute[ptr] = temp; + } + } + + if ( dirList[permute[numDirs]] ) + numDirs++; + + for ( i = 0; i < numDirs; i++ ) + for ( j = i+1; j < numDirs; j++ ) + { + if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 ) + { + temp = permute[j]; + permute[j] = permute[i]; + permute[i] = temp; + } + } + + for ( i = numDirs; i < numStrings; i++ ) + for ( j = i+1; j < numStrings; j++ ) + { + if ( strcmp(&strings[permute[j]][0], &strings[permute[i]][0]) < 0 ) + { + temp = permute[j]; + permute[j] = permute[i]; + permute[i] = temp; + } + } +} + + +int SetBrowseGlob (ClientData nulldata, Tcl_Interp *interp, + int argc, char **argv) +{ + if (argc == 2 ) + { + strcpy(globString, argv[1]); + + fprintf(stdout, "GLOB: %s\n", globString); + + return TCL_OK; + } + + Tcl_AppendResult (interp, + "wrong args: should be \"", argv[0]," string\"", (char *) NULL); + return TCL_ERROR; +} + + +static boolean MatchesGlob(char *string, char *glob) +{ + char *stringRight, *globRight; + + while ( (*glob != '\0') && (*glob != '*') ) /* match left side */ + { + if ( (*string == '\0') || (*string != *glob) ) + return FALSE; + string++; + glob++; + } + + if ( *glob == '\0' ) /* no star */ + return TRUE; + + /* now match right side */ + stringRight = &string[strlen(string)-1]; + globRight = &glob[strlen(glob)-1]; + + while ( *globRight != '*' ) + { + if ( (stringRight < string) || (*stringRight != *globRight) ) + return FALSE; + globRight--; + stringRight--; + } + + return TRUE; +} diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c new file mode 100644 index 00000000..09f46f66 --- /dev/null +++ b/converter/ppm/ppmtompeg/frame.c @@ -0,0 +1,836 @@ +/*===========================================================================* + * frame.c * + * * + * basic frame procedures * + * * + * EXPORTED PROCEDURES: * + * Frame_Init * + * Frame_Exit * + * Frame_New * + * Frame_Free * + * Frame_AllocBlocks * + * Frame_AllocYCC * + * Frame_AllocDecoded * + * Frame_AllocHalf * + * Frame_Resize * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#include "mallocvar.h" + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "frame.h" +#include "fsize.h" +#include "dct.h" + +/*===========* + * CONSTANTS * + *===========*/ + +/* The maximum number of B-Frames allowed between reference frames. */ +#define B_FRAME_RUN 16 + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +static MpegFrame * frameMemory[B_FRAME_RUN+2]; +static unsigned int numOfFrames; + + +/*==================================================== +* Resize_Array_Width +* +* This function will resize any array width up +* or down in size. The algorithm is based on the +* least common multiple approach more commonly +* used in audio frequency adjustments. +*=====================================================*/ +static void +Resize_Array_Width(uint8 ** const inarray, + int const in_x, + int const in_y, + uint8 ** const outarray, + int const out_x) { + + unsigned int i; + int in_total; + int out_total; + uint8 *inptr; + uint8 *outptr; + uint8 pointA,pointB; + /* double slope,diff; */ + + for (i = 0; i < in_y; ++i) { /* For each row */ + unsigned int j; + inptr = &inarray[i][0]; + outptr = &outarray[i][0]; + in_total = 0; + out_total = 0; + for (j=0; j < out_x; ++j) { /* For each output value */ + if (in_total == out_total) { + *outptr = *inptr; + outptr++; + out_total=out_total+in_x; + while(in_total < out_total){ + in_total = in_total + out_x; + ++inptr; + } + if (in_total > out_total) { + in_total = in_total - out_x; + --inptr; + } + } else { + pointA = *inptr; + ++inptr; + pointB = *inptr; + --inptr; +#if 0 + /*Interpolative solution */ + slope = ((double)(pointB -pointA))/((double)(out_x)); + diff = (((double)(out_total - in_total))); + if (diff < (out_x/2)){ + *outptr = (pointA + (uint8)(slope*diff)); + } else { + *outptr = (pointB - + (uint8)(slope*(((float)(out_x)) - diff))); + } +#endif + /* Non-Interpolative solution */ + *outptr = *inptr; + + ++outptr; + out_total = out_total + in_x; + while(in_total < out_total) { + in_total = in_total + out_x; + ++inptr; + } + if (in_total > out_total) { + in_total = in_total - out_x; + --inptr; + } + } /* end if */ + } /* end for each output value */ + } /* end for each row */ +} /* end main */ + + + +/*============================== +* Resize_Array_Height +* +* Resize any array height larger or smaller. +* Same as Resize_array_Width except pointer +* manipulation must change. +*===============================*/ +static void +Resize_Array_Height(uint8 ** const inarray, + int const in_x, + int const in_y, + uint8 ** const outarray, + int const out_y) { + + unsigned int i; + + for(i=0; i < in_x; ++i){ /* for each column */ + int in_total; + int out_total; + uint8 pointA, pointB; + double slope, diff; + unsigned int j; + int k; + + in_total = 0; + out_total = 0; + k = 0; + for(j=0; j < out_y; ++j){ /* for each output value */ + if (in_total == out_total) { + outarray[j][i] = inarray[k][i]; + out_total=out_total+in_y; + while(in_total < out_total){ + in_total = in_total + out_y; + ++k; + } + if (in_total > out_total) { + in_total = in_total - out_y; + --k; + } + } else { + pointA = inarray[k][i]; + if (k != (in_y -1)) { + pointB = inarray[k+1][i]; + } else + pointB = pointA; + /* Interpolative case */ + slope = ((double)(pointB -pointA))/(double)(out_y); + diff = (double)(out_total - in_total); + /* outarray[j][i] = (inarray[k][i] + (uint8)(slope*diff)); */ + /* Non-Interpolative case */ + outarray[j][i] = inarray[k][i]; + out_total = out_total + in_y; + while (in_total < out_total) { + in_total = in_total + out_y; + ++k; + } + if (in_total > out_total){ + in_total = in_total - out_y; + --k; + } + } + } + } +} + + + +/*======================================================== +* Resize_Width +*======================================================*/ +static void +Resize_Width(MpegFrame * const omfrw, + MpegFrame * const mfrw, + int const in_x, + int const in_y, + int const out_x) { + + int y; + + omfrw->orig_y = NULL; + Fsize_x = out_x; + + /* Allocate new frame memory */ + MALLOCARRAY(omfrw->orig_y, Fsize_y); + ERRCHK(omfrw->orig_y, "malloc"); + for (y = 0; y < Fsize_y; ++y) { + MALLOCARRAY(omfrw->orig_y[y], out_x); + ERRCHK(omfrw->orig_y[y], "malloc"); + } + + MALLOCARRAY(omfrw->orig_cr, Fsize_y / 2); + ERRCHK(omfrw->orig_cr, "malloc"); + for (y = 0; y < Fsize_y / 2; ++y) { + MALLOCARRAY(omfrw->orig_cr[y], out_x / 2); + ERRCHK(omfrw->orig_cr[y], "malloc"); + } + + MALLOCARRAY(omfrw->orig_cb, Fsize_y / 2); + ERRCHK(omfrw->orig_cb, "malloc"); + for (y = 0; y < Fsize_y / 2; ++y) { + MALLOCARRAY(omfrw->orig_cb[y], out_x / 2); + ERRCHK(omfrw->orig_cb[y], "malloc"); + } + + if (referenceFrame == ORIGINAL_FRAME) { + omfrw->ref_y = omfrw->orig_y; + omfrw->ref_cr = omfrw->orig_cr; + omfrw->ref_cb = omfrw->orig_cb; + } + + /* resize each component array separately */ + Resize_Array_Width(mfrw->orig_y, in_x, in_y, omfrw->orig_y, out_x); + Resize_Array_Width(mfrw->orig_cr, (in_x/2), (in_y/2), omfrw->orig_cr, + (out_x/2)); + Resize_Array_Width(mfrw->orig_cb, (in_x/2), (in_y/2), omfrw->orig_cb, + (out_x/2)); + + /* Free old frame memory */ + if (mfrw->orig_y) { + unsigned int i; + for (i = 0; i < in_y; ++i) { + free(mfrw->orig_y[i]); + } + free(mfrw->orig_y); + + for (i = 0; i < in_y / 2; ++i) { + free(mfrw->orig_cr[i]); + } + free(mfrw->orig_cr); + + for (i = 0; i < in_y / 2; ++i) { + free(mfrw->orig_cb[i]); + } + free(mfrw->orig_cb); + } +} + + + +/*======================================================= +* Resize_Height +* +* Resize Frame height up or down +*=======================================================*/ +static void +Resize_Height(MpegFrame * const omfrh, + MpegFrame * const mfrh, + int const in_x, + int const in_y, + int const out_y) { + + unsigned int y; + + Fsize_y = out_y; + + /* Allocate new frame memory */ + MALLOCARRAY(omfrh->orig_y, out_y); + ERRCHK(omfrh->orig_y, "malloc"); + for (y = 0; y < out_y; ++y) { + MALLOCARRAY(omfrh->orig_y[y], Fsize_x); + ERRCHK(omfrh->orig_y[y], "malloc"); + } + + MALLOCARRAY(omfrh->orig_cr, out_y / 2); + ERRCHK(omfrh->orig_cr, "malloc"); + for (y = 0; y < out_y / 2; ++y) { + MALLOCARRAY(omfrh->orig_cr[y], Fsize_x / 2); + ERRCHK(omfrh->orig_cr[y], "malloc"); + } + + MALLOCARRAY(omfrh->orig_cb, out_y / 2); + ERRCHK(omfrh->orig_cb, "malloc"); + for (y = 0; y < out_y / 2; ++y) { + MALLOCARRAY(omfrh->orig_cb[y], Fsize_x / 2); + ERRCHK(omfrh->orig_cb[y], "malloc"); + } + + if (referenceFrame == ORIGINAL_FRAME) { + omfrh->ref_y = omfrh->orig_y; + omfrh->ref_cr = omfrh->orig_cr; + omfrh->ref_cb = omfrh->orig_cb; + } + + /* resize component arrays separately */ + Resize_Array_Height(mfrh->orig_y, in_x, in_y, omfrh->orig_y, out_y); + Resize_Array_Height(mfrh->orig_cr, (in_x/2), (in_y/2), omfrh->orig_cr, + (out_y/2)); + Resize_Array_Height(mfrh->orig_cb, (in_x/2), (in_y/2), omfrh->orig_cb, + (out_y/2)); + + /* Free old frame memory */ + if (mfrh->orig_y) { + unsigned int i; + for (i = 0; i < in_y; ++i) { + free(mfrh->orig_y[i]); + } + free(mfrh->orig_y); + + for (i = 0; i < in_y / 2; ++i) { + free(mfrh->orig_cr[i]); + } + free(mfrh->orig_cr); + + for (i = 0; i < in_y / 2; ++i) { + free(mfrh->orig_cb[i]); + } + free(mfrh->orig_cb); + } +} + + + +/*===========================================================================* + * + * Frame_Init + * + * initializes the memory associated with all frames ever + * If the input is not coming in from stdin, only 3 frames are needed ; + * else, the program must create frames equal to the greatest distance + * between two reference frames to hold the B frames while it is parsing + * the input from stdin. + * + * RETURNS: nothing + * + * SIDE EFFECTS: frameMemory, numOfFrames + * + *===========================================================================*/ +void +Frame_Init(unsigned int const numOfFramesRequested) { + int idx; + + numOfFrames = numOfFramesRequested; + + for (idx = 0; idx < numOfFrames; ++idx) { + MALLOCVAR(frameMemory[idx]); + frameMemory[idx]->inUse = FALSE; + frameMemory[idx]->orig_y = NULL; + frameMemory[idx]->y_blocks = NULL; + frameMemory[idx]->decoded_y = NULL; + frameMemory[idx]->halfX = NULL; + frameMemory[idx]->next = NULL; + } +} + + +/*===========================================================================* + * + * FreeFrame + * + * frees the memory associated with the given frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +FreeFrame(MpegFrame * const frameP) { + + if (frameP) { + if (frameP->orig_y) { + unsigned int i; + for (i = 0; i < Fsize_y; ++i) + free(frameP->orig_y[i]); + free(frameP->orig_y); + + for (i = 0; i < (Fsize_y / 2); ++i) + free(frameP->orig_cr[i]); + free(frameP->orig_cr); + + for (i = 0; i < (Fsize_y / 2); ++i) + free(frameP->orig_cb[i]); + free(frameP->orig_cb); + } + if (frameP->decoded_y) { + unsigned int i; + for (i = 0; i < Fsize_y; ++i) + free(frameP->decoded_y[i]); + free(frameP->decoded_y); + + for (i = 0; i < (Fsize_y / 2); ++i) + free(frameP->decoded_cr[i]); + free(frameP->decoded_cr); + + for (i = 0; i < (Fsize_y / 2); ++i) + free(frameP->decoded_cb[i]); + free(frameP->decoded_cb); + } + + if (frameP->y_blocks) { + unsigned int i; + for (i = 0; i < Fsize_y / DCTSIZE; ++i) + free(frameP->y_blocks[i]); + free(frameP->y_blocks); + + for (i = 0; i < Fsize_y / (2 * DCTSIZE); ++i) + free(frameP->cr_blocks[i]); + free(frameP->cr_blocks); + + for (i = 0; i < Fsize_y / (2 * DCTSIZE); ++i) + free(frameP->cb_blocks[i]); + free(frameP->cb_blocks); + } + if (frameP->halfX) { + unsigned int i; + for ( i = 0; i < Fsize_y; ++i ) + free(frameP->halfX[i]); + free(frameP->halfX); + + for (i = 0; i < Fsize_y-1; ++i) + free(frameP->halfY[i]); + free(frameP->halfY); + + for (i = 0; i < Fsize_y-1; ++i) + free(frameP->halfBoth[i]); + free(frameP->halfBoth); + } + free(frameP); + } +} + + + +/*===========================================================================* + * + * Frame_Exit + * + * frees the memory associated with frames + * + * RETURNS: nothing + * + * SIDE EFFECTS: frameMemory + * + *===========================================================================*/ +void +Frame_Exit(void) { + + int idx; + + for (idx = 0; idx < numOfFrames; ++idx) { + FreeFrame(frameMemory[idx]); + } +} + + +/*===========================================================================* + * + * Frame_Free + * + * frees the given frame -- allows it to be re-used + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_Free(MpegFrame * const frameP) { + frameP->inUse = FALSE; +} + + + +/*===========================================================================* + * + * GetUnusedFrame + * + * return an unused frame + * + * RETURNS: the frame + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static MpegFrame * +GetUnusedFrame() { + unsigned int idx; + + for (idx = 0; idx < numOfFrames; ++idx) { + if (!frameMemory[idx]->inUse) { + frameMemory[idx]->inUse = TRUE; + break; + } + } + if (idx >= numOfFrames) { + fprintf(stderr, "ERROR: No unused frames!!!\n"); + fprintf(stderr, " If you are using stdin for input, " + "it is likely that you have too many\n"); + fprintf(stderr, " B-frames between two reference frames. " + "See the man page for help.\n"); + exit(1); + } + return frameMemory[idx]; +} + + + +/*===========================================================================* + * + * ResetFrame + * + * reset a frame to the given id and type + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ResetFrame(int const id, + int const type, + MpegFrame * const frame) { + + switch (type) { + case 'i': + frame->type = TYPE_IFRAME; + break; + case 'p': + frame->type = TYPE_PFRAME; + break; + case 'b': + frame->type = TYPE_BFRAME; + break; + default: + fprintf(stderr, "Invalid MPEG frame type %c\n", type); + exit(1); + } + + frame->id = id; + frame->halfComputed = FALSE; + frame->next = NULL; +} + + + +/*===========================================================================* + * + * Frame_New + * + * finds a frame that isn't currently being used and resets it + * + * RETURNS: the frame + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +MpegFrame * +Frame_New(int const id, + int const type) { + + MpegFrame *frame; + + frame = GetUnusedFrame(); + ResetFrame(id, type, frame); + + return frame; +} + + + +/*===========================================================================* + * + * Frame_AllocBlocks + * + * allocate memory for blocks for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocBlocks(MpegFrame * const frameP) { + + if (frameP->y_blocks != NULL) { + /* already allocated */ + } else { + int const dctx = Fsize_x / DCTSIZE; + int const dcty = Fsize_y / DCTSIZE; + + unsigned int i; + + MALLOCARRAY(frameP->y_blocks, dcty); + ERRCHK(frameP->y_blocks, "malloc"); + for (i = 0; i < dcty; ++i) { + MALLOCARRAY(frameP->y_blocks[i], dctx); + ERRCHK(frameP->y_blocks[i], "malloc"); + } + + MALLOCARRAY(frameP->cr_blocks, dcty / 2); + ERRCHK(frameP->cr_blocks, "malloc"); + MALLOCARRAY(frameP->cb_blocks, dcty / 2); + ERRCHK(frameP->cb_blocks, "malloc"); + for (i = 0; i < (dcty / 2); ++i) { + MALLOCARRAY(frameP->cr_blocks[i], dctx / 2); + ERRCHK(frameP->cr_blocks[i], "malloc"); + MALLOCARRAY(frameP->cb_blocks[i], dctx / 2); + ERRCHK(frameP->cb_blocks[i], "malloc"); + } + } +} + + + +/*===========================================================================* + * + * Frame_AllocYCC + * + * allocate memory for YCC info for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocYCC(MpegFrame * const frameP) { + + if (frameP->orig_y != NULL) { + /* already allocated */ + } else { + unsigned int y; + + DBG_PRINT(("ycc_calc:\n")); + /* + * first, allocate tons of memory + */ + MALLOCARRAY(frameP->orig_y, Fsize_y); + ERRCHK(frameP->orig_y, "malloc"); + for (y = 0; y < Fsize_y; ++y) { + MALLOCARRAY(frameP->orig_y[y], Fsize_x); + ERRCHK(frameP->orig_y[y], "malloc"); + } + + MALLOCARRAY(frameP->orig_cr, Fsize_y / 2); + ERRCHK(frameP->orig_cr, "malloc"); + for (y = 0; y < (Fsize_y / 2); ++y) { + MALLOCARRAY(frameP->orig_cr[y], Fsize_x / 2); + ERRCHK(frameP->orig_cr[y], "malloc"); + } + + MALLOCARRAY(frameP->orig_cb, Fsize_y / 2); + ERRCHK(frameP->orig_cb, "malloc"); + for (y = 0; y < (Fsize_y / 2); ++y) { + MALLOCARRAY(frameP->orig_cb[y], Fsize_x / 2); + ERRCHK(frameP->orig_cb[y], "malloc"); + } + + if (referenceFrame == ORIGINAL_FRAME) { + frameP->ref_y = frameP->orig_y; + frameP->ref_cr = frameP->orig_cr; + frameP->ref_cb = frameP->orig_cb; + } + } +} + + + +/*===========================================================================* + * + * Frame_AllocHalf + * + * allocate memory for half-pixel values for the given frame, if required + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocHalf(MpegFrame * const frameP) { + + if (frameP->halfX != NULL) { + } else { + unsigned int y; + + MALLOCARRAY(frameP->halfX, Fsize_y); + ERRCHK(frameP->halfX, "malloc"); + for (y = 0; y < Fsize_y; ++y) { + MALLOCARRAY(frameP->halfX[y], Fsize_x - 1); + ERRCHK(frameP->halfX[y], "malloc"); + } + MALLOCARRAY(frameP->halfY, Fsize_y - 1); + ERRCHK(frameP->halfY, "malloc"); + for (y = 0; y < Fsize_y - 1; ++y) { + MALLOCARRAY(frameP->halfY[y], Fsize_x); + ERRCHK(frameP->halfY[y], "malloc"); + } + MALLOCARRAY(frameP->halfBoth, Fsize_y - 1); + ERRCHK(frameP->halfBoth, "malloc"); + for (y = 0; y < Fsize_y - 1; ++y) { + MALLOCARRAY(frameP->halfBoth[y], Fsize_x - 1); + ERRCHK(frameP->halfBoth[y], "malloc"); + } + } +} + + + +/*===========================================================================* + * + * Frame_AllocDecoded + * + * allocate memory for decoded frame for the given frame, if required + * if makeReference == TRUE, then makes it reference frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Frame_AllocDecoded(MpegFrame * const frameP, + boolean const makeReference) { + + if (frameP->decoded_y != NULL) { + /* already allocated */ + } else { + unsigned int y; + + /* allocate memory for decoded image */ + /* can probably reuse original image memory, but may decide to use + it for some reason, so do it this way at least for now -- more + flexible + */ + MALLOCARRAY(frameP->decoded_y, Fsize_y); + ERRCHK(frameP->decoded_y, "malloc"); + for (y = 0; y < Fsize_y; ++y) { + MALLOCARRAY(frameP->decoded_y[y], Fsize_x); + ERRCHK(frameP->decoded_y[y], "malloc"); + } + + MALLOCARRAY(frameP->decoded_cr, Fsize_y / 2); + ERRCHK(frameP->decoded_cr, "malloc"); + for (y = 0; y < (Fsize_y / 2); ++y) { + MALLOCARRAY(frameP->decoded_cr[y], Fsize_x / 2); + ERRCHK(frameP->decoded_cr[y], "malloc"); + } + + MALLOCARRAY(frameP->decoded_cb, Fsize_y / 2); + ERRCHK(frameP->decoded_cb, "malloc"); + for (y = 0; y < (Fsize_y / 2); ++y) { + MALLOCARRAY(frameP->decoded_cb[y], Fsize_x / 2); + ERRCHK(frameP->decoded_cb[y], "malloc"); + } + + if (makeReference) { + frameP->ref_y = frameP->decoded_y; + frameP->ref_cr = frameP->decoded_cr; + frameP->ref_cb = frameP->decoded_cb; + } + } +} + + + +/*=============================================================== + * + * Frame_Resize by James Boucher + * Boston University Multimedia Communications Lab + * + * This function takes the mf input frame, read in READFrame(), + * and resizes all the input component arrays to the output + * dimensions specified in the parameter file as OUT_SIZE. + * The new frame is returned with the omf pointer. As well, + * the values of Fsize_x and Fsize_y are adjusted. + ***************************************************************/ +void +Frame_Resize(MpegFrame * const omf, + MpegFrame * const mf, + int const insize_x, + int const insize_y, + int const outsize_x, + int const outsize_y) { + + MpegFrame * frameAP; /* intermediate frame */ + + MALLOCVAR_NOFAIL(frameAP); + + if (insize_x != outsize_x && insize_y != outsize_y) { + Resize_Width(frameAP, mf, insize_x, insize_y, outsize_x); + Resize_Height(omf, frameAP, outsize_x, insize_y, outsize_y); + } else + if (insize_x ==outsize_x && insize_y != outsize_y) { + Resize_Height(omf, mf, insize_x, insize_y, outsize_y); + } else + if (insize_x !=outsize_x && insize_y == outsize_y) { + Resize_Width(omf, mf, insize_x, insize_y, outsize_x); + } else + exit(1); + + free(frameAP); + free(mf); +} diff --git a/converter/ppm/ppmtompeg/frametype.c b/converter/ppm/ppmtompeg/frametype.c new file mode 100644 index 00000000..b7daacc9 --- /dev/null +++ b/converter/ppm/ppmtompeg/frametype.c @@ -0,0 +1,365 @@ +/*===========================================================================* + * frametype.c * + * * + * procedures to keep track of frame types (I, P, B) * + * * + * EXPORTED PROCEDURES: * + * FType_Type * + * FType_FutureRef * + * FType_PastRef * + * * + * SYNOPSIS * + * FType_Type returns the type of the given numbered frame * + * FType_FutureRef returns the number of the future reference frame * + * FType_PastRef returns the number of the past reference frame * + * * + * 00.12.07 change malloc from frameTable to calloc to fix bug + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "mallocvar.h" +#include "all.h" +#include "frames.h" +#include "frame.h" +#include "param.h" +#include "specifics.h" +#include "frametype.h" + + +static FrameTable *frameTable=NULL; +static boolean use_cache = FALSE; +static int firstI = 0; +static int numFrames; + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int framePatternLen; +extern char * framePattern; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * FType_Type + * + * returns the type of the given numbered frame + * + * RETURNS: the type + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +char +FType_Type(unsigned int const frameNum) { + + char const patternedType = framePattern[frameNum % framePatternLen]; + + char retval; + + if (use_cache) + return frameTable[frameNum].typ; + + if (frameNum+1 == numFrames) { + /* It's the last frame in the sequence. If the pattern says it's + a B, we convert it to I because a B frame makes no sense as the + last frame of a sequence. + */ + if (patternedType == 'b') + retval = 'i'; + else + retval = patternedType; + } else { + if (specificsOn) { + static int lastI = -1; + int newtype; + + if (lastI > frameNum) + lastI = -1; + newtype = SpecTypeLookup(frameNum); + switch (newtype) { + case 1: + lastI = frameNum; + retval = 'i'; + break; + case 2: + retval = 'p'; + break; + case 3: + retval = 'b'; + break; + default: + if (lastI != -1) { + unsigned int const pretendFrameNumber = + (frameNum - lastI + firstI) % framePatternLen; + retval = framePattern[pretendFrameNumber]; + } else + retval = patternedType; + } + } else + retval = patternedType; + } + return retval; +} + + + +unsigned int +FType_FutureRef(unsigned int const currFrameNum) { +/*---------------------------------------------------------------------------- + Return the number of the future reference frame for the B frame + 'currentFrameNum'. +-----------------------------------------------------------------------------*/ + unsigned int retval; + + if (use_cache) { + retval = frameTable[currFrameNum].next->number; + } else { + int const index = currFrameNum % framePatternLen; + int const futureIndex = frameTable[index].next->number; + unsigned int const patternedFutureRef = + currFrameNum + + (((futureIndex-index)+framePatternLen) % framePatternLen); + + retval = MIN(patternedFutureRef, numFrames-1); + } + return retval; +} + + + +/*===========================================================================* + * + * FType_PastRef + * + * returns the number of the past reference frame + * + * RETURNS: the number + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +FType_PastRef(currFrameNum) + int currFrameNum; +{ + int index; + int pastIndex; + + if (use_cache) { + return frameTable[currFrameNum].prev->number; + } else { + index = currFrameNum % framePatternLen; + pastIndex = frameTable[index].prev->number; + + return currFrameNum - + (((index-pastIndex)+framePatternLen) % framePatternLen); + } +} + + +/*===========================================================================* + * + * SetFramePattern + * + * set the IPB pattern; calls ComputeFrameTable to set up table + * + * RETURNS: nothing + * + * SIDE EFFECTS: framePattern, framePatternLen, frameTable + * + *===========================================================================*/ +#define SIMPLE_ASCII_UPPER(x) (((x)>='a') ? ((x)-'a'+'A') : (x)) +void +SetFramePattern(const char * const pattern) { + unsigned int const len = strlen(pattern); + + char *buf; + unsigned int index; + + if (!pattern) + pm_error("INTERNAL ERROR: pattern cannot be NULL " + "in SetFramePattern"); + + if (SIMPLE_ASCII_UPPER(pattern[0]) != 'I') { + unsigned int index; + for (index = 0; index < len; ++index) { + if (SIMPLE_ASCII_UPPER(pattern[index]) == 'I') { + break; + } else if (SIMPLE_ASCII_UPPER(pattern[index]) == 'P') + pm_error("first reference frame must be 'i', not '%c'", + pattern[index]); + } + } + + buf = (char *)malloc(sizeof(char)*(len+1)); + ERRCHK(buf, "malloc"); + + firstI = -1; + for (index = 0; index < len; index++) { + switch( SIMPLE_ASCII_UPPER(pattern[index]) ) { + case 'I': + buf[index] = 'i'; + if (firstI == -1) firstI = index; + break; + case 'P': + buf[index] = 'p'; + break; + case 'B': + buf[index] = 'b'; + break; + default: + pm_error("Invalid MPEG Frame type '%c'.", pattern[index]); + } + } + buf[len] = 0; + + if (firstI == -1) + pm_error("Must have an I-frame in PATTERN"); + + framePattern = buf; + framePatternLen = len; + + /* Used to ComputeFrameTable(), but now must wait until param + parsed. (STDIN or not) + */ +} + + + +void +ComputeFrameTable(unsigned int const numFramesArg) { +/*---------------------------------------------------------------------------- + Compute a table of I, P, B frames to help in determining dependencie + + 'numFrames' == 0 means number of frames is not known at this time. +-----------------------------------------------------------------------------*/ + int index; + FrameTable *lastI, *lastIP, *firstB, *secondIP; + FrameTable *ptr; + char typ; + int table_size; + + numFrames = numFramesArg; + + if (numFrames) + table_size = numFrames; + else + table_size = framePatternLen; + + MALLOCARRAY_NOFAIL(frameTable, 1 + table_size); + + lastI = NULL; + lastIP = NULL; + firstB = NULL; + secondIP = NULL; + for ( index = 0; index < table_size; index++ ) { + frameTable[index].number = index; + typ = FType_Type(index); + frameTable[index].typ = typ; + switch( typ ) { + case 'i': + ptr = firstB; + while ( ptr != NULL ) { + ptr->next = &(frameTable[index]); + ptr = ptr->nextOutput; + } + frameTable[index].nextOutput = firstB; + frameTable[index].prev = lastIP; /* for freeing */ + if ( lastIP != NULL ) { + lastIP->next = &(frameTable[index]); + if ( secondIP == NULL ) { + secondIP = &(frameTable[index]); + } + } + lastIP = &(frameTable[index]); + firstB = NULL; + break; + case 'p': + ptr = firstB; + while ( ptr != NULL ) { + ptr->next = &(frameTable[index]); + ptr = ptr->nextOutput; + } + frameTable[index].nextOutput = firstB; + frameTable[index].prev = lastIP; + if ( lastIP != NULL ) { + lastIP->next = &(frameTable[index]); + if ( secondIP == NULL ) { + secondIP = &(frameTable[index]); + } + } + lastIP = &(frameTable[index]); + firstB = NULL; + break; + case 'b': + if ( (index+1 == framePatternLen) || + (FType_Type(index+1) != 'b') ) { + frameTable[index].nextOutput = NULL; + } else { + frameTable[index].nextOutput = &(frameTable[index+1]); + } + frameTable[index].prev = lastIP; + if ( firstB == NULL ) { + firstB = &(frameTable[index]); + } + break; + default: + fprintf(stderr, "Programmer Error in ComputeFrameTable (%d)\n", + framePattern[index]); + exit(1); + break; + } + } + + /* why? SRS */ + frameTable[table_size].number = framePatternLen; + ptr = firstB; + while ( ptr != NULL ) { + ptr->next = &(frameTable[table_size]); + ptr = ptr->nextOutput; + } + frameTable[table_size].nextOutput = firstB; + frameTable[table_size].prev = lastIP; + if ( secondIP == NULL ) + frameTable[table_size].next = &(frameTable[0]); + else + frameTable[table_size].next = secondIP; + + frameTable[0].prev = lastIP; + if ( lastIP != NULL ) { + lastIP->next = &(frameTable[table_size]); + } + + if (numFrames) + use_cache = TRUE; +} diff --git a/converter/ppm/ppmtompeg/fsize.c b/converter/ppm/ppmtompeg/fsize.c new file mode 100644 index 00000000..3808405c --- /dev/null +++ b/converter/ppm/ppmtompeg/fsize.c @@ -0,0 +1,134 @@ +/*===========================================================================* + * fsize.c * + * * + * procedures to keep track of frame size * + * * + * EXPORTED PROCEDURES: * + * Fsize_Reset * + * Fsize_Note * + * Fsize_Validate * + * * + * EXPORTED VARIABLES: * + * Fsize_x * + * Fsize_y * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "fsize.h" +#include "dct.h" + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ +int Fsize_x = 0; +int Fsize_y = 0; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Fsize_Reset + * + * reset the frame size to 0 + * + * RETURNS: nothing + * + * SIDE EFFECTS: Fsize_x, Fsize_y + * + *===========================================================================*/ +void +Fsize_Reset(void) { + Fsize_x = Fsize_y = 0; +} + + + +/*===========================================================================* + * + * Fsize_Validate + * + * make sure that the x, y values are 16-pixel aligned + * + * RETURNS: modifies the x, y values to 16-pixel alignment + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Fsize_Validate(int * const xP, + int * const yP) { + + *xP &= ~(DCTSIZE * 2 - 1); /* Zero the low-order bits */ + *yP &= ~(DCTSIZE * 2 - 1); /* Zero the low-order bits */ +} + + +/*===========================================================================* + * + * Fsize_Note + * + * note the given frame size and modify the global values as appropriate + * + * RETURNS: nothing + * + * SIDE EFFECTS: Fsize_x, Fsize_y + * + *===========================================================================*/ +void +Fsize_Note(int const id, + unsigned int const width, + unsigned int const height) { + + Fsize_x = width; + Fsize_y = height; + Fsize_Validate(&Fsize_x, &Fsize_y); + + if ((Fsize_x == 0) || (Fsize_y == 0)) { + fprintf(stderr,"Frame %d: size is less than the minimum: %d x %d!\n", + id, DCTSIZE*2, DCTSIZE*2); + exit(1); + } + +#ifdef BLEAH + if (Fsize_x == 0) { + Fsize_x = width; + Fsize_y = height; + Fsize_Validate(&Fsize_x, &Fsize_y); + } else if (width < Fsize_x || height < Fsize_y) { + fprintf(stderr, "Frame %d: wrong size: (%d,%d). Should be greater or equal to: (%d,%d)\n", + id, width, height, Fsize_x, Fsize_y); + exit(1); + } +#endif +} diff --git a/converter/ppm/ppmtompeg/gethostname.c b/converter/ppm/ppmtompeg/gethostname.c new file mode 100644 index 00000000..014b42e8 --- /dev/null +++ b/converter/ppm/ppmtompeg/gethostname.c @@ -0,0 +1,26 @@ +#define _BSD_SOURCE /* Make sure strdup() is in string.h */ + +#include <string.h> +#include <errno.h> +#include <sys/utsname.h> + +#include "pm.h" + +#include "gethostname.h" + +const char * +GetHostName(void) { +/*---------------------------------------------------------------------------- + Return the host name of this system. +-----------------------------------------------------------------------------*/ + struct utsname utsname; + int rc; + + rc = uname(&utsname); + + if (rc < 0) + pm_error("Unable to find out host name. " + "uname() failed with errno %d (%s)", errno, strerror(errno)); + + return strdup(utsname.nodename); +} diff --git a/converter/ppm/ppmtompeg/gethostname.h b/converter/ppm/ppmtompeg/gethostname.h new file mode 100644 index 00000000..e5450175 --- /dev/null +++ b/converter/ppm/ppmtompeg/gethostname.h @@ -0,0 +1,7 @@ +#ifndef GETHOSTNAME_H_INCLUDED +#define GETHOSTNAME_H_INCLUDED + +const char * +GetHostName(void); + +#endif diff --git a/converter/ppm/ppmtompeg/headers/all.h b/converter/ppm/ppmtompeg/headers/all.h new file mode 100644 index 00000000..e350aab8 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/all.h @@ -0,0 +1,95 @@ +/*===========================================================================* + * all.h * + * * + * stuff included from ALL source files * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/headers/RCS/all.h,v 1.9 1995/06/05 21:11:06 smoot Exp $ + * $Log: all.h,v $ + * Revision 1.9 1995/06/05 21:11:06 smoot + * added little_endian force for irizx + * + * Revision 1.8 1995/02/02 22:02:18 smoot + * added ifdefs for compatability on stranger and stranger architectures... + * + * Revision 1.7 1995/02/02 07:26:45 eyhung + * added parens to all.h to remove compiler warning + * + * Revision 1.6 1995/02/02 01:47:11 eyhung + * added MAXINT + * + * Revision 1.5 1995/01/19 23:54:33 eyhung + * Changed copyrights + * + * Revision 1.4 1994/11/14 22:52:04 smoot + * Added linux #include for time.h + * + * Revision 1.3 1994/11/12 02:12:13 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + +#ifndef ENCODE_ALL_INCLUDED +#define ENCODE_ALL_INCLUDED + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <memory.h> +#include <limits.h> + +/* There's got to be a better way.... */ +#ifdef LINUX +#include <time.h> +#endif +#ifdef MIPS +#include <time.h> +#endif +#ifdef IRIX +#define FORCE_LITTLE_ENDIAN +#include <time.h> +#endif + +#include "ansi.h" +#include "general.h" + +/* some machines have #define index strchr; get rid of this nonsense */ +#ifdef index +#undef index +#endif /* index */ + +#ifndef MAXINT +#define MAXINT 0x7fffffff +#endif + +#endif /* ENCODE_ALL_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/ansi.h b/converter/ppm/ppmtompeg/headers/ansi.h new file mode 100644 index 00000000..b3c3ab17 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/ansi.h @@ -0,0 +1,76 @@ +/*===========================================================================* + * ansi.h * + * * + * macro for non-ansi compilers * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/ansi.h,v 1.6 1995/08/15 23:43:13 smoot Exp $ + * $Log: ansi.h,v $ + * Revision 1.6 1995/08/15 23:43:13 smoot + * *** empty log message *** + * + * Revision 1.5 1995/01/19 23:54:35 eyhung + * Changed copyrights + * + * Revision 1.4 1994/11/12 02:12:13 keving + * nothing + * + * Revision 1.3 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.2 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.1 1993/06/14 22:50:22 keving + * nothing + * + */ + + +#ifndef ANSI_INCLUDED +#define ANSI_INCLUDED + + +/* + * _ANSI_ARGS_ macro stolen from Tcl6.5 by John Ousterhout + */ +#undef _ANSI_ARGS_ +#undef const +#ifdef NON_ANSI_COMPILER +#define _ANSI_ARGS_(x) () +#define CONST +#else +#define _ANSI_ARGS_(x) x +#define CONST const +#ifdef __cplusplus +#define VARARGS (...) +#else +#define VARARGS () +#endif +#endif + + +#endif /* ANSI_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/bitio.h b/converter/ppm/ppmtompeg/headers/bitio.h new file mode 100644 index 00000000..89e61fbb --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/bitio.h @@ -0,0 +1,140 @@ +/*===========================================================================* + * bitio.h * + * * + * bitwise input/output * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/bitio.h,v 1.8 1995/01/19 23:54:37 eyhung Exp $ + * $Log: bitio.h,v $ + * Revision 1.8 1995/01/19 23:54:37 eyhung + * Changed copyrights + * + * Revision 1.7 1994/11/12 02:12:14 keving + * nothing + * + * Revision 1.6 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.5 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.4 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.3 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.2 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.2 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +#ifndef BIT_IO_INCLUDED +#define BIT_IO_INCLUDED + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define WORDS_PER_BUCKET 128 +#define MAXBITS_PER_BUCKET (WORDS_PER_BUCKET * 32) +#define MAX_BUCKETS 128 +#define MAX_BITS MAX_BUCKETS*MAXBITS_PER_BUCKET + + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct bitBucket { + struct bitBucket *nextPtr; + uint32 bits[WORDS_PER_BUCKET]; + int bitsleft, bitsleftcur, currword; +} ActualBucket; + +typedef struct _BitBucket { + int totalbits; + int cumulativeBits; + int bitsWritten; + FILE *filePtr; + ActualBucket *firstPtr; + ActualBucket *lastPtr; +} BitBucket; + + +/*========* + * MACROS * + *========*/ + +#define SET_ITH_BIT(bits, i) (bits |= (1 << (i))) +#define GET_ITH_BIT(bits, i) (bits & (1 << (i))) + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void +Bitio_Free(BitBucket * const bbPtr); + +void +Bitio_Write(BitBucket * const bbPtr, + uint32 const bits, + int const nbits); + +void +Bitio_BytePad(BitBucket * const bbPtr); + +BitBucket * +Bitio_New(FILE * const filePtr); + +BitBucket * +Bitio_New_Filename(const char * const fileName); + +void +Bitio_Flush(BitBucket * const bbPtr); + +void +Bitio_Close(BitBucket * const bbPtr); + +void +Bitio_WriteToSocket(BitBucket * const bbPtr, + int const socket); + +#endif /* BIT_IO_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/block.h b/converter/ppm/ppmtompeg/headers/block.h new file mode 100644 index 00000000..46050492 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/block.h @@ -0,0 +1,53 @@ +void +ComputeDiffDCTs(MpegFrame * const current, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int * const pattern); + +void +ComputeDiffDCTBlock(Block current, + Block dest, + Block motionBlock, + boolean * const significantDifferenceP); + +void +ComputeMotionBlock(uint8 ** const prev, + int const by, + int const bx, + vector const m, + Block * const motionBlockP); + +void +ComputeMotionLumBlock(MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + LumBlock * const motionBlockP); + +void +BlockToData(uint8 ** const data, + Block block, + int const by, + int const bx); + +void +AddMotionBlock(Block block, + uint8 ** const prev, + int const by, + int const bx, + vector const m); + +void +AddBMotionBlock(Block block, + uint8 ** const prev, + uint8 ** const next, + int const by, + int const bx, + int const mode, + motion const motion); + +void +BlockifyFrame(MpegFrame * const frameP); + diff --git a/converter/ppm/ppmtompeg/headers/byteorder.h b/converter/ppm/ppmtompeg/headers/byteorder.h new file mode 100644 index 00000000..0070252a --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/byteorder.h @@ -0,0 +1,77 @@ +/*===========================================================================* + * byteorder.h * + * * + * stuff to handle different byte order * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/headers/RCS/byteorder.h,v 1.3 1995/01/19 23:54:39 eyhung Exp $ + * $Log: byteorder.h,v $ + * Revision 1.3 1995/01/19 23:54:39 eyhung + * Changed copyrights + * + * Revision 1.3 1995/01/19 23:54:39 eyhung + * Changed copyrights + * + * Revision 1.2 1994/11/12 02:12:15 keving + * nothing + * + * Revision 1.1 1993/07/22 22:24:23 keving + * nothing + * + */ + + +#include "general.h" + + +#ifdef FORCE_BIG_ENDIAN + /* leave byte order as it is */ +#define htonl(x) (x) +#define ntohl(x) (x) +#define htons(x) (x) +#define ntohs(x) (x) +#else +#ifdef FORCE_LITTLE_ENDIAN + /* need to reverse byte order */ + /* note -- we assume here that htonl is called on a variable, not a + * constant; thus, this is not for general use, but works with bitio.c + */ +#define htonl(x) \ + ((((unsigned char *)(&x))[0] << 24) | \ + (((unsigned char *)(&x))[1] << 16) | \ + (((unsigned char *)(&x))[2] << 8) | \ + (((unsigned char *)(&x))[3])) +#define ntohl(x) htonl(x) +#define htons(x) \ + ((((unsigned char *)(&x))[0] << 8) | \ + ((unsigned char *)(&x))[1]) +#define ntohs(x) htons(x) +#else + /* let in.h handle it, if possible */ +#include <sys/types.h> +#include <netinet/in.h> +#endif /* FORCE_LITTLE_ENDIAN */ +#endif /* FORCE_BIG_ENDIAN */ diff --git a/converter/ppm/ppmtompeg/headers/combine.h b/converter/ppm/ppmtompeg/headers/combine.h new file mode 100644 index 00000000..e28c6dee --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/combine.h @@ -0,0 +1,20 @@ +struct inputSource; + +void +GOPsToMPEG(struct inputSource * const inputSourceP, + const char * const outputFileName, + FILE * const outputFilePtr); + +typedef void (*fileAcquisitionFn)(void * const handle, + unsigned int const frameNumber, + FILE ** const ifPP); + + +typedef void (*fileDispositionFn)(void * const handle, + unsigned int const frameNumber); + +void +FramesToMPEG(FILE * const outputFile, + void * const inputHandle, + fileAcquisitionFn acquireInputFile, + fileDispositionFn disposeInputFile); diff --git a/converter/ppm/ppmtompeg/headers/dct.h b/converter/ppm/ppmtompeg/headers/dct.h new file mode 100644 index 00000000..e024b6c1 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/dct.h @@ -0,0 +1,79 @@ +/*===========================================================================* + * dct.h * + * * + * DCT procedures * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#ifndef DCT_INCLUDED +#define DCT_INCLUDED + + +#include "ansi.h" + + + +#define DCTSIZE 8 /* you really don't want to change this */ +#define DCTSIZE_SQ 64 /* you really don't want to change this */ + +#define DCTSIZE2 64 +typedef short DCTELEM; +typedef DCTELEM DCTBLOCK[DCTSIZE2]; +typedef DCTELEM DCTBLOCK_2D[DCTSIZE][DCTSIZE]; + + +/* + * from mfwddct.c: + */ +extern void mp_fwd_dct_block2 _ANSI_ARGS_((DCTBLOCK_2D src, DCTBLOCK_2D dest)); + +/* jrevdct.c */ +extern void init_pre_idct _ANSI_ARGS_((void )); +extern void mpeg_jrevdct _ANSI_ARGS_((DCTBLOCK data )); + + +/* We assume that right shift corresponds to signed division by 2 with + * rounding towards minus infinity. This is correct for typical "arithmetic + * shift" instructions that shift in copies of the sign bit. But some + * C compilers implement >> with an unsigned shift. For these machines you + * must define RIGHT_SHIFT_IS_UNSIGNED. + * RIGHT_SHIFT provides a proper signed right shift of an int32 quantity. + * It is only applied with constant shift counts. SHIFT_TEMPS must be + * included in the variables of any routine using RIGHT_SHIFT. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define SHIFT_TEMPS int32 shift_temp; +#define RIGHT_SHIFT(x,shft) \ + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((int32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) +#else +#define SHIFT_TEMPS +#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif + + +#endif /* DCT_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/frame.h b/converter/ppm/ppmtompeg/headers/frame.h new file mode 100644 index 00000000..1003ee15 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/frame.h @@ -0,0 +1,147 @@ +/*===========================================================================* + * frame.h * + * * + * basic frames procedures * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#ifndef FRAME_INCLUDED +#define FRAME_INCLUDED + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "mtypes.h" + +/*===========* + * CONSTANTS * + *===========*/ +#define TYPE_IFRAME 2 +#define TYPE_PFRAME 3 +#define TYPE_BFRAME 4 + + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct mpegFrame { + int type; + char inputFileName[256]; + int id; /* the frame number -- starts at 0 */ + boolean inUse; /* TRUE iff this frame is currently being used */ + /* FALSE means any data here can be thrashed */ + + /* + * now, the YCrCb data. All pixel information is stored in unsigned + * 8-bit pieces. We separate y, cr, and cb because cr and cb are + * subsampled by a factor of 2. + * + * if orig_y is NULL, then orig_cr, orig_cb are undefined + */ + uint8 **orig_y, **orig_cr, **orig_cb; + + /* now, the decoded data -- relevant only if + * referenceFrame == DECODED_FRAME + * + * if decoded_y is NULL, then decoded_cr, decoded_cb are undefined + */ + uint8 **decoded_y, **decoded_cr, **decoded_cb; + + /* reference data */ + uint8 **ref_y, **ref_cr, **ref_cb; + + /* + * these are the Blocks which will ultimately compose MacroBlocks. + * A Block is in a format that mp_fwddct() can crunch. + * if y_blocks is NULL, then cr_blocks, cb_blocks are undefined + */ + Block **y_blocks, **cr_blocks, **cb_blocks; + + /* + * this is the half-pixel luminance data (for reference frames) + */ + uint8 **halfX, **halfY, **halfBoth; + + boolean halfComputed; /* TRUE iff half-pixels already computed */ + + struct mpegFrame *next; /* points to the next B-frame to be encoded, if + * stdin is used as the input. + */ +} MpegFrame; + + +void +Frame_Init(unsigned int const numOfFramesRequested); + +void +Frame_Exit(void); + +void +Frame_Free(MpegFrame * const frameP); + +MpegFrame * +Frame_New(int const id, + int const type); + +void +Frame_AllocBlocks(MpegFrame * const frameP); + +void +Frame_AllocYCC(MpegFrame * const frameP); + +void +Frame_AllocHalf(MpegFrame * const frameP); + +void +Frame_AllocDecoded(MpegFrame * const frameP, + boolean const makeReference); + +void +Frame_Resize(MpegFrame * const omf, + MpegFrame * const mf, + int const insize_x, + int const insize_y, + int const outsize_x, + int const outsize_y); + + +extern void Frame_Free _ANSI_ARGS_((MpegFrame *frame)); +extern void Frame_Exit _ANSI_ARGS_((void)); +extern void Frame_AllocPPM _ANSI_ARGS_((MpegFrame * frame)); +extern void Frame_AllocYCC _ANSI_ARGS_((MpegFrame * mf)); +extern void Frame_AllocDecoded _ANSI_ARGS_((MpegFrame *frame, + boolean makeReference)); +extern void Frame_AllocHalf _ANSI_ARGS_((MpegFrame *frame)); +extern void Frame_AllocBlocks _ANSI_ARGS_((MpegFrame *mf)); +extern void Frame_Resize _ANSI_ARGS_((MpegFrame *omf, MpegFrame *mf, + int insize_x, int insize_y, + int outsize_x, int outsize_y)); + + +#endif /* FRAME_INCLUDED */ diff --git a/converter/ppm/ppmtompeg/headers/frames.h b/converter/ppm/ppmtompeg/headers/frames.h new file mode 100644 index 00000000..3fefaea7 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/frames.h @@ -0,0 +1,487 @@ +/*===========================================================================* + * frames.h + * + * stuff dealing with frames + * + *===========================================================================*/ + +#ifndef FRAMES_INCLUDED +#define FRAMES_INCLUDED + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" +#include "mtypes.h" +#include "mheaders.h" +#include "frame.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 + +#define LUM_BLOCK 0 +#define CHROM_BLOCK 1 +#define CR_BLOCK 2 +#define CB_BLOCK 3 + +#define MOTION_FORWARD 0 +#define MOTION_BACKWARD 1 +#define MOTION_INTERPOLATE 2 + + +#define USE_HALF 0 +#define USE_FULL 1 + + /* motion vector stuff */ +#define FORW_F_CODE fCode /* from picture header */ +#define BACK_F_CODE fCode +#define FORW_F (1 << (FORW_F_CODE - 1)) +#define BACK_F (1 << (BACK_F_CODE - 1)) +#define RANGE_NEG (-(1 << (3 + FORW_F_CODE))) +#define RANGE_POS ((1 << (3 + FORW_F_CODE))-1) +#define MODULUS (1 << (4 + FORW_F_CODE)) + +#define ORIGINAL_FRAME 0 +#define DECODED_FRAME 1 + + +/*=======================* + * STRUCTURE DEFINITIONS * + *=======================*/ + +typedef struct FrameTableStruct { + /* the following are all initted once and never changed */ + /* (they depend only on the pattern */ + char typ; + struct FrameTableStruct *next; + struct FrameTableStruct *prev; + + /* nextOutput is a pointer to next frame table entry to output */ + struct FrameTableStruct *nextOutput; + + boolean freeNow; /* TRUE iff no frames point back to this */ + + int number; + + int bFrameNumber; /* actual frame number, if a b-frame */ + +} FrameTable; + + +/*==================* + * TYPE DEFINITIONS * + *==================*/ + +typedef struct dct_data_tye_struct { + char useMotion; + char pattern, mode; + int fmotionX, fmotionY, bmotionX, bmotionY; +} dct_data_type; + +void EncodeYDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb)); +void +EncodeCDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb); + + +/*========* + * MACROS * + *========*/ + +/* return ceiling(a/b) where a, b are ints, using temp value c */ +#define int_ceil_div(a,b,c) ((b*(c = a/b) < a) ? (c+1) : c) +#define int_floor_div(a,b,c) ((b*(c = a/b) > a) ? (c-1) : c) + +/* assumes many things: + * block indices are (y,x) + * variables y_dc_pred, cr_dc_pred, and cb_dc_pred + * flat block fb exists + */ +#define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ + boolean overflow, overflowChange=FALSE; \ + int overflowValue = 0; \ + do { \ + overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ + qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ + fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ + overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ + fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ + if ((overflow) && (qscale!=31)) { \ + overflowChange = TRUE; overflowValue++; \ + qscale++; \ + } else overflow = FALSE; \ + } while (overflow); \ + Mhead_GenMBHeader(bb, \ + frameType /* pict_code_type */, mbAI /* addr_incr */, \ + qscale /* q_scale */, \ + 0 /* forw_f_code */, 0 /* back_f_code */, \ + 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ + 0 /* horiz_back_r */, 0 /* vert_back_r */, \ + 0 /* motion_forw */, 0 /* m_horiz_forw */, \ + 0 /* m_vert_forw */, 0 /* motion_back */, \ + 0 /* m_horiz_back */, 0 /* m_vert_back */, \ + 0 /* mb_pattern */, TRUE /* mb_intra */); \ + \ + /* Y blocks */ \ + EncodeYDC(fb[0][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[0], bb); \ + EncodeYDC(fb[1][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[1], bb); \ + EncodeYDC(fb[2][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[2], bb); \ + EncodeYDC(fb[3][0], &y_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[3], bb); \ + \ + /* CB block */ \ + EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[4], bb); \ + \ + /* CR block */ \ + EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ + Mpost_RLEHuffIBlock(fb[5], bb); \ + if (overflowChange) qscale -= overflowValue; \ + } + +#define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) { \ + x1 = (bx1)*DCTSIZE; \ + x2 = (bx2)*DCTSIZE; \ + } + +static __inline__ void +MotionToFrameCoord(int const by, + int const bx, + int const my, + int const mx, + int * const yP, + int * const xP) { +/*---------------------------------------------------------------------------- + Given a DCT block location and a motion vector, return the pixel + coordinates to which the upper left corner of the block moves. + + Return negative coordinates if it moves out of frame. +-----------------------------------------------------------------------------*/ + *yP = by * DCTSIZE + my; + *xP = bx * DCTSIZE + mx; +} + +#define COORD_IN_FRAME(fy,fx, type) \ + ((type == LUM_BLOCK) ? \ + ((fy >= 0) && (fx >= 0) && (fy < Fsize_y) && (fx < Fsize_x)) : \ + ((fy >= 0) && (fx >= 0) && (fy < (Fsize_y>>1)) && (fx < (Fsize_x>>1)))) + + +static __inline__ void +encodeMotionVector(int const x, + int const y, + vector * const qP, + vector * const rP, + int const f, + int const fCode) { + + int tempX; + int tempY; + int tempC; + + if (x < RANGE_NEG) + tempX = x + MODULUS; + else if (x > RANGE_POS) + tempX = x - MODULUS; + else + tempX = x; + + if (y < RANGE_NEG) + tempY = y + MODULUS; + else if (y > RANGE_POS) + tempY = y - MODULUS; + else + tempY = y; + + if (tempX >= 0) { + qP->x = int_ceil_div(tempX, f, tempC); + rP->x = f - 1 + tempX - qP->x*f; + } else { + qP->x = int_floor_div(tempX, f, tempC); + rP->x = f - 1 - tempX + qP->x*f; + } + + if (tempY >= 0) { + qP->y = int_ceil_div(tempY, f, tempC); + rP->y = f - 1 + tempY - qP->y*f; + } else { + qP->y = int_floor_div(tempY, f, tempC); + rP->y = f - 1 - tempY + qP->y*f; + } +} + + +#define DoQuant(bit, src, dest) \ + if (pattern & bit) { \ + switch (Mpost_QuantZigBlock(src, dest, QScale, FALSE)) { \ + case MPOST_NON_ZERO: \ + break; \ + case MPOST_ZERO: \ + pattern ^= bit; \ + break; \ + case MPOST_OVERFLOW: \ + if (QScale != 31) { \ + QScale++; \ + overflowChange = TRUE; \ + overflowValue++; \ + goto calc_blocks; \ + } \ + break; \ + } \ + } + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void +ComputeBMotionLumBlock(MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + int const mode, + motion const motion, + LumBlock * const motionBlockP); + +int +BMotionSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + MpegFrame * const next, + int const by, + int const bx, + motion * const motionP, + int const oldMode); + +void GenIFrame (BitBucket * const bb, + MpegFrame * const mf); +void GenPFrame (BitBucket * const bb, + MpegFrame * const current, + MpegFrame * const prev); +void GenBFrame (BitBucket * const bb, + MpegFrame * const curr, + MpegFrame * const prev, + MpegFrame * const next); +void AllocDctBlocks _ANSI_ARGS_((void )); + + +float +IFrameTotalTime(void); + +float +PFrameTotalTime(void); + +float +BFrameTotalTime(void); + +void +ShowIFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer); + +void +ShowPFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer); + +void +ShowBFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer); + +/* DIFFERENCE FUNCTIONS */ + +int32 +LumBlockMAD(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar); + +int32 +LumBlockMSE(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar); + +int32 +LumMotionError(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumAddMotionError(const LumBlock * const currentBlockP, + const LumBlock * const blockSoFarP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorA(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorB(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorC(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorD(const LumBlock * const currentP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar); + +int32 +LumMotionErrorSubSampled(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int const startY, + int const startX); + +void +BlockComputeSNR(MpegFrame * const current, + float * const snr, + float * const psnr); + +int32 +time_elapsed(void); + +void +AllocDctBlocks(void); + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int pixelFullSearch; +extern int searchRangeP,searchRangeB; /* defined in psearch.c */ +extern int qscaleI; +extern int gopSize; +extern int slicesPerFrame; +extern int blocksPerSlice; +extern int referenceFrame; +extern int specificsOn; +extern int quietTime; /* shut up for at least quietTime seconds; + * negative means shut up forever + */ +extern boolean realQuiet; /* TRUE = no messages to stdout */ + +extern boolean frameSummary; /* TRUE = frame summaries should be printed */ +extern boolean printSNR; +extern boolean printMSE; +extern boolean decodeRefFrames; /* TRUE = should decode I and P frames */ +extern int fCodeI,fCodeP,fCodeB; +extern boolean forceEncodeLast; +extern int TIME_RATE; + +#endif /* FRAMES_INCLUDED */ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/frames.h,v 1.13 1995/08/15 23:43:04 smoot Exp $ + * $Log: frames.h,v $ + * Revision 1.13 1995/08/15 23:43:04 smoot + * *** empty log message *** + * + * Revision 1.12 1995/04/14 23:13:18 smoot + * Reorganized for better rate control. Added overflow in DCT values + * handling. + * + * Revision 1.11 1995/01/19 23:54:46 smoot + * allow computediffdcts to un-assert parts of the pattern + * + * Revision 1.10 1995/01/16 07:43:10 eyhung + * Added realQuiet + * + * Revision 1.9 1995/01/10 23:15:28 smoot + * Fixed searchRange lack of def + * + * Revision 1.8 1994/11/15 00:55:36 smoot + * added printMSE + * + * Revision 1.7 1994/11/14 22:51:02 smoot + * added specifics flag. Added BlockComputeSNR parameters + * + * Revision 1.6 1994/11/01 05:07:23 darryl + * with rate control changes added + * + * Revision 1.1 1994/09/27 01:02:55 darryl + * Initial revision + * + * Revision 1.5 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.4 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.3 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.2 1993/03/02 19:00:27 keving + * nothing + * + * Revision 1.1 1993/02/19 20:15:51 keving + * nothing + * + */ + + diff --git a/converter/ppm/ppmtompeg/headers/frametype.h b/converter/ppm/ppmtompeg/headers/frametype.h new file mode 100644 index 00000000..63bee964 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/frametype.h @@ -0,0 +1,17 @@ +#ifndef FRAMETYPE_H_INCLUDED +#define FRAMETYPE_H_INCLUDED + +char +FType_Type(unsigned int const frameNum); + +unsigned int +FType_FutureRef(unsigned int const currFrameNum); + +int FType_PastRef _ANSI_ARGS_((int currFrameNum)); + +void SetFramePattern(const char * const pattern); + +void +ComputeFrameTable(unsigned int const numFrames); + +#endif diff --git a/converter/ppm/ppmtompeg/headers/fsize.h b/converter/ppm/ppmtompeg/headers/fsize.h new file mode 100644 index 00000000..6a1c910e --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/fsize.h @@ -0,0 +1,49 @@ +/*===========================================================================* + * fsize.h * + * * + * procedures to deal with frame size * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +#ifndef FSIZE_H_INCLUDED +#define FSIZE_H_INCLUDED + +extern int Fsize_x; +extern int Fsize_y; + + +void +Fsize_Reset(void); + +void +Fsize_Validate(int * const xP, + int * const yP); + +void +Fsize_Note(int const id, + unsigned int const width, + unsigned int const height); + +#endif diff --git a/converter/ppm/ppmtompeg/headers/general.h b/converter/ppm/ppmtompeg/headers/general.h new file mode 100644 index 00000000..f29c9445 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/general.h @@ -0,0 +1,174 @@ +/*===========================================================================* + * general.h * + * * + * very general stuff * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/general.h,v 1.7 1995/08/04 23:34:13 smoot Exp $ + * $Log: general.h,v $ + * Revision 1.7 1995/08/04 23:34:13 smoot + * jpeg5 changed the silly HAVE_BOOLEAN define.... + * + * Revision 1.6 1995/01/19 23:54:49 eyhung + * Changed copyrights + * + * Revision 1.5 1994/11/12 02:12:48 keving + * nothing + * + * Revision 1.4 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.3 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.1 1993/02/22 22:39:19 keving + * nothing + * + */ + + +#ifndef GENERAL_INCLUDED +#define GENERAL_INCLUDED + + +/* prototypes for library procedures + * + * if your /usr/include headers do not have these, then pass -DMISSING_PROTOS + * to your compiler + * + */ +#ifdef MISSING_PROTOS +int fprintf(); +int fwrite(); +int fread(); +int fflush(); +int fclose(); + +int sscanf(); +int bzero(); +int bcopy(); +int system(); +int time(); +int perror(); + +int socket(); +int bind(); +int listen(); +int accept(); +int connect(); +int close(); +int read(); +int write(); + +int pclose(); + +#endif + + +/*===========* + * CONSTANTS * + *===========*/ + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define SPACE ' ' +#define TAB '\t' +#define SEMICOLON ';' +#define NULL_CHAR '\0' +#define NEWLINE '\n' + + +/*==================* + * TYPE DEFINITIONS * + *==================*/ + +#ifndef HAVE_BOOLEAN +typedef int boolean; +#define HAVE_BOOLEAN +/* JPEG library also defines boolean */ +#endif + +/* In the following, we need the "signed" in order to make these typedefs + match those in AIX system header files. Otherwise, compile fails on + AIX. 2000.09.11. +*/ +typedef unsigned char uint8; +typedef signed char int8; +typedef unsigned short uint16; +typedef signed short int16; + +/* The 32 bit integer types are probably obsolete. + + parallel.c used to use them as buffers for socket I/O, because in the + protocol on the socket, an integer is represented by 4 octets. But + the proper type for that is unsigned char[4], so we changed parallel.c + to that in September 2004. + + A user of TRU64 4.0f in May 2000 used a -DLONG_32 option, but did + not indicate that it was really necessary. After that, Configure + added -DLONG_32 for all TRU64 builds. A user of TRU64 5.1A in July + 2003 demonstrated that int is in fact 4 bytes on his machine (and + long is 8 bytes). So we removed the -DLONG_32 from Configure. This + whole issue may too be obsolete because of the fixing of parallel.c + mentioned above. +*/ + + /* LONG_32 should only be defined iff + * 1) long's are 32 bits and + * 2) int's are not + */ +#ifdef LONG_32 +typedef unsigned long uint32; +typedef long int32; +#else +typedef unsigned int uint32; +typedef signed int int32; +#endif + + +/*========* + * MACROS * + *========*/ + +#undef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#undef abs +#define abs(a) ((a) >= 0 ? (a) : -(a)) + + +#endif diff --git a/converter/ppm/ppmtompeg/headers/huff.h b/converter/ppm/ppmtompeg/headers/huff.h new file mode 100644 index 00000000..47ffb843 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/huff.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/huff.h,v 1.3 1995/01/19 23:54:51 eyhung Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#define HUFF_MAXRUN 32 +#define HUFF_MAXLEVEL 41 + +extern int huff_maxlevel[]; +extern uint32 *huff_table[]; +extern int *huff_bits[]; diff --git a/converter/ppm/ppmtompeg/headers/input.h b/converter/ppm/ppmtompeg/headers/input.h new file mode 100644 index 00000000..75734237 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/input.h @@ -0,0 +1,70 @@ +#ifndef INPUT_H_INCLUDED +#define INPUT_H_INCLUDED + +#include "pm_c_util.h" +#include "ppm.h" +#include "frame.h" + +struct InputFileEntry; + +struct inputSource { +/*---------------------------------------------------------------------------- + This describes the source of data for the program. + Typically, the source data is a bunch of raw frames in PPM format. + But sometimes, it is a bunch of already encoded frames or GOPs. +-----------------------------------------------------------------------------*/ + bool stdinUsed; + int numInputFiles; + /* This is the maximum number of input files available. If + we're reading from explicitly named files, it is exactly + the number available. If we're reading from a stream, it's + infinity. (At the moment, "reading from a stream" is + equivalent to "reading from Standard Input"). + */ + + /* Members below here defined only if 'stdinUsed' is false */ + + struct InputFileEntry ** inputFileEntries; + /* Each element of this array describes a set of input files. + Valid elements are consecutive starting at index 0. + */ + unsigned int numInputFileEntries; + /* Number of valid entries in array inputFileEntries[] */ + unsigned int ifArraySize; + /* Number of allocated entries in the array inputFileEntries[] */ +}; + + +void +GetNthInputFileName(struct inputSource * const inputSourceP, + unsigned int const n, + const char ** const fileName); + +void +ReadNthFrame(struct inputSource * const inputSourceP, + unsigned int const frameNumber, + boolean const remoteIO, + boolean const childProcess, + boolean const separateConversion, + const char * const slaveConversion, + const char * const inputConversion, + MpegFrame * const frameP, + bool * const endOfStreamP); + +void +JM2JPEG(struct inputSource * const inputSourceP); + +void +AddInputFiles(struct inputSource * const inputSourceP, + const char * const input); + +void +SetStdinInput(struct inputSource * const inputSourceP); + +void +CreateInputSource(struct inputSource ** const inputSourcePP); + +void +DestroyInputSource(struct inputSource * const inputSourceP); + +#endif diff --git a/converter/ppm/ppmtompeg/headers/jpeg.h b/converter/ppm/ppmtompeg/headers/jpeg.h new file mode 100644 index 00000000..62c6f930 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/jpeg.h @@ -0,0 +1,12 @@ +#include "ansi.h" + + +void +JMovie2JPEG(const char * const infilename, + const char * const obase, + int const start, + int const end); + +void +ReadJPEG(MpegFrame * const mf, + FILE * const fp); diff --git a/converter/ppm/ppmtompeg/headers/mheaders.h b/converter/ppm/ppmtompeg/headers/mheaders.h new file mode 100644 index 00000000..21d43e3d --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/mheaders.h @@ -0,0 +1,114 @@ +/*===========================================================================* + * mheaders.h * + * * + * MPEG headers * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/mheaders.h,v 1.4 1995/03/27 19:29:24 smoot Exp $ + * $Log: mheaders.h,v $ + * Revision 1.4 1995/03/27 19:29:24 smoot + * changed to remove mb_quant + * + * Revision 1.3 1995/01/19 23:54:56 eyhung + * Changed copyrights + * + * Revision 1.2 1994/11/12 02:12:51 keving + * nothing + * + * Revision 1.1 1993/07/22 22:24:23 keving + * nothing + * + * + */ + + +#ifndef MHEADERS_INCLUDED +#define MHEADERS_INCLUDED + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "bitio.h" + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void SetGOPStartTime _ANSI_ARGS_((int index)); + +void +Mhead_GenSequenceHeader(BitBucket * const bbPtr, + uint32 const hsize, + uint32 const vsize, + int32 const pratio, + int32 const pict_rate, + int32 const bit_rate_arg, + int32 const buf_size_arg, + int32 const c_param_flag_arg, + const int32 * const iq_matrix, + const int32 * const niq_matrix, + uint8 * const ext_data, + int32 const ext_data_size, + uint8 * const user_data, + int32 const user_data_size); + +void Mhead_GenSequenceEnder _ANSI_ARGS_((BitBucket *bbPtr)); +void Mhead_GenGOPHeader _ANSI_ARGS_((BitBucket *bbPtr, + int32 drop_frame_flag, + int32 tc_hrs, int32 tc_min, + int32 tc_sec, int32 tc_pict, + int32 closed_gop, int32 broken_link, + uint8 *ext_data, int32 ext_data_size, + uint8 *user_data, int32 user_data_size)); +void Mhead_GenPictureHeader _ANSI_ARGS_((BitBucket *bbPtr, int frameType, + int pictCount, int f_code)); +void Mhead_GenSliceHeader _ANSI_ARGS_((BitBucket *bbPtr, uint32 slicenum, + uint32 qscale, uint8 *extra_info, + uint32 extra_info_size)); +void Mhead_GenSliceEnder _ANSI_ARGS_((BitBucket *bbPtr)); +void Mhead_GenMBHeader _ANSI_ARGS_((BitBucket *bbPtr, + uint32 pict_code_type, uint32 addr_incr, + uint32 q_scale, + uint32 forw_f_code, uint32 back_f_code, + uint32 horiz_forw_r, uint32 vert_forw_r, + uint32 horiz_back_r, uint32 vert_back_r, + int32 motion_forw, int32 m_horiz_forw, + int32 m_vert_forw, int32 motion_back, + int32 m_horiz_back, int32 m_vert_back, + uint32 mb_pattern, uint32 mb_intra)); + + +#endif /* MHEADERS_INCLUDED */ + + + + + diff --git a/converter/ppm/ppmtompeg/headers/motion_search.h b/converter/ppm/ppmtompeg/headers/motion_search.h new file mode 100644 index 00000000..ab83cbca --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/motion_search.h @@ -0,0 +1,154 @@ +/*===========================================================================* + * search.h * + * * + * stuff dealing with the motion search * + * * + *===========================================================================*/ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define PSEARCH_SUBSAMPLE 0 +#define PSEARCH_EXHAUSTIVE 1 +#define PSEARCH_LOGARITHMIC 2 +#define PSEARCH_TWOLEVEL 3 + +#define BSEARCH_EXHAUSTIVE 0 +#define BSEARCH_CROSS2 1 +#define BSEARCH_SIMPLE 2 + + +/*========* + * MACROS * + *========*/ + +#define COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX)\ +leftMY = -2*DCTSIZE*by; /* these are valid motion vectors */ \ +leftMX = -2*DCTSIZE*bx; \ +/* these are invalid motion vectors */ \ +rightMY = 2*(Fsize_y - (by+2)*DCTSIZE + 1) - 1; \ +rightMX = 2*(Fsize_x - (bx+2)*DCTSIZE + 1) - 1; \ +\ +if ( stepSize == 2 ) { \ + rightMY++; \ + rightMX++; \ + } + +#define VALID_MOTION(m) \ +(((m).y >= leftMY) && ((m).y < rightMY) && \ + ((m).x >= leftMX) && ((m).x < rightMX) ) + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void +SetPSearchAlg(const char * const alg); +void +SetBSearchAlg(const char * const alg); +const char * +BSearchName(void); +const char * +PSearchName(void); + +int +PLogarithmicSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const searchRange); + +int +PSubSampleSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const searchRange); + +int +PLocalSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const bestSoFar, + int const searchRange); + +int +PTwoLevelSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const bestSoFar, + int const searchRange); +void +PMotionSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP); + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int psearchAlg; + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/search.h,v 1.6 1995/08/15 23:43:36 smoot Exp $ + * $Log: search.h,v $ + * Revision 1.6 1995/08/15 23:43:36 smoot + * *** empty log message *** + * + * Revision 1.5 1995/01/19 23:55:20 eyhung + * Changed copyrights + * + * Revision 1.4 1994/12/07 00:42:01 smoot + * Added seperate P and B search ranges + * + * Revision 1.3 1994/11/12 02:12:58 keving + * nothing + * + * Revision 1.2 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.1 1993/07/09 00:17:23 keving + * nothing + * + */ + + + diff --git a/converter/ppm/ppmtompeg/headers/mpeg.h b/converter/ppm/ppmtompeg/headers/mpeg.h new file mode 100644 index 00000000..d739dede --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/mpeg.h @@ -0,0 +1,116 @@ +/*===========================================================================* + * mpeg.h * + * * + * no comment * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <time.h> + +#include "pm_c_util.h" +#include "ppm.h" +#include "ansi.h" +#include "mtypes.h" +#include "frame.h" + +struct inputSource; + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +enum frameContext {CONTEXT_WHOLESTREAM, CONTEXT_GOP, CONTEXT_JUSTFRAMES}; + +void +GenMPEGStream(struct inputSource * const inputSourceP, + enum frameContext const context, + unsigned int const frameStart, + unsigned int const frameEnd, + int32 const qtable[], + int32 const niqtable[], + bool const childProcess, + FILE * const ofp, + const char * const outputFileName, + bool const wantVbvUnderflowWarning, + bool const wantVbvOverflowWarning, + unsigned int * const inputFrameBitsP, + unsigned int * const totalBitsP); + +void +PrintStartStats(time_t const startTime, + bool const specificFrames, + unsigned int const firstFrame, + unsigned int const lastFrame, + struct inputSource * const inputSourceP); + +void +PrintEndStats(time_t const startTime, + time_t const endTime, + unsigned int const inputFrameBits, + unsigned int const totalBits); + +void +ComputeGOPFrames(int const whichGOP, + unsigned int * const firstFrameP, + unsigned int * const lastFrameP, + unsigned int const numFrames); + +extern void IncrementTCTime _ANSI_ARGS_((void)); +void SetReferenceFrameType(const char * const type); + +boolean +NonLocalRefFrame(int const id); + +void +ReadDecodedRefFrame(MpegFrame * const frameP, + unsigned int const frameNumber); + +extern void WriteDecodedFrame _ANSI_ARGS_((MpegFrame *frame)); +extern void SetBitRateFileName _ANSI_ARGS_((char *fileName)); +extern void SetFrameRate _ANSI_ARGS_((void)); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern MpegFrame *frameMemory[3]; +extern int32 tc_hrs, tc_min, tc_sec, tc_pict, tc_extra; +extern int totalFramesSent; +extern int gopSize; +extern char *framePattern; +extern int framePatternLen; +extern int32 qtable[]; +extern int32 niqtable[]; +extern int32 *customQtable; +extern int32 *customNIQtable; +extern int aspectRatio; +extern int frameRate; +extern int frameRateRounded; +extern boolean frameRateInteger; + diff --git a/converter/ppm/ppmtompeg/headers/mproto.h b/converter/ppm/ppmtompeg/headers/mproto.h new file mode 100644 index 00000000..c3b0f4b3 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/mproto.h @@ -0,0 +1,132 @@ +/*===========================================================================* + * mproto.h * + * * + * basically a lot of miscellaneous prototypes * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/headers/RCS/mproto.h,v 1.12 1995/03/29 20:14:29 smoot Exp $ + * $Log: mproto.h,v $ + * Revision 1.12 1995/03/29 20:14:29 smoot + * deleted unneeded dct prototype + * + * Revision 1.11 1995/01/19 23:55:02 eyhung + * Changed copyrights + * + * Revision 1.10 1995/01/16 06:20:10 eyhung + * Changed ReadYUV to ReadEYUV + * + * Revision 1.9 1993/07/22 22:24:23 keving + * nothing + * + * Revision 1.8 1993/07/09 00:17:23 keving + * nothing + * + * Revision 1.7 1993/06/03 21:08:53 keving + * nothing + * + * Revision 1.6 1993/02/24 19:13:33 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "bitio.h" + + +#define DCTSIZE2 DCTSIZE*DCTSIZE +typedef short DCTELEM; +typedef DCTELEM DCTBLOCK[DCTSIZE2]; + + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +/* + * from mbasic.c: + */ +void mp_reset _ANSI_ARGS_((void)); +void mp_free _ANSI_ARGS_((MpegFrame *mf)); +MpegFrame *mp_new _ANSI_ARGS_((int fnumber, char type, MpegFrame *oldFrame)); +void mp_ycc_calc _ANSI_ARGS_((MpegFrame *mf)); +void mp_dct_blocks _ANSI_ARGS_((MpegFrame *mf)); +void AllocDecoded _ANSI_ARGS_((MpegFrame *frame)); + +/* + * from moutput.c: + */ +boolean mp_quant_zig_block _ANSI_ARGS_((Block in, FlatBlock out, int qscale, int iblock)); +void UnQuantZig _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); +void mp_rle_huff_block _ANSI_ARGS_((FlatBlock in, BitBucket *out)); +void mp_rle_huff_pblock _ANSI_ARGS_((FlatBlock in, BitBucket *out)); +void mp_create_blocks _ANSI_ARGS_((MpegFrame *mf)); + + + + +void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, int width, + int height)); +boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer)); +void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); + +void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); +boolean PMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, + int by, int bx, int *motionY, int *motionX)); +void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); +void mp_validate_size _ANSI_ARGS_((int *x, int *y)); +void AllocYCC _ANSI_ARGS_((MpegFrame * mf)); + + +/* jrevdct.c */ +void init_pre_idct _ANSI_ARGS_((void )); +void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); +void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); +void j_rev_dct_sparse _ANSI_ARGS_((DCTBLOCK data , int pos )); +void j_rev_dct _ANSI_ARGS_((DCTBLOCK data )); + +/* block.c */ +void BlockToData _ANSI_ARGS_((uint8 **data, Block block, int by, int bx)); +void AddMotionBlock _ANSI_ARGS_((Block block, uint8 **prev, int by, int bx, + int my, int mx)); diff --git a/converter/ppm/ppmtompeg/headers/mtypes.h b/converter/ppm/ppmtompeg/headers/mtypes.h new file mode 100644 index 00000000..0db5a330 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/mtypes.h @@ -0,0 +1,109 @@ +/*===========================================================================* + * mtypes.h + * + * MPEG data types + * + *===========================================================================*/ + +/* Copyright information is at end of file */ + +#ifndef MTYPES_INCLUDED +#define MTYPES_INCLUDED + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "dct.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define TYPE_BOGUS 0 /* for the header of the circular list */ +#define TYPE_VIRGIN 1 + +#define STATUS_EMPTY 0 +#define STATUS_LOADED 1 +#define STATUS_WRITTEN 2 + + +typedef struct vector { + int y; + int x; +} vector; + +typedef struct motion { + vector fwd; + vector bwd; +} motion; + +/*==================* + * TYPE DEFINITIONS * + *==================*/ + +/* + * your basic Block type + */ +typedef int16 Block[DCTSIZE][DCTSIZE]; +typedef int16 FlatBlock[DCTSIZE_SQ]; +typedef struct { + int32 l[2*DCTSIZE][2*DCTSIZE]; +} LumBlock; +typedef int32 ChromBlock[DCTSIZE][DCTSIZE]; + +/*========* + * MACROS * + *========*/ + +#ifdef ABS +#undef ABS +#endif + +#define ABS(x) (((x)<0)?-(x):(x)) + +#ifdef HEINOUS_DEBUG_MODE +#define DBG_PRINT(x) {printf x; fflush(stdout);} +#else +#define DBG_PRINT(x) +#endif + +#define ERRCHK(bool, str) {if(!(bool)) {perror(str); exit(1);}} + +/* For Specifics */ +typedef struct detalmv_def { + int typ,fx,fy,bx,by; +} BlockMV; +#define TYP_SKIP 0 +#define TYP_FORW 1 +#define TYP_BACK 2 +#define TYP_BOTH 3 + + +#endif /* MTYPES_INCLUDED */ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + diff --git a/converter/ppm/ppmtompeg/headers/opts.h b/converter/ppm/ppmtompeg/headers/opts.h new file mode 100644 index 00000000..5901a677 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/opts.h @@ -0,0 +1,125 @@ +/* + * opts.h - set optional parameters + */ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/opts.h,v 1.3 1995/08/15 23:43:43 smoot Exp $ + * $Log: opts.h,v $ + * Revision 1.3 1995/08/15 23:43:43 smoot + * *** empty log message *** + * + * Revision 1.2 1995/05/02 22:00:51 smoot + * added TUNEing stuff + * + * Revision 1.1 1995/04/14 23:12:53 smoot + * Initial revision + * + */ + +#include "general.h" +#include "ansi.h" +#include "mtypes.h" + +/* + TUNE b [limit] lower limit on how different a block must be to be DCT coded + TUNE c [file [color-diff]] Collect statistics on Quantization + TUNE d [RateScale DistortionScale] Do a DCT in the P search, not just DIFF + TUNE k [breakpt end [slope]] Squash small lum values + TUNE l Figure out Laplacian distrib and use them to dequantize and do snr calc + TUNE n Dont consider DC differenece in DCT searches + TUNE q Do MSE for distortion measure, not MAD + TUNE s [Max] | [LumMax ChromMax] Squash small differences in successive frames + TUNE u disallow skip blocks in B frames + TUNE w filename [c] Write I block distortion numbers to file [with bit-rates] + TUNE z Zaps Intra blocks in P/B frames. + + [ Note k and s make -snr numbers a lie, by playing with input ] + [ Note d n and q are contradictory (can only use one) ] + [ Note c will not work on parallel encodings ] +*/ + +extern boolean tuneingOn; + +/* Smash to no-change a motion block DCT with MAD less than: */ +/* DETAL b value */ +extern int block_bound; + +/* Collect info on quantization */ +extern boolean collect_quant; +extern int collect_quant_detailed; +extern FILE *collect_quant_fp; + +/* Nuke dim areas */ +extern int kill_dim, kill_dim_break, kill_dim_end; +extern float kill_dim_slope; + + +/* Stuff to control MV search comparisons */ +#define DEFAULT_SEARCH 0 +#define LOCAL_DCT 1 /* Do DCT in search (SLOW!!!!) */ +#define NO_DC_SEARCH 2 /* Dont consider DC component in motion searches */ +#define DO_Mean_Squared_Distortion 3 /* Do Squared distortion, not ABS */ + +/* Parameters for special searches */ +/* LOCAL_DCT */ +extern float LocalDCTRateScale, LocalDCTDistortScale; + +/* Search Type Variable */ +extern int SearchCompareMode; + +/* squash small differences */ +extern boolean squash_small_differences; +extern int SquashMaxLum, SquashMaxChr; + +/* Disallows Intra blocks in P/B code */ +extern boolean IntraPBAllowed; + +/* Write out distortion numbers */ +extern boolean WriteDistortionNumbers; +extern int collect_distortion_detailed; +extern FILE *distortion_fp; +extern FILE *fp_table_rate[31], *fp_table_dist[31]; + +/* Laplacian Distrib */ +extern boolean DoLaplace; +extern double **L1, **L2, **Lambdas; +extern int LaplaceNum, LaplaceCnum; + +/* Turn on/off skipping in B frames */ +extern boolean BSkipBlocks; + +/* Procedures Prototypes */ +int GetIQScale _ANSI_ARGS_((void)); +int GetPQScale _ANSI_ARGS_((void)); +int GetBQScale _ANSI_ARGS_((void)); +void Tune_Init _ANSI_ARGS_((void)); +int CalcRLEHuffLength _ANSI_ARGS_((FlatBlock in)); +void ParseTuneParam(const char * const charPtr); +int mse _ANSI_ARGS_((Block blk1, Block blk2)); +void Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock)); +extern void CalcLambdas(void); + + + + diff --git a/converter/ppm/ppmtompeg/headers/parallel.h b/converter/ppm/ppmtompeg/headers/parallel.h new file mode 100644 index 00000000..e18d3f46 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/parallel.h @@ -0,0 +1,135 @@ +/*===========================================================================* + * parallel.h + * + * parallel encoding + * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "ansi.h" +#include "bitio.h" +#include "frame.h" + + +struct inputSource; + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +void +MasterServer(struct inputSource * const inputSourceP, + const char * const paramFileName, + const char * const outputFileName); + +void +NotifyMasterDone(const char * const hostName, + int const portNum, + int const machineNumber, + unsigned int const seconds, + boolean * const moreWorkToDoP, + int * const frameStartP, + int * const frameEndP); + +void +IoServer(struct inputSource * const inputSourceP, + const char * const parallelHostName, + int const portNum); + +void +CombineServer(int const numInputFiles, + const char * const masterHostName, + int const masterPortNum, + const char* const outputFileName); + +void +DecodeServer(int const numInputFiles, + const char * const decodeFileName, + const char * const parallelHostName, + int const portNum); + +void +WaitForOutputFile(int number); + +void +GetRemoteFrame(MpegFrame * const frameP, + int const frameNumber); + +void +SendRemoteFrame(int const frameNumber, + BitBucket * const bbP); + +void +NoteFrameDone(int frameStart, int frameEnd); + +void +SetIOConvert(boolean separate); + +void +SetRemoteShell(const char * const shell); + +void +NotifyDecodeServerReady(int const id); + +void +WaitForDecodedFrame(int id); + +void +SendDecodedFrame(MpegFrame * const frameP); + +void +GetRemoteDecodedRefFrame(MpegFrame * const frameP, + int const frameNumber); + +void +SetParallelPerfect(boolean val); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int parallelTestFrames; +extern int parallelTimeChunks; + +extern const char *IOhostName; +extern int ioPortNumber; +extern int decodePortNumber; + +extern boolean ioServer; +extern boolean niceProcesses; +extern boolean forceIalign; +extern int machineNumber; +extern boolean remoteIO; +extern boolean separateConversion; + + + + + + + diff --git a/converter/ppm/ppmtompeg/headers/param.h b/converter/ppm/ppmtompeg/headers/param.h new file mode 100644 index 00000000..31be61ee --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/param.h @@ -0,0 +1,87 @@ +/*===========================================================================* + * param.h * + * * + * reading the parameter file * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "pm_c_util.h" +#include "ansi.h" +#include "input.h" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define MAX_MACHINES 256 +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +#define ENCODE_FRAMES 0 +#define COMBINE_GOPS 1 +#define COMBINE_FRAMES 2 + + +struct params { + struct inputSource * inputSourceP; + bool warnUnderflow; + bool warnOverflow; +}; + + +void +ReadParamFile(const char * const fileName, + int const function, + struct params * const paramP); + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +/* All this stuff ought to be in a struct param instead */ + +extern char outputFileName[256]; +extern int whichGOP; +extern int numMachines; +extern char machineName[MAX_MACHINES][256]; +extern char userName[MAX_MACHINES][256]; +extern char executable[MAX_MACHINES][1024]; +extern char remoteParamFile[MAX_MACHINES][1024]; +extern boolean remote[MAX_MACHINES]; +extern char currentPath[MAXPATHLEN]; +extern char currentFramePath[MAXPATHLEN]; +extern char currentGOPPath[MAXPATHLEN]; +extern char inputConversion[1024]; +extern char yuvConversion[256]; +extern int yuvWidth, yuvHeight; +extern int realWidth, realHeight; +extern char ioConversion[1024]; +extern char slaveConversion[1024]; +extern FILE *bitRateFile; +extern boolean showBitRatePerFrame; +extern boolean computeMVHist; +extern const double VidRateNum[9]; +extern boolean keepTempFiles; diff --git a/converter/ppm/ppmtompeg/headers/postdct.h b/converter/ppm/ppmtompeg/headers/postdct.h new file mode 100644 index 00000000..3f3b51fe --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/postdct.h @@ -0,0 +1,40 @@ +/*===========================================================================* + * postdct.h * + * * + * MPEG post-DCT processing * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "bitio.h" + + +int Mpost_QuantZigBlock (Block in, FlatBlock out, int qscale, int iblock); +void Mpost_UnQuantZigBlock (FlatBlock in, Block out, + int qscale, boolean iblock); +void Mpost_RLEHuffIBlock (FlatBlock in, BitBucket *out); +void Mpost_RLEHuffPBlock (FlatBlock in, BitBucket *out); + +#define MPOST_ZERO 0 +#define MPOST_NON_ZERO 1 +#define MPOST_OVERFLOW (-1) diff --git a/converter/ppm/ppmtompeg/headers/prototypes.h b/converter/ppm/ppmtompeg/headers/prototypes.h new file mode 100644 index 00000000..d729aafa --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/prototypes.h @@ -0,0 +1,78 @@ +/*===========================================================================* + * prototypes.h * + * * + * miscellaneous prototypes * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ +/*==============* + * HEADER FILES * + *==============*/ + +#include "general.h" +#include "ansi.h" +#include "frame.h" + + +/*===============================* + * EXTERNAL PROCEDURE prototypes * + *===============================*/ + +int GetBQScale _ANSI_ARGS_((void)); +int GetPQScale _ANSI_ARGS_((void)); +void ResetBFrameStats _ANSI_ARGS_((void)); +void ResetPFrameStats _ANSI_ARGS_((void)); +void SetSearchRange (int const pixelsP, + int const pixelsB); +void ResetIFrameStats _ANSI_ARGS_((void)); +void +SetPixelSearch(const char * const searchType); +void SetIQScale _ANSI_ARGS_((int qI)); +void SetPQScale _ANSI_ARGS_((int qP)); +void SetBQScale _ANSI_ARGS_((int qB)); +float EstimateSecondsPerIFrame _ANSI_ARGS_((void)); +float EstimateSecondsPerPFrame _ANSI_ARGS_((void)); +float EstimateSecondsPerBFrame _ANSI_ARGS_((void)); +void SetGOPSize _ANSI_ARGS_((int size)); +void +SetStatFileName(const char * const fileName); +void SetSlicesPerFrame _ANSI_ARGS_((int number)); +void SetBlocksPerSlice _ANSI_ARGS_((void)); + + +void DCTFrame _ANSI_ARGS_((MpegFrame * mf)); + +void PPMtoYCC _ANSI_ARGS_((MpegFrame * mf)); + +void MotionSearchPreComputation _ANSI_ARGS_((MpegFrame *frame)); + +void ComputeHalfPixelData _ANSI_ARGS_((MpegFrame *frame)); +void mp_validate_size _ANSI_ARGS_((int *x, int *y)); + +extern void SetFCode _ANSI_ARGS_((void)); + + +/* psearch.c */ +void ShowPMVHistogram _ANSI_ARGS_((FILE *fpointer)); +void ShowBBMVHistogram _ANSI_ARGS_((FILE *fpointer)); +void ShowBFMVHistogram _ANSI_ARGS_((FILE *fpointer)); diff --git a/converter/ppm/ppmtompeg/headers/psocket.h b/converter/ppm/ppmtompeg/headers/psocket.h new file mode 100644 index 00000000..214f5dce --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/psocket.h @@ -0,0 +1,41 @@ +#ifndef PSOCKET_H_INCLUDED +#define PSOCKET_H_INCLUDED + +#include <netdb.h> + +void +ReadInt(int const socketFd, + int * const valueP); + +void +ReadBytes(int const fd, + unsigned char * const buf, + unsigned int const nbyte); + +void +WriteInt(int const socketFd, + int const value); + +void +WriteBytes(int const fd, + unsigned char * const buf, + unsigned int const nbyte); + +void +ConnectToSocket(const char * const machineName, + int const portNum, + struct hostent ** const hostEnt, + int * const socketFdP, + const char ** const errorP); + +void +CreateListeningSocket(int * const socketP, + int * const portNumP, + const char ** const errorP); + +void +AcceptConnection(int const listenSocketFd, + int * const connectSocketFdP, + const char ** const errorP); + +#endif diff --git a/converter/ppm/ppmtompeg/headers/rate.h b/converter/ppm/ppmtompeg/headers/rate.h new file mode 100644 index 00000000..df5ca1cc --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/rate.h @@ -0,0 +1,204 @@ +/*===========================================================================* + * rate.h * + * * + * Procedures concerned with rate control + * * + * EXPORTED PROCEDURES: * + * getRateMode() + * setBitRate() + * getBitRate() + * setBufferSize() + * getBufferSize() + * initRateControl() + * targetRateControl() + * updateRateControl() + * MB_RateOut() + * * + *===========================================================================*/ + +/* COPYRIGHT INFO HERE */ + +#define VARIABLE_RATE 0 +#define FIXED_RATE 1 + + +/*==================* + * Exported VARIABLES * + *==================*/ + + +extern int rc_bitsThisMB; +extern int rc_numBlocks; +extern int rc_totalQuant; +extern int rc_quantOverride; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * initRateControl + * + * initialize the allocation parameters. + *===========================================================================*/ +int +initRateControl(bool const wantUnderflowWarning, + bool const wantOverflowWarning); + +/*===========================================================================* + * + * targetRateControl + * + * Determine the target allocation for given picture type. + * + * RETURNS: target size in bits + *===========================================================================*/ +void +targetRateControl(MpegFrame * const frameP); + + +/*===========================================================================* + * + * MB_RateOut + * + * Prints out sampling of MB rate control data. Every "nth" block + * stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE + * + * RETURNS: nothing + *===========================================================================*/ +extern void MB_RateOut _ANSI_ARGS_((int type)); + + +/*===========================================================================* + * + * updateRateControl + * + * Update the statistics kept, after end of frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + *===========================================================================*/ +void +updateRateControl(int const type); + + +/*===========================================================================* + * + * needQScaleChange(current Q scale, 4 luminance blocks) + * + * + * RETURNS: new Qscale + *===========================================================================*/ +extern int needQScaleChange _ANSI_ARGS_((int oldQScale, Block blk0, Block blk1, Block blk2, Block blk3)); + +/*===========================================================================* + * + * incNumBlocks() + * + * + * RETURNS: nothing + *===========================================================================*/ +extern void incNumBlocks _ANSI_ARGS_((int num)); + + +/*===========================================================================* + * + * incMacroBlockBits() + * + * Increments the number of Macro Block bits and the total of Frame + * bits by the number passed. + * + * RETURNS: nothing + *===========================================================================*/ +extern void incMacroBlockBits _ANSI_ARGS_((int num)); + + +/*===========================================================================* + * + * SetRateControl () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + *===========================================================================*/ +extern void SetRateControl _ANSI_ARGS_((char *charPtr)); + + +/*===========================================================================* + * + * setBufferSize () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + *===========================================================================*/ +extern void +setBufferSize(const char * const charPtr); + + +/*===========================================================================* + * + * getBufferSize () + * + * returns the buffer size read from the parameter file. Size is + * in bits- not in units of 16k as written to the sequence header. + * + * RETURNS: int (or -1 if invalid) + *===========================================================================*/ +extern int getBufferSize _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * setBitRate () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + * + * SIDE EFFECTS: global variables + *===========================================================================*/ +extern void +setBitRate(const char * const charPtr); + + +/*===========================================================================* + * + * getBitRate () + * + * Returns the bit rate read from the parameter file. This is the + * real rate in bits per second, not in 400 bit units as is written to + * the sequence header. + * + * RETURNS: int (-1 if Variable mode operation) + *===========================================================================*/ +extern int getBitRate _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * getRateMode () + * + * Returns the rate mode- interpreted waa either Fixed or Variable + * + * RETURNS: integer + *===========================================================================*/ +extern int getRateMode _ANSI_ARGS_((void)); + + +/*===========================================================================* + * + * incQuantOverride() + * + * counter of override of quantization + * + * RETURNS: nothing + *===========================================================================*/ +extern void incQuantOverride _ANSI_ARGS_((int num)); + diff --git a/converter/ppm/ppmtompeg/headers/readframe.h b/converter/ppm/ppmtompeg/headers/readframe.h new file mode 100644 index 00000000..3a6876b1 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/readframe.h @@ -0,0 +1,69 @@ +/*===========================================================================* + * readframe.h * + * * + * stuff dealing with reading frames * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "pm_c_util.h" + +/*===========* + * CONSTANTS * + *===========*/ + +#define PPM_FILE_TYPE 0 +#define YUV_FILE_TYPE 2 +#define ANY_FILE_TYPE 3 +#define BASE_FILE_TYPE 4 +#define PNM_FILE_TYPE 5 +#define SUB4_FILE_TYPE 6 +#define JPEG_FILE_TYPE 7 +#define JMOVIE_FILE_TYPE 8 +#define Y_FILE_TYPE 9 + + +struct inputSource; + +void +ReadFrameFile(MpegFrame * const frameP, + FILE * const ifP, + const char * const conversion, + bool * const eofP); + +void +ReadFrame(MpegFrame * const frameP, + struct inputSource * const inputSourceP, + unsigned int const frameNumber, + const char * const conversion, + bool * const endOfStreamP); + +FILE * +ReadIOConvert(struct inputSource * const inputSourceP, + unsigned int const frameNumber); + +extern void SetFileType(const char * const conversion); +extern void SetFileFormat(const char * const format); +extern void SetResize(bool const set); + +extern int baseFormat; diff --git a/converter/ppm/ppmtompeg/headers/rgbtoycc.h b/converter/ppm/ppmtompeg/headers/rgbtoycc.h new file mode 100644 index 00000000..52159963 --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/rgbtoycc.h @@ -0,0 +1,39 @@ +/*===========================================================================* + * rgbtoycc.h * + * * + * Procedures to convert from RGB space to YUV space * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + + +#include "frame.h" +#include "pnm.h" + +void +PNMtoYUV(MpegFrame * const frame, + xel ** const xels, + unsigned int const cols, + unsigned int const rows, + xelval const maxval); diff --git a/converter/ppm/ppmtompeg/headers/specifics.h b/converter/ppm/ppmtompeg/headers/specifics.h new file mode 100644 index 00000000..7bcf4ace --- /dev/null +++ b/converter/ppm/ppmtompeg/headers/specifics.h @@ -0,0 +1,36 @@ +#include "ansi.h" + + +/*===========* + * TYPES * + *===========*/ + +typedef struct bs_def { + int num; + boolean relative; + char qscale; + BlockMV *mv; /* defined in mtypes.h */ + struct bs_def *next; +} Block_Specifics; + +typedef struct detail_def { + int num; + char qscale; + struct detail_def *next; +} Slice_Specifics; + +typedef struct fsl_def { + int framenum; + int frametype; + char qscale; + Slice_Specifics *slc; + Block_Specifics *bs; + struct fsl_def *next; +} FrameSpecList; + + +void Specifics_Init _ANSI_ARGS_((void)); +int SpecLookup _ANSI_ARGS_((int fn, int typ, int num, + BlockMV **info, int start_qs)); +int SpecTypeLookup _ANSI_ARGS_((int fn)); + diff --git a/converter/ppm/ppmtompeg/huff.c b/converter/ppm/ppmtompeg/huff.c new file mode 100644 index 00000000..821daca1 --- /dev/null +++ b/converter/ppm/ppmtompeg/huff.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/huff.c,v 1.6 1995/01/19 23:07:39 eyhung Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#include "mtypes.h" +#include "huff.h" + +int huff_maxlevel[32] = { 41, 19, 6, 5, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; + +uint32 huff_table0[41] = { 0x0, 0x6, 0x8, 0xa, 0xc, 0x4c, 0x42, 0x14, 0x3a, 0x30, 0x26, 0x20, 0x34, 0x32, 0x30, 0x2e, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20 }; +int huff_bits0[41] = { 0, 3, 5, 6, 8, 9, 9, 11, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; + +uint32 huff_table1[19] = { 0x0, 0x6, 0xc, 0x4a, 0x18, 0x36, 0x2c, 0x2a, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x26, 0x24, 0x22, 0x20 }; +int huff_bits1[19] = { 0, 4, 7, 9, 11, 13, 14, 14, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17 }; + +uint32 huff_table2[6] = { 0x0, 0xa, 0x8, 0x16, 0x28, 0x28 }; +int huff_bits2[6] = { 0, 5, 8, 11, 13, 14 }; + +uint32 huff_table3[5] = { 0x0, 0xe, 0x48, 0x38, 0x26 }; +int huff_bits3[5] = { 0, 6, 9, 13, 14 }; + +uint32 huff_table4[4] = { 0x0, 0xc, 0x1e, 0x24 }; +int huff_bits4[4] = { 0, 6, 11, 13 }; + +uint32 huff_table5[4] = { 0x0, 0xe, 0x12, 0x24 }; +int huff_bits5[4] = { 0, 7, 11, 14 }; + +uint32 huff_table6[4] = { 0x0, 0xa, 0x3c, 0x28 }; +int huff_bits6[4] = { 0, 7, 13, 17 }; + +uint32 huff_table7[3] = { 0x0, 0x8, 0x2a }; +int huff_bits7[3] = { 0, 7, 13 }; + +uint32 huff_table8[3] = { 0x0, 0xe, 0x22 }; +int huff_bits8[3] = { 0, 8, 13 }; + +uint32 huff_table9[3] = { 0x0, 0xa, 0x22 }; +int huff_bits9[3] = { 0, 8, 14 }; + +uint32 huff_table10[3] = { 0x0, 0x4e, 0x20 }; +int huff_bits10[3] = { 0, 9, 14 }; + +uint32 huff_table11[3] = { 0x0, 0x46, 0x34 }; +int huff_bits11[3] = { 0, 9, 17 }; + +uint32 huff_table12[3] = { 0x0, 0x44, 0x32 }; +int huff_bits12[3] = { 0, 9, 17 }; + +uint32 huff_table13[3] = { 0x0, 0x40, 0x30 }; +int huff_bits13[3] = { 0, 9, 17 }; + +uint32 huff_table14[3] = { 0x0, 0x1c, 0x2e }; +int huff_bits14[3] = { 0, 11, 17 }; + +uint32 huff_table15[3] = { 0x0, 0x1a, 0x2c }; +int huff_bits15[3] = { 0, 11, 17 }; + +uint32 huff_table16[3] = { 0x0, 0x10, 0x2a }; +int huff_bits16[3] = { 0, 11, 17 }; + +uint32 huff_table17[2] = { 0x0, 0x3e }; +int huff_bits17[2] = { 0, 13 }; + +uint32 huff_table18[2] = { 0x0, 0x34 }; +int huff_bits18[2] = { 0, 13 }; + +uint32 huff_table19[2] = { 0x0, 0x32 }; +int huff_bits19[2] = { 0, 13 }; + +uint32 huff_table20[2] = { 0x0, 0x2e }; +int huff_bits20[2] = { 0, 13 }; + +uint32 huff_table21[2] = { 0x0, 0x2c }; +int huff_bits21[2] = { 0, 13 }; + +uint32 huff_table22[2] = { 0x0, 0x3e }; +int huff_bits22[2] = { 0, 14 }; + +uint32 huff_table23[2] = { 0x0, 0x3c }; +int huff_bits23[2] = { 0, 14 }; + +uint32 huff_table24[2] = { 0x0, 0x3a }; +int huff_bits24[2] = { 0, 14 }; + +uint32 huff_table25[2] = { 0x0, 0x38 }; +int huff_bits25[2] = { 0, 14 }; + +uint32 huff_table26[2] = { 0x0, 0x36 }; +int huff_bits26[2] = { 0, 14 }; + +uint32 huff_table27[2] = { 0x0, 0x3e }; +int huff_bits27[2] = { 0, 17 }; + +uint32 huff_table28[2] = { 0x0, 0x3c }; +int huff_bits28[2] = { 0, 17 }; + +uint32 huff_table29[2] = { 0x0, 0x3a }; +int huff_bits29[2] = { 0, 17 }; + +uint32 huff_table30[2] = { 0x0, 0x38 }; +int huff_bits30[2] = { 0, 17 }; + +uint32 huff_table31[2] = { 0x0, 0x36 }; +int huff_bits31[2] = { 0, 17 }; + +uint32 *huff_table[32] = { huff_table0, huff_table1, huff_table2, huff_table3, huff_table4, huff_table5, huff_table6, huff_table7, huff_table8, huff_table9, huff_table10, huff_table11, huff_table12, huff_table13, huff_table14, huff_table15, huff_table16, huff_table17, huff_table18, huff_table19, huff_table20, huff_table21, huff_table22, huff_table23, huff_table24, huff_table25, huff_table26, huff_table27, huff_table28, huff_table29, huff_table30, huff_table31 }; +int *huff_bits[32] = { huff_bits0, huff_bits1, huff_bits2, huff_bits3, huff_bits4, huff_bits5, huff_bits6, huff_bits7, huff_bits8, huff_bits9, huff_bits10, huff_bits11, huff_bits12, huff_bits13, huff_bits14, huff_bits15, huff_bits16, huff_bits17, huff_bits18, huff_bits19, huff_bits20, huff_bits21, huff_bits22, huff_bits23, huff_bits24, huff_bits25, huff_bits26, huff_bits27, huff_bits28, huff_bits29, huff_bits30, huff_bits31 }; diff --git a/converter/ppm/ppmtompeg/huff.h b/converter/ppm/ppmtompeg/huff.h new file mode 100644 index 00000000..4d0b8840 --- /dev/null +++ b/converter/ppm/ppmtompeg/huff.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/huff.h,v 1.2 1995/01/19 23:08:28 eyhung Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#define HUFF_MAXRUN 32 +#define HUFF_MAXLEVEL 41 + +extern int huff_maxlevel[]; +extern uint32 *huff_table[]; +extern int *huff_bits[]; diff --git a/converter/ppm/ppmtompeg/huff.table b/converter/ppm/ppmtompeg/huff.table new file mode 100644 index 00000000..4f01d325 --- /dev/null +++ b/converter/ppm/ppmtompeg/huff.table @@ -0,0 +1,172 @@ +# +# Copyright (c) 1993 The Regents of the University of California. +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose, without fee, and without written agreement is +# hereby granted, provided that the above copyright notice and the following +# two paragraphs appear in all copies of this software. +# +# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT +# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF +# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO +# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +# + +# +# $Header: /n/picasso/users/dwallach/vid2/mpeg_encode/RCS/huff.table,v 1.3 1993/02/17 23:21:58 dwallach Exp $ +# $Log: huff.table,v $ +# Revision 1.3 1993/02/17 23:21:58 dwallach +# checkin prior to keving's joining the project +# +# Revision 1.2 1993/01/18 10:20:02 dwallach +# *** empty log message *** +# +# + +# this files is the raw Huffman encoding tables, from +# the MPEG draft standard, P. D-41 - D-43 (Table D-2.15) + +# Format: +# Run Level VLC Code + +# Run 0, Level 1 is special -- this table has the "NOT FIRST COEFF" entry +# The "IF FIRST COEFF" would be: 0 1 1s + +0 1 11s + +0 2 0100 s +0 3 0010 1s +0 4 0000 110s +0 5 0010 0110 s +0 6 0010 0001 s +0 7 0000 0010 10s +0 8 0000 0001 1101 s +0 9 0000 0001 1000 s +0 10 0000 0001 0011 s +0 11 0000 0001 0000 s +0 12 0000 0000 1101 0s +0 13 0000 0000 1100 1s +0 14 0000 0000 1100 0s +0 15 0000 0000 1011 1s +0 16 0000 0000 0111 11s +0 17 0000 0000 0111 10s +0 18 0000 0000 0111 01s +0 19 0000 0000 0111 00s +0 20 0000 0000 0110 11s +0 21 0000 0000 0110 10s +0 22 0000 0000 0110 01s +0 23 0000 0000 0110 00s +0 24 0000 0000 0101 11s +0 25 0000 0000 0101 10s +0 26 0000 0000 0101 01s +0 27 0000 0000 0101 00s +0 28 0000 0000 0100 11s +0 29 0000 0000 0100 10s +0 30 0000 0000 0100 01s +0 31 0000 0000 0100 00s +0 32 0000 0000 0011 000s +0 33 0000 0000 0010 111s +0 34 0000 0000 0010 110s +0 35 0000 0000 0010 101s +0 36 0000 0000 0010 100s +0 37 0000 0000 0010 011s +0 38 0000 0000 0010 010s +0 39 0000 0000 0010 001s +0 40 0000 0000 0010 000s + +1 1 011s +1 2 0001 10s +1 3 0010 0101 s +1 4 0000 0011 00s +1 5 0000 0001 1011 s +1 6 0000 0000 1011 0s +1 7 0000 0000 1010 1s +1 8 0000 0000 0011 111s +1 9 0000 0000 0011 110s +1 10 0000 0000 0011 101s +1 11 0000 0000 0011 100s +1 12 0000 0000 0011 011s +1 13 0000 0000 0011 010s +1 14 0000 0000 0011 001s +1 15 0000 0000 0001 0011 s +1 16 0000 0000 0001 0010 s +1 17 0000 0000 0001 0001 s +1 18 0000 0000 0001 0000 s + +2 1 0101 s +2 2 0000 100s +2 3 0000 0010 11s +2 4 0000 0001 0100 s +2 5 0000 0000 1010 0s + +3 1 0011 1s +3 2 0010 0100 s +3 3 0000 0001 1100 s +3 4 0000 0000 1001 1s + +4 1 0011 0s +4 2 0000 0011 11s +4 3 0000 0001 0010 s + +5 1 0001 11s +5 2 0000 0010 01s +5 3 0000 0000 1001 0s + +6 1 0001 01s +6 2 0000 0001 1110 s +6 3 0000 0000 0001 0100 s + +7 1 0001 00s +7 2 0000 0001 0101 s + +8 1 0000 111s +8 2 0000 0001 0001 s + +9 1 0000 101s +9 2 0000 0000 1000 1s + +10 1 0010 0111 s +10 2 0000 0000 1000 0s + +11 1 0010 0011 s +11 2 0000 0000 0001 1010 s + +12 1 0010 0010 s +12 2 0000 0000 0001 1001 s + +13 1 0010 0000 s +13 2 0000 0000 0001 1000 s + +14 1 0000 0011 10s +14 2 0000 0000 0001 0111 s + +15 1 0000 0011 01s +15 2 0000 0000 0001 0110 s + +16 1 0000 0010 00s +16 2 0000 0000 0001 0101 s + +17 1 0000 0001 1111 s +18 1 0000 0001 1010 s +19 1 0000 0001 1001 s +20 1 0000 0001 0111 s +21 1 0000 0001 0110 s + +22 1 0000 0000 1111 1s +23 1 0000 0000 1111 0s +24 1 0000 0000 1110 1s +25 1 0000 0000 1110 0s +26 1 0000 0000 1101 1s + +27 1 0000 0000 0001 1111 s +28 1 0000 0000 0001 1110 s +29 1 0000 0000 0001 1101 s +30 1 0000 0000 0001 1100 s +31 1 0000 0000 0001 1011 s diff --git a/converter/ppm/ppmtompeg/iframe.c b/converter/ppm/ppmtompeg/iframe.c new file mode 100644 index 00000000..cb6d4683 --- /dev/null +++ b/converter/ppm/ppmtompeg/iframe.c @@ -0,0 +1,1062 @@ +/*===========================================================================* + * iframe.c * + * * + * Procedures concerned with the I-frame encoding * + * * + * EXPORTED PROCEDURES: * + * GenIFrame * + * SetSlicesPerFrame * + * SetBlocksPerSlice * + * SetIQScale * + * GetIQScale * + * ResetIFrameStats * + * ShowIFrameSummary * + * EstimateSecondsPerIFrame * + * EncodeYDC * + * EncodeCDC * + * time_elapsed * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + + +#ifdef CLOCKS_PER_SEC +#include <times.h> +#else +#include <sys/times.h> +#endif + +#include <sys/types.h> +#include <sys/param.h> +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "block.h" +#include "mpeg.h" +#include "param.h" +#include "mheaders.h" +#include "fsize.h" +#include "parallel.h" +#include "postdct.h" +#include "rate.h" +#include "specifics.h" +#include "opts.h" + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int lastNumBits = 0; +static int lastIFrame = 0; +static int numBlocks = 0; +static int numBits; +static int numFrames = 0; +static int numFrameBits = 0; +static int32 totalTime = 0; +static float totalSNR = 0.0; +static float totalPSNR = 0.0; + +static int lengths[256] = { + 0, 1, 2, 2, 3, 3, 3, 3, /* 0 - 7 */ + 4, 4, 4, 4, 4, 4, 4, 4, /* 8 - 15 */ + 5, 5, 5, 5, 5, 5, 5, 5, /* 16 - 31 */ + 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, /* 32 - 63 */ + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, /* 64 - 127 */ + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8 +}; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +int qscaleI; +int slicesPerFrame; +int blocksPerSlice; +int fCodeI, fCodeP, fCodeB; +boolean printSNR = FALSE; +boolean printMSE = FALSE; +boolean decodeRefFrames = FALSE; +Block **dct=NULL, **dctr=NULL, **dctb=NULL; +dct_data_type **dct_data; /* used in p/bframe.c */ +int TIME_RATE; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ +extern void PrintItoIBitRate _ANSI_ARGS_((int numBits, int frameNum)); + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ +void AllocDctBlocks(void ); +int SetFCodeHelper (int sr); +void CalcDistortion (MpegFrame *current, int y, int x); + +int +SetFCodeHelper(int const SR) { + + int range,fCode; + + if ( pixelFullSearch ) { + range = SR; + } else { + range = SR*2; + } + + if ( range < 256 ) { + if ( range < 64 ) { + if ( range < 32 ) { + fCode = 1; + } else { + fCode = 2; + } + } else { + if ( range < 128 ) { + fCode = 3; + } else { + fCode = 4; + } + } + } else { + if ( range < 1024 ) { + if ( range < 512 ) { + fCode = 5; + } else { + fCode = 6; + } + } else { + if ( range < 2048 ) { + fCode = 7; + } else { + fprintf(stderr, "ERROR: INVALID SEARCH RANGE!!!\n"); + exit(1); + } + } + } + return fCode; +} + + + +/*===========================================================================* + * + * SetFCode + * + * set the forward_f_code and backward_f_code according to the search + * range. Must be called AFTER pixelFullSearch and searchRange have + * been initialized. Irrelevant for I-frames, but computation is + * negligible (done only once, as well) + * + * RETURNS: nothing + * + * SIDE EFFECTS: fCodeI,fCodeP,fCodeB + * + *===========================================================================*/ +void +SetFCode(void) { + fCodeI = SetFCodeHelper(1); /* GenIFrame ignores value */ + fCodeP = SetFCodeHelper(searchRangeP); + fCodeB = SetFCodeHelper(searchRangeB); +} + + + +/*===========================================================================* + * + * SetSlicesPerFrame + * + * set the number of slices per frame + * + * RETURNS: nothing + * + * SIDE EFFECTS: slicesPerFrame + * + *===========================================================================*/ +void +SetSlicesPerFrame(int const number) { + + slicesPerFrame = number; +} + + + +/*===========================================================================* + * + * SetBlocksPerSlice + * + * set the number of blocks per slice, based on slicesPerFrame + * + * RETURNS: nothing + * + * SIDE EFFECTS: blocksPerSlice + * + *===========================================================================*/ +void +SetBlocksPerSlice(void) { + + int totalBlocks; + + totalBlocks = (Fsize_y>>4)*(Fsize_x>>4); + + if ( slicesPerFrame > totalBlocks ) { + blocksPerSlice = 1; + } else { + blocksPerSlice = totalBlocks/slicesPerFrame; + } +} + + + +/*===========================================================================* + * + * SetIQScale + * + * set the I-frame Q-scale + * + * RETURNS: nothing + * + * SIDE EFFECTS: qscaleI + * + *===========================================================================*/ +void +SetIQScale(int const qI) { + qscaleI = qI; +} + + + +/*===========================================================================* + * + * GetIQScale + * + * Get the I-frame Q-scale + * + * RETURNS: the Iframe Qscale + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +GetIQScale(void) { + return qscaleI; +} + + + +/*===========================================================================* + * + * GenIFrame + * + * generate an I-frame; appends result to bb + * + * RETURNS: I-frame appended to bb + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +GenIFrame(BitBucket * const bb, + MpegFrame * const current) { + + int x, y; + int index; + FlatBlock fb[6]; + Block dec[6]; + int32 y_dc_pred, cr_dc_pred, cb_dc_pred; + int totalBits; + int totalFrameBits; + int32 startTime, endTime; + float snr[3], psnr[3]; + int mbAddress; + int QScale; + BlockMV *info; /* Not used in Iframes, but nice to pass in anyway */ + int bitstreamMode, newQScale; + int rc_blockStart=0; + + if (dct==NULL) AllocDctBlocks(); + if (collect_quant) {fprintf(collect_quant_fp, "# I\n");} + + /* set-up for statistics */ + numFrames++; + totalFrameBits = bb->cumulativeBits; + if ( showBitRatePerFrame ) { + if ( lastNumBits == 0 ) { + lastNumBits = bb->cumulativeBits; + lastIFrame = current->id; + } else { + /* ASSUMES 30 FRAMES PER SECOND */ + + if (! realQuiet) { + fprintf(stdout, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, current->id-1, + ((bb->cumulativeBits-lastNumBits)*30)/ + (current->id-lastIFrame)); + } + + fprintf(bitRateFile, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, current->id-1, + ((bb->cumulativeBits-lastNumBits)*30)/ + (current->id-lastIFrame)); + lastNumBits = bb->cumulativeBits; + lastIFrame = current->id; + } + } + + startTime = time_elapsed(); + + Frame_AllocBlocks(current); + BlockifyFrame(current); + + DBG_PRINT(("Generating iframe\n")); + QScale = GetIQScale(); + /* Allocate bits for this frame for rate control purposes */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + targetRateControl(current); + } + + Mhead_GenPictureHeader(bb, I_FRAME, current->id, fCodeI); + /* Check for Qscale change */ + if (specificsOn) { + newQScale = SpecLookup(current->id, 0, 0 /* junk */, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + /* check for slice */ + newQScale = SpecLookup(current->id, 1, 1, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); + + if ( referenceFrame == DECODED_FRAME ) { + Frame_AllocDecoded(current, TRUE); + } else if ( printSNR ) { + Frame_AllocDecoded(current, FALSE); + } + + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + totalBits = bb->cumulativeBits; + mbAddress = 0; + + /* DCT the macroblocks */ + for (y = 0; y < (Fsize_y >> 3); y += 2) { + for (x = 0; x < (Fsize_x >> 3); x += 2) { + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "l\n"); + if (DoLaplace) {LaplaceCnum = 0;} + mp_fwd_dct_block2(current->y_blocks[y][x], dct[y][x]); + mp_fwd_dct_block2(current->y_blocks[y][x+1], dct[y][x+1]); + mp_fwd_dct_block2(current->y_blocks[y+1][x], dct[y+1][x]); + mp_fwd_dct_block2(current->y_blocks[y+1][x+1], dct[y+1][x+1]); + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "c\n"); + if (DoLaplace) {LaplaceCnum = 1;} + mp_fwd_dct_block2(current->cb_blocks[y>>1][x>>1], + dctb[y>>1][x>>1]); + if (DoLaplace) {LaplaceCnum = 2;} + mp_fwd_dct_block2(current->cr_blocks[y>>1][x>>1], + dctr[y>>1][x>>1]); + } + } + + if (DoLaplace) + CalcLambdas(); + + for (y = 0; y < (Fsize_y >> 3); y += 2) { + for (x = 0; x < (Fsize_x >> 3); x += 2) { + /* Check for Qscale change */ + if (specificsOn) { + newQScale = + SpecLookup(current->id, 2, mbAddress, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + /* Determine if new Qscale needed for Rate Control purposes */ + if (bitstreamMode == FIXED_RATE) { + rc_blockStart = bb->cumulativeBits; + newQScale = needQScaleChange(qscaleI, + current->y_blocks[y][x], + current->y_blocks[y][x+1], + current->y_blocks[y+1][x], + current->y_blocks[y+1][x+1]); + if (newQScale > 0) { + QScale = newQScale; + } + } + + if ( (mbAddress % blocksPerSlice == 0) && (mbAddress != 0) ) { + /* create a new slice */ + if (specificsOn) { + /* Make sure no slice Qscale change */ + newQScale = SpecLookup(current->id, 1, + mbAddress/blocksPerSlice, &info, + QScale); + if (newQScale != -1) QScale = newQScale; + } + Mhead_GenSliceEnder(bb); + Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + GEN_I_BLOCK(I_FRAME, current, bb, 1+(x>>1), QScale); + } else { + GEN_I_BLOCK(I_FRAME, current, bb, 1, QScale); + } + + if (WriteDistortionNumbers) { + CalcDistortion(current, y, x); + } + + if ( decodeRefFrames ) { + /* now, reverse the DCT transform */ + LaplaceCnum = 0; + for ( index = 0; index < 6; index++ ) { + if (!DoLaplace) { + Mpost_UnQuantZigBlock(fb[index], dec[index], QScale, + TRUE); + } else { + if (index == 4) {LaplaceCnum = 1;} + if (index == 5) {LaplaceCnum = 2;} + Mpost_UnQuantZigBlockLaplace(fb[index], dec[index], + QScale, TRUE); + } + mpeg_jrevdct((int16 *)dec[index]); + } + + /* now, unblockify */ + BlockToData(current->decoded_y, dec[0], y, x); + BlockToData(current->decoded_y, dec[1], y, x+1); + BlockToData(current->decoded_y, dec[2], y+1, x); + BlockToData(current->decoded_y, dec[3], y+1, x+1); + BlockToData(current->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(current->decoded_cr, dec[5], y>>1, x>>1); + } + + numBlocks++; + mbAddress++; + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + incMacroBlockBits(bb->cumulativeBits - rc_blockStart); + rc_blockStart = bb->cumulativeBits; + MB_RateOut(TYPE_IFRAME); + } + } + } + + if ( printSNR ) { + BlockComputeSNR(current,snr,psnr); + totalSNR += snr[0]; + totalPSNR += psnr[0]; + } + + numBits += (bb->cumulativeBits-totalBits); + + DBG_PRINT(("End of frame\n")); + + Mhead_GenSliceEnder(bb); + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + updateRateControl(TYPE_IFRAME); + } + + endTime = time_elapsed(); + totalTime += (endTime-startTime); + + numFrameBits += (bb->cumulativeBits-totalFrameBits); + + if ( showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(bitRateFile, "%5d\t%8d\n", current->id, + 30*(bb->cumulativeBits-totalFrameBits)); + } + + if ( frameSummary && !realQuiet ) { + + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(stdout, + "FRAME %d (I): %ld seconds (%d bits/s output)\n", + current->id, (long)((endTime-startTime)/TIME_RATE), + 30*(bb->cumulativeBits-totalFrameBits)); + if ( printSNR ) { + fprintf(stdout, + "FRAME %d: SNR: %.1f\t%.1f\t%.1f\t" + "PSNR: %.1f\t%.1f\t%.1f\n", + current->id, snr[0], snr[1], snr[2], + psnr[0], psnr[1], psnr[2]); + } + } +} + + + +/*===========================================================================* + * + * ResetIFrameStats + * + * reset the I-frame statistics + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ResetIFrameStats(void) { + numBlocks = 0; + numBits = 0; + numFrames = 0; + numFrameBits = 0; + totalTime = 0; +} + + + +float +IFrameTotalTime(void) { + return (float)totalTime/(float)TIME_RATE; +} + + + +void +ShowIFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer) { +/*---------------------------------------------------------------------------- + Print out statistics on all I frames. +-----------------------------------------------------------------------------*/ + if (numFrames > 0) { + fprintf(fpointer, "-------------------------\n"); + fprintf(fpointer, "*****I FRAME SUMMARY*****\n"); + fprintf(fpointer, "-------------------------\n"); + + fprintf(fpointer, " Blocks: %5d (%6d bits) (%5d bpb)\n", + numBlocks, numBits, numBits/numBlocks); + fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf)" + "(%2.1f%% of total)\n", + numFrames, numFrameBits, numFrameBits/numFrames, + 100.0*(float)numFrameBits/(float)totalBits); + fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", + numFrames*inputFrameBits/numFrameBits, + 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits)); + if ( printSNR ) + fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", + totalSNR/(float)numFrames, totalPSNR/(float)numFrames); + if ( totalTime == 0 ) { + fprintf(fpointer, " Seconds: NONE\n"); + } else { + fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) " + "(%9ld mps)\n", + (long)(totalTime/TIME_RATE), + (float)((float)(TIME_RATE*numFrames)/(float)totalTime), + (long)((float)TIME_RATE * (float)numFrames * + (float)inputFrameBits/(24.0*(float)totalTime)), + (long)((float)TIME_RATE*(float)numFrames * + (float)inputFrameBits/(256.0*24.0 * + (float)totalTime))); + } + } +} + + + +/*===========================================================================* + * + * EstimateSecondsPerIFrame + * + * estimates the number of seconds required per I-frame + * + * RETURNS: seconds (floating point value) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float +EstimateSecondsPerIFrame() +{ + return (float)totalTime/((float)TIME_RATE*(float)numFrames); +} + + +/*===========================================================================* + * + * EncodeYDC + * + * Encode the DC portion of a DCT of a luminance block + * + * RETURNS: result appended to bb + * + * SIDE EFFECTS: updates pred_term + * + *===========================================================================*/ +void +EncodeYDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb) { + + /* see Table B.5a -- MPEG-I doc */ + static int codes[9] = { + 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e + }; + static int codeLengths[9] = { + 3, 2, 2, 3, 3, 4, 5, 6, 7 + }; + int ydiff, ydiff_abs; + int length; + + ydiff = (dc_term - (*pred_term)); + if (ydiff > 255) { +#ifdef BLEAH + fprintf(stdout, "TRUNCATED\n"); +#endif + ydiff = 255; + } else if (ydiff < -255) { +#ifdef BLEAH + fprintf(stdout, "TRUNCATED\n"); +#endif + ydiff = -255; + } + + ydiff_abs = ABS(ydiff); + length = lengths[ydiff_abs]; + Bitio_Write(bb, codes[length], codeLengths[length]); + if ( length != 0 ) { + if ( ydiff > 0 ) { + Bitio_Write(bb, ydiff_abs, length); + } else { + Bitio_Write(bb, ~ydiff_abs, length); + } + } + + (*pred_term) += ydiff; +} + + + +/*===========================================================================* + * + * EncodeCDC + * + * Encode the DC portion of a DCT of a chrominance block + * + * RETURNS: result appended to bb + * + * SIDE EFFECTS: updates pred_term + * + *===========================================================================*/ +void +EncodeCDC(int32 const dc_term, + int32 * const pred_term, + BitBucket * const bb) { + + /* see Table B.5b -- MPEG-I doc */ + static int codes[9] = { + 0x0, 0x1, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe + }; + static int codeLengths[9] = { + 2, 2, 2, 3, 4, 5, 6, 7, 8 + }; + int cdiff, cdiff_abs; + int length; + + cdiff = (dc_term - (*pred_term)); + if (cdiff > 255) { +#ifdef BLEAH + fprintf(stdout, "TRUNCATED\n"); +#endif + cdiff = 255; + } else if (cdiff < -255) { +#ifdef BLEAH + fprintf(stdout, "TRUNCATED\n"); +#endif + cdiff = -255; + } + + cdiff_abs = ABS(cdiff); + length = lengths[cdiff_abs]; + Bitio_Write(bb, codes[length], codeLengths[length]); + if ( length != 0 ) { + if ( cdiff > 0 ) { + Bitio_Write(bb, cdiff_abs, length); + } else { + Bitio_Write(bb, ~cdiff_abs, length); + } + } + + (*pred_term) += cdiff; +} + + + +void +BlockComputeSNR(MpegFrame * const current, + float * const snr, + float * const psnr) { + + int32 tempInt; + int y, x; + int32 varDiff[3]; + double ratio[3]; + double total[3]; + uint8 **origY=current->orig_y, **origCr=current->orig_cr, + **origCb=current->orig_cb; + uint8 **newY=current->decoded_y, **newCr=current->decoded_cr, + **newCb=current->decoded_cb; + static int32 **SignalY, **NoiseY; + static int32 **SignalCb, **NoiseCb; + static int32 **SignalCr, **NoiseCr; + static short ySize[3], xSize[3]; + static boolean needs_init=TRUE; + + /* Init */ + if (needs_init) { + int ysz = (Fsize_y>>3) * sizeof(int32 *); + int xsz = (Fsize_x>>3); + + needs_init = FALSE; + for (y=0; y<3; y++) { + varDiff[y] = ratio[y] = total[y] = 0.0; + } + ySize[0]=Fsize_y; xSize[0]=Fsize_x; + ySize[1]=Fsize_y>>1; xSize[1]=Fsize_x>>1; + ySize[2]=Fsize_y>>1; xSize[2]=Fsize_x>>1; + SignalY = (int32 **) malloc(ysz); + NoiseY = (int32 **) malloc(ysz); + SignalCb = (int32 **) malloc(ysz); + NoiseCb = (int32 **) malloc(ysz); + SignalCr = (int32 **) malloc(ysz); + NoiseCr = (int32 **) malloc(ysz); + if (SignalY == NULL || NoiseY == NULL || SignalCr == NULL || + NoiseCb == NULL || SignalCb == NULL || NoiseCr == NULL) { + fprintf(stderr, "Out of memory in BlockComputeSNR\n"); + exit(-1); + } + for (y = 0; y < ySize[0]>>3; y++) { + SignalY[y] = (int32 *) calloc(xsz,4); + SignalCr[y] = (int32 *) calloc(xsz,4); + SignalCb[y] = (int32 *) calloc(xsz,4); + NoiseY[y] = (int32 *) calloc(xsz,4); + NoiseCr[y] = (int32 *) calloc(xsz,4); + NoiseCb[y] = (int32 *) calloc(xsz,4); + } + } else { + for (y = 0; y < ySize[0]>>3; y++) { + memset((char *) &NoiseY[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &SignalY[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &NoiseCb[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &NoiseCr[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &SignalCb[y][0], 0, (xSize[0]>>3) * 4); + memset((char *) &SignalCr[y][0], 0, (xSize[0]>>3) * 4); + } + } + + /* find all the signal and noise */ + for (y = 0; y < ySize[0]; y++) { + for (x = 0; x < xSize[0]; x++) { + tempInt = (origY[y][x] - newY[y][x]); + NoiseY[y>>4][x>>4] += tempInt*tempInt; + total[0] += (double)abs(tempInt); + tempInt = origY[y][x]; + SignalY[y>>4][x>>4] += tempInt*tempInt; + }} + for (y = 0; y < ySize[1]; y++) { + for (x = 0; x < xSize[1]; x ++) { + tempInt = (origCb[y][x] - newCb[y][x]); + NoiseCb[y>>3][x>>3] += tempInt*tempInt; + total[1] += (double)abs(tempInt); + tempInt = origCb[y][x]; + SignalCb[y>>3][x>>3] += tempInt*tempInt; + tempInt = (origCr[y][x]-newCr[y][x]); + NoiseCr[y>>3][x>>3] += tempInt*tempInt; + total[2] += (double)abs(tempInt); + tempInt = origCr[y][x]; + SignalCr[y>>3][x>>3] += tempInt*tempInt; + }} + + /* Now sum up that noise */ + for(y=0; y<Fsize_y>>4; y++){ + for(x=0; x<Fsize_x>>4; x++){ + varDiff[0] += NoiseY[y][x]; + varDiff[1] += NoiseCb[y][x]; + varDiff[2] += NoiseCr[y][x]; + if (printMSE) printf("%4d ",(int)(NoiseY[y][x]/256.0)); + } + if (printMSE) puts(""); + } + + /* Now look at those ratios! */ + for(y=0; y<Fsize_y>>4; y++){ + for(x=0; x<Fsize_x>>4; x++){ + ratio[0] += (double)SignalY[y][x]/(double)varDiff[0]; + ratio[1] += (double)SignalCb[y][x]/(double)varDiff[1]; + ratio[2] += (double)SignalCr[y][x]/(double)varDiff[2]; + }} + + for (x=0; x<3; x++) { + snr[x] = 10.0 * log10(ratio[x]); + psnr[x] = 20.0 * log10(255.0/sqrt((double)varDiff[x]/ + (double)(ySize[x]*xSize[x]))); + + if (! realQuiet) { + fprintf(stdout, "Mean error[%1d]: %f\n", + x, total[x] / (double)(xSize[x] * ySize[x])); + } + + } +} + + + +void +WriteDecodedFrame(MpegFrame * const frame) { + + FILE * fpointer; + char fileName[256]; + int width, height; + int y; + + /* need to save decoded frame to disk because it might be accessed + by another process */ + + width = Fsize_x; + height = Fsize_y; + + sprintf(fileName, "%s.decoded.%d", outputFileName, frame->id); + + if (!realQuiet) { + fprintf(stdout, "Outputting to %s\n", fileName); + fflush(stdout); + } + + fpointer = fopen(fileName, "wb"); + + for ( y = 0; y < height; y++ ) { + fwrite(frame->decoded_y[y], 1, width, fpointer); + } + + for (y = 0; y < (height >> 1); y++) { /* U */ + fwrite(frame->decoded_cb[y], 1, width >> 1, fpointer); + } + + for (y = 0; y < (height >> 1); y++) { /* V */ + fwrite(frame->decoded_cr[y], 1, width >> 1, fpointer); + } + fflush(fpointer); + fclose(fpointer); +} + + + +void +PrintItoIBitRate(int const numBits, + int const frameNum) { + + if ( showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + + if (! realQuiet) { + fprintf(stdout, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, frameNum-1, + ((numBits-lastNumBits)*30)/ + (frameNum-lastIFrame)); + } + + fprintf(bitRateFile, "I-to-I (frames %5d to %5d) bitrate: %8d\n", + lastIFrame, frameNum-1, + ((numBits-lastNumBits)*30)/ + (frameNum-lastIFrame)); + } +} + + + +/*===========================================================================* + * + * AllocDctBlocks + * + * allocate memory for dct blocks + * + * RETURNS: nothing + * + * SIDE EFFECTS: creates dct, dctr, dctb + * + *===========================================================================*/ +void +AllocDctBlocks(void) { + int dctx, dcty; + int i; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + dct = (Block **) malloc(sizeof(Block *) * dcty); + ERRCHK(dct, "malloc"); + for (i = 0; i < dcty; i++) { + dct[i] = (Block *) malloc(sizeof(Block) * dctx); + ERRCHK(dct[i], "malloc"); + } + + dct_data = (dct_data_type **) malloc(sizeof(dct_data_type *) * dcty); + ERRCHK(dct_data, "malloc"); + for (i = 0; i < dcty; i++) { + dct_data[i] = (dct_data_type *) malloc(sizeof(dct_data_type) * dctx); + ERRCHK(dct[i], "malloc"); + } + + dctr = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); + dctb = (Block **) malloc(sizeof(Block *) * (dcty >> 1)); + ERRCHK(dctr, "malloc"); + ERRCHK(dctb, "malloc"); + for (i = 0; i < (dcty >> 1); i++) { + dctr[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); + dctb[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1)); + ERRCHK(dctr[i], "malloc"); + ERRCHK(dctb[i], "malloc"); + } +} + + + +/*======================================================================* + * + * time_elapsed + * + * Handle different time systems on different machines + * + * RETURNS number of seconds process time used + * + *======================================================================*/ +int32 time_elapsed(void) { +#ifdef CLOCKS_PER_SEC + /* ANSI C */ + TIME_RATE = CLOCKS_PER_SEC; + return (int32) clock(); +#else + struct tms timeBuffer; + TIME_RATE = 60; + times(&timeBuffer); + return timeBuffer.tms_utime + timeBuffer.tms_stime; +#endif +} + + + +void +CalcDistortion(MpegFrame * const current, + int const y, + int const x) { + + int qscale, distort=0; + Block decblk; + FlatBlock fblk; + int datarate = 0; + + for (qscale = 1; qscale < 32; qscale ++) { + distort = 0; + datarate = 0; + Mpost_QuantZigBlock(dct[y][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x], decblk); + + Mpost_QuantZigBlock(dct[y][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y][x+1], decblk); + + Mpost_QuantZigBlock(dct[y+1][x], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x], decblk); + + Mpost_QuantZigBlock(dct[y+1][x+1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->y_blocks[y+1][x+1], decblk); + + Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cb_blocks[y>>1][x>>1], decblk); + + Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], fblk, qscale, TRUE); + Mpost_UnQuantZigBlock(fblk, decblk, qscale, TRUE); + if (collect_distortion_detailed) datarate += CalcRLEHuffLength(fblk); + mpeg_jrevdct((int16 *)decblk); + distort += mse(current->cr_blocks[y >> 1][x >> 1], decblk); + + if (!collect_distortion_detailed) { + fprintf(distortion_fp, "\t%d\n", distort); + } else if (collect_distortion_detailed == 1) { + fprintf(distortion_fp, "\t%d\t%d\n", distort, datarate); + } else { + fprintf(fp_table_rate[qscale-1], "%d\n", datarate); + fprintf(fp_table_dist[qscale-1], "%d\n", distort); + } + } +} + + + + diff --git a/converter/ppm/ppmtompeg/input.c b/converter/ppm/ppmtompeg/input.c new file mode 100644 index 00000000..2b87afa7 --- /dev/null +++ b/converter/ppm/ppmtompeg/input.c @@ -0,0 +1,515 @@ +/*===========================================================================* + * input.c + * + * Stuff for getting the raw frame input for the program + * + *===========================================================================*/ + +/* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ + +#define _XOPEN_SOURCE 1 + /* This makes sure popen() is in stdio.h. In GNU libc 2.1.3, + _POSIX_C_SOURCE = 2 is sufficient, but on AIX 4.3, the higher level + _XOPEN_SOURCE is required. 2000.09.09 + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <limits.h> + +#include "nstring.h" +#include "mallocvar.h" +#include "parallel.h" +#include "readframe.h" +#include "param.h" +#include "jpeg.h" +#include "input.h" + +extern boolean realQuiet; /* TRUE = no messages to stdout */ + +struct InputFileEntry { + char left[256]; + char right[256]; + bool glob; /* if FALSE, left is complete name */ + int startID; + int endID; + int skip; + int numPadding; /* -1 if there is none */ + int numFiles; + bool repeat; +}; + + +struct inputSource inputSource; + + + +void +GetNthInputFileName(struct inputSource * const inputSourceP, + unsigned int const n, + const char ** const fileNameP) { +/*---------------------------------------------------------------------------- + Return the file name of the Nth input file. +-----------------------------------------------------------------------------*/ + static int lastN = 0, lastMapN = 0, lastSoFar = 0; + int mapN; + int index; + int soFar; + int numPadding; + struct InputFileEntry * mapNEntryP; + + assert(!inputSourceP->stdinUsed); + assert(n < inputSourceP->numInputFiles); + + if (n >= lastN) { + soFar = lastSoFar; + index = lastMapN; + } else { + soFar = 0; + index = 0; + } + + assert(index < inputSourceP->numInputFileEntries); + + while (soFar + inputSourceP->inputFileEntries[index]->numFiles <= n) { + soFar += inputSourceP->inputFileEntries[index]->numFiles; + ++index; + assert(index < inputSourceP->numInputFileEntries); + } + + mapN = index; + + mapNEntryP = inputSourceP->inputFileEntries[mapN]; + + index = mapNEntryP->startID + mapNEntryP->skip*(n - soFar); + + numPadding = mapNEntryP->numPadding; + + if (numPadding != -1) { + char numBuffer[33]; + int loop; + + sprintf(numBuffer, "%32d", index); + for (loop = 32-numPadding; loop < 32; ++loop) { + if (numBuffer[loop] != ' ') + break; + else + numBuffer[loop] = '0'; + } + + if (mapNEntryP->repeat != TRUE) + asprintfN(fileNameP, "%s%s%s", + mapNEntryP->left, &numBuffer[32-numPadding], + mapNEntryP->right); + else + asprintfN(fileNameP, "%s", mapNEntryP->left); + } else { + if (mapNEntryP->repeat != TRUE) + asprintfN(fileNameP, "%s%d%s", + mapNEntryP->left, index, mapNEntryP->right); + else + asprintfN(fileNameP, "%s", mapNEntryP->left); + } + + lastN = n; + lastMapN = mapN; + lastSoFar = soFar; +} + + + +void +ReadNthFrame(struct inputSource * const inputSourceP, + unsigned int const frameNumber, + boolean const remoteIO, + boolean const childProcess, + boolean const separateConversion, + const char * const slaveConversion, + const char * const inputConversion, + MpegFrame * const frameP, + bool * const endOfStreamP) { + + if (remoteIO) + /* Get the frame from the remote I/O server */ + GetRemoteFrame(frameP, frameNumber); + else { + /* Get the frame out of the file in which it lives */ + + const char * conversion; + + if (childProcess && separateConversion) + conversion = slaveConversion; + else + conversion = inputConversion; + + ReadFrame(frameP, inputSourceP, frameNumber, conversion, endOfStreamP); + } +} + + + +/* Jim Boucher's code */ + +void +JM2JPEG(struct inputSource * const inputSourceP) { + char full_path[1024]; + char inter_file[1024]; + int ci; + + for(ci = 0; ci < inputSourceP->numInputFileEntries; ci++) { + inter_file[0] = '\0'; + full_path[0] = '\0'; + strcpy(full_path, currentPath); + + if (!inputSource.stdinUsed) { + strcat(full_path, "/"); + strcat(full_path, inputSourceP->inputFileEntries[ci]->left); + strcpy(inter_file,full_path); + + if (!realQuiet) + fprintf(stdout, "Extracting JPEG's in the JMOVIE from %s\n", + full_path); + + JMovie2JPEG(full_path, + inter_file, + inputSourceP->inputFileEntries[ci]->startID, + inputSourceP->inputFileEntries[ci]->endID); + } else + pm_error("ERROR: Cannot use JMovie format on Standard Input"); + } +} + + + +static const char * +SkipSpacesTabs(const char * const start) { + + const char * p; + + for (p = start; *p == ' ' || *p == '\t'; ++p); + + return p; +} + + + +static void +processGlob(const char * const input, + struct InputFileEntry * const inputFileEntryP) { + + const char *globPtr; + char * charPtr; + char left[256], right[256]; + char leftNumText[256], rightNumText[256]; + char skipNumText[256]; + int leftNum, rightNum; + int skipNum; + boolean padding; + int numPadding = 0; + + inputFileEntryP->glob = TRUE; + inputFileEntryP->repeat = FALSE; + + /* star expand */ + + globPtr = input; + charPtr = left; + /* copy left of '*' */ + while ( (*globPtr != '\0') && (*globPtr != '*') ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if (*globPtr == '\0') { + fprintf(stderr, + "WARNING: expanding non-star regular expression\n"); + inputFileEntryP->repeat = TRUE; + globPtr = input; + charPtr = left; + /* recopy left of whitespace */ + while ( (*globPtr != '\0') && (*globPtr != '*') && + (*globPtr != ' ') && (*globPtr != '\t')) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + *right = '\0'; + } else { + + globPtr++; + charPtr = right; + /* copy right of '*' */ + while ( (*globPtr != '\0') && (*globPtr != ' ') && + (*globPtr != '\t') ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + } + + globPtr = SkipSpacesTabs(globPtr); + + if ( *globPtr != '[' ) { + fprintf(stderr, + "ERROR: " + "Invalid input file expansion expression (no '[')\n"); + exit(1); + } + + globPtr++; + charPtr = leftNumText; + /* copy left number */ + while ( ISDIGIT(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if ( *globPtr != '-' ) { + fprintf(stderr, + "ERROR: " + "Invalid input file expansion expression (no '-')\n"); + exit(1); + } + + globPtr++; + charPtr = rightNumText; + /* copy right number */ + while ( ISDIGIT(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + if ( atoi(rightNumText) < atoi(leftNumText) ) { + fprintf(stderr, + "ERROR: " + "Beginning of input range is higher than end.\n"); + exit(1); + } + + + if ( *globPtr != ']' ) { + if ( *globPtr != '+' ) { + fprintf(stderr, + "ERROR: " + "Invalid input file expansion expression " + "(no ']')\n"); + exit(1); + } + + globPtr++; + charPtr = skipNumText; + /* copy skip number */ + while ( ISDIGIT(*globPtr) ) { + *charPtr = *globPtr; + charPtr++; + globPtr++; + } + *charPtr = '\0'; + + if ( *globPtr != ']' ) { + fprintf(stderr, + "ERROR: Invalid input file expansion expression " + "(no ']')\n"); + exit(1); + } + + skipNum = atoi(skipNumText); + } else { + skipNum = 1; + } + + leftNum = atoi(leftNumText); + rightNum = atoi(rightNumText); + + if ( (leftNumText[0] == '0') && (leftNumText[1] != '\0') ) { + padding = TRUE; + numPadding = strlen(leftNumText); + } else { + padding = FALSE; + } + + inputFileEntryP->startID = leftNum; + inputFileEntryP->endID = rightNum; + inputFileEntryP->skip = skipNum; + inputFileEntryP->numFiles = + (rightNum-leftNum+1)/skipNum; + strcpy(inputFileEntryP->left, left); + strcpy(inputFileEntryP->right, right); + if ( padding ) { + inputFileEntryP->numPadding = numPadding; + } else { + inputFileEntryP->numPadding = -1; + } +} + + + +static void processJmovie(const char * const input, + struct InputFileEntry * const inputFileEntryP) { + FILE *jmovie; + char full_path[1024]; + + inputFileEntryP->glob = TRUE; + full_path[0] = '\0'; + strcpy(full_path, currentPath); + + strcat(full_path, "/"); + strcat(full_path, input); + jmovie = fopen(input, "rb"); + + if (jmovie == NULL) { + perror (input); + exit (1); + } + + fseek (jmovie, (8*sizeof(char)), 0); + fseek (jmovie, (2*sizeof(int)), 1); + + if (fread(&(inputFileEntryP->numFiles), + sizeof(int), 1, jmovie) != 1) { + perror ("Error in reading number of frames in JMOVIE"); + exit(1); + } + fclose (jmovie); + + strcpy(inputFileEntryP->right,".jpg"); + inputFileEntryP->numPadding = -1; + inputFileEntryP->startID = 1; + inputFileEntryP->endID = (inputFileEntryP->numFiles-1); + inputFileEntryP->skip = 1; + if (! realQuiet) { + fprintf (stdout, + "Encoding all %d frames from JMOVIE.\n", + inputFileEntryP->endID); + } +} + + + +static void +processSimpleFileName(const char * const input, + struct InputFileEntry * const inputFileEntryP) { + + inputFileEntryP->glob = FALSE; + inputFileEntryP->numFiles = 1; + /* fixes a bug from version 1.3: */ + inputFileEntryP->numPadding = 0; + /* fixes a bug from version 1.4 */ + strcpy(inputFileEntryP->right,"\0"); + inputFileEntryP->startID = 0; + inputFileEntryP->endID = 0; + inputFileEntryP->skip = 0; +} + + +#define INPUT_ENTRY_BLOCK_SIZE 128 + +void +AddInputFiles(struct inputSource * const inputSourceP, + const char * const input) { + + unsigned int const currentIndex = inputSourceP->numInputFileEntries; + + struct InputFileEntry * currentEntryP; + + if (currentIndex >= inputSourceP->ifArraySize) { + /* Get more space */ + inputSourceP->ifArraySize += INPUT_ENTRY_BLOCK_SIZE; + REALLOCARRAY_NOFAIL(inputSourceP->inputFileEntries, + inputSourceP->ifArraySize); + } + MALLOCVAR_NOFAIL(inputSourceP->inputFileEntries[currentIndex]); + currentEntryP = inputSourceP->inputFileEntries[currentIndex]; + + if (input[strlen(input)-1] == ']') + processGlob(input, currentEntryP); + else { + strcpy(currentEntryP->left, input); + if (baseFormat == JMOVIE_FILE_TYPE) + processJmovie(input, currentEntryP); + else + processSimpleFileName(input, currentEntryP); + } + inputSourceP->numInputFiles += currentEntryP->numFiles; + ++inputSourceP->numInputFileEntries; +} + + + +void +SetStdinInput(struct inputSource * const inputSourceP) { + + assert(inputSourceP->numInputFileEntries == 0); + + inputSourceP->stdinUsed = TRUE; + inputSourceP->numInputFiles = INT_MAX; +} + + + +void +CreateInputSource(struct inputSource ** const inputSourcePP) { + + struct inputSource * inputSourceP; + + MALLOCVAR_NOFAIL(inputSourceP); + + inputSourceP->stdinUsed = FALSE; + inputSourceP->numInputFileEntries = 0; + inputSourceP->ifArraySize = 1; + inputSourceP->numInputFiles = 0; + MALLOCARRAY_NOFAIL(inputSourceP->inputFileEntries, 1); + + *inputSourcePP = inputSourceP; +} + + + +void +DestroyInputSource(struct inputSource * const inputSourceP) { + + unsigned int i; + + for (i = 0; i < inputSourceP->numInputFileEntries; ++i) + free(inputSourceP->inputFileEntries[i]); + + free(inputSourceP->inputFileEntries); + + free(inputSourceP); +} + + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/jpeg.c b/converter/ppm/ppmtompeg/jpeg.c new file mode 100644 index 00000000..3aad6364 --- /dev/null +++ b/converter/ppm/ppmtompeg/jpeg.c @@ -0,0 +1,634 @@ +/*===========================================================================* + * jpeg.c + * + * procedures to deal with JPEG files + * + * EXPORTED PROCEDURES: + * JMovie2JPEG + * ReadJPEG + * + *===========================================================================*/ + +/* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ + +/*==============* + * HEADER FILES * + *==============*/ +#define _XOPEN_SOURCE /* Make sure stdio.h contains fileno() */ +#include <stdio.h> +#include "all.h" +/* With the lossless jpeg patch applied to the Jpeg library + (ftp://ftp.wizards.dupont.com/pub/ImageMagick/delegates/ljpeg-6b.tar.gz), + the name of min_DCT_scaled_size changes to min_codec_data_unit, + for some reason. With this macro, we change it back. +*/ +#define min_codec_data_unit min_DCT_scaled_size +#include <jpeglib.h> +#undef min_codec_data_unit +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "rgbtoycc.h" +#include "jpeg.h" + +#include "mallocvar.h" + +/* make it happier.... */ +#undef DCTSIZE2 + +/* jcopy_sample_rows() is an internal routine in the JPEG library, not + meant for use by us. We should figure out what the official interface + for this is and use it. The following is copied out of jpegint.h, which + is part of the JPEG library source code. + */ +extern void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); + + +#define HEADER_SIZE 607 /*JFIF header size used on output images*/ + + + +/*=======================================================================* + * * + * JMovie2JPEG * + * * + * Splits up a Parallax J_Movie into a set of JFIF image files * + * * + * RETURNS: nothing * + * * + * SIDE EFFECTS: none * + * * + * Contributed By James Boucher(jboucher@flash.bu.edu) * + * Boston University Multimedia Communications Lab * + * This code was adapted from the Berkeley Playone.c and Brian Smith's * + * JGetFrame code after being modified on 10-7-93 by Dinesh Venkatesh * + * of BU. * + * This code converts a version 2 Parallax J_Movie into a * + * set of JFIF compatible JPEG images. It works for all image * + * sizes and qualities. * + ************************************************************************/ +void +JMovie2JPEG(const char * const infilename, + /* input filename string */ + const char * const obase, + /* output filename base string=>obase##.jpg */ + int const start, + /* first frame to be extracted */ + int const end + /* last frame to be extracted */ + ) { + + FILE *inFile; /* Jmovie file pointer */ + FILE *outFile; /* JPEG file pointer for output file */ + int fd, i; /* input file descriptor and a counting variable*/ + char ofname[256]; /* output filename string */ + int Temp = 0, temp = 0; /* dummy variables */ + int image_offset = 0; /* counting variable */ + /* J_Movie header infomation */ + int ver_no; /* version number - expected to be 2 */ + int fps; /* frame rate - frames per second */ + int no_frames; /* total number of frames in jmovie */ + int bandwidth; /* bandwidth required for normal playback*/ + int qfactor; /* quality factor used to scale Q matrix */ + int mapsize; /* number of color map entries - 2^24 */ + int audio_tracks; /* number of audio tracks ==1 */ + int audiosize; /*number of bytes in audio tracks */ + int *inoffsets; /* input frame offsets from start of jmovie*/ + int width; /* image width */ + int height; /* image height */ + int size; /* total image size in bytes */ + char op_code; /* jmovie op_code */ + char jpeg_size[4]; /* jpeg data size */ + static char junk[1000]; /* data sink for audio data */ + int last; /* Number of last frame we will process */ + + /* The next array represents the default JFIF header for + quality = 100 and size = 320x240. The values are + adjusted as the J_Movie header is read. The default + size of this array is set large so as to make room + for the appending of the jpeg bitstream. It can be + made smaller if you have a better idea of its expected size + */ + static unsigned char inbuffer[300000] = { + 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, + 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x11, + 0x08, 0x00, 0xF0, 0x01, 0x40, 0x03, 0x01, 0x21, + 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xFF, + 0xDB, 0x00, 0x84, 0x00, 0x10, 0x0B, 0x0C, 0x0E, + 0x0C, 0x0A, 0x10, 0x0E, 0x0D, 0x0E, 0x12, + 0x11, 0x10, 0x13, 0x18, 0x28, 0x1A, 0x18, 0x16, + 0x16, 0x18, 0x31, 0x23, 0x25, 0x1D, 0x28, 0x3A, + 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38, 0x37, 0x40, + 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57, 0x45, 0x37, + 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F, 0x62, 0x67, + 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79, 0x70, 0x64, + 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01, 0x11, 0x12, + 0x12, 0x18, 0x15, 0x18, 0x2F, 0x1A, 0x1A, 0x2F, + 0x63, 0x42, 0x38, 0x42, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, + 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0xFF, 0xC4, + 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, + 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, + 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, + 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, + 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, + 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, + 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, + 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, + 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, + 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, + 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, + 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, + 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, + 0xF7, 0xF8, 0xF9, 0xFA, 0x01, 0x00, 0x03, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0A, 0x0B, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, + 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, + 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, + 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, + 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, + 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, + 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, + 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, + 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, + 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, + 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, + 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, + 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, + 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0xDA, + 0x00, 0x0C, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, + 0x11, 0x00, 0x3F, 0x00 + + }; + + if (start > end) { + fprintf(stderr,"bad frame numbers\n"); + exit(1); + } + + /* open J_Movie */ + inFile = fopen(infilename, "rb"); + if (inFile == NULL) { + perror (infilename); + exit(1); + } + + /* get file descriptor */ + fd = fileno(inFile); + + /* The following lines parse the jpeg_movie header and recover the */ + /* relavant information */ + + fseek(inFile, 8 * sizeof(char), 0); + + if (fread(&ver_no, sizeof(int), 1, inFile) != 1) { + perror("Error in reading version"); + exit(1); + } + if (ver_no != 2) { + perror("Unrecognized version - Quantization tables may be wrong\n"); + } + if (fread(&fps, sizeof(int), 1, inFile) != 1) { + perror("Error in reading fps"); + exit(1); + } + if (fread (&no_frames, sizeof(int), 1, inFile) != 1) { + perror("Error in reading no_frames"); + exit(1); + } + + MALLOCARRAY(inoffsets, no_frames); + + if (fread(&width, sizeof(int), 1, inFile) != 1) { + perror("Error in reading width"); + exit(1); + } + /* set image width in JFIF header */ + inbuffer[27] = (char)(0xFF & (width >> 8)); + inbuffer[28] = (char)(0xFF & width); + + if (fread(&height, sizeof(int), 1, inFile) != 1) { + perror("Error in reading height"); + exit(1); + } + /* set image height in JFIF header */ + inbuffer[25] = (char)(0xFF & (height >> 8)); + inbuffer[26] = (char)(0xFF & height); + + if (fread(&bandwidth, sizeof(int), 1, inFile) != 1) { + perror("Error in reading bandwidth"); + exit(1); + } + + if (fread(&qfactor, sizeof(int), 1, inFile) != 1) { + perror("Error in reading qfactor"); + exit(1); + } + /* The default quality factor = 100, therefore, if + our quality factor does not equal 100 we must + scale the quantization matrices in the JFIF header + */ + /* Note values are clipped to a max of 255 */ + if (qfactor != 100) { + for (Temp = 44; Temp < 108; ++Temp) { + temp= (inbuffer[Temp]*qfactor)/100; + inbuffer[Temp] = (char)((temp<255) ? temp : 255); + } + for (Temp = 109; Temp < 173; ++Temp) { + temp = (inbuffer[Temp]*qfactor)/100; + inbuffer[Temp] = (char)((temp<255) ? temp : 255); + } + } + + if (fread(&mapsize, sizeof(int), 1, inFile) != 1) { + perror("Error in reading mapsize"); + exit(1); + } + if (fread (&image_offset, sizeof(int), 1, inFile) != 1) { + perror("Error in reading image offset"); + exit(1); + } + if (fread (&audio_tracks, sizeof(int), 1, inFile) != 1) { + perror("Error in reading audio tracks"); + exit(1); + } + + fread(junk,sizeof(int),1,inFile); + + if (fread (&audiosize, sizeof(int), 1, inFile) != 1) { + perror("Error in reading audiosize"); + exit(1); + } + + fseek (inFile, image_offset, 0); + + last = MIN(end, no_frames-1); + + for (i = 0; i < no_frames; ++i) { + fread(&(inoffsets[i]), sizeof(int), 1, inFile); + } /* Reads in the frame sizes into the array */ + + rewind(inFile); + + /* Extract JFIF files from J_Movie */ + for (i = start; i <= last; ++i) { + size = inoffsets[i] - inoffsets[i-1]- 5; + lseek(fd, inoffsets[i-1], 0); + read(fd, &(op_code), 1); + while (op_code != 0xffffffec) { + read(fd,junk,audiosize); + read(fd, &(op_code), 1); + size = size - audiosize ; + } /* To skip the audio bytes in each frame */ + read(fd, jpeg_size, 4); + read(fd, &(inbuffer[607]), size); + sprintf(ofname, "%s%d.jpg", obase, i); + outFile = fopen(ofname, "wb"); + fwrite(inbuffer, (size+607), sizeof(char), outFile); + fclose(outFile); + } + free(inoffsets); + fclose(inFile); +} + + + + +/*===========================================================================* + * + * ReadJPEG contributed by James Arthur Boucher of Boston University's + * Multimedia Communications Lab + * + * read a JPEG file and copy data into frame original data arrays + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +/*************************JPEG LIBRARY INTERFACE*********************/ +/* + * THE BIG PICTURE: + * + * The rough outline this JPEG decompression operation is: + * + * allocate and initialize JPEG decompression object + * specify data source (eg, a file) + * jpeg_read_header(); // obtain image dimensions and other parameters + * set parameters for decompression + * jpeg_start_decompress(); + * while (scan lines remain to be read) + * jpeg_read_scanlines(...); + * jpeg_finish_decompress(); + * release JPEG decompression object + * + */ +void +ReadJPEG(MpegFrame * const mf, + FILE * const fp) { + + static struct jpeg_decompress_struct cinfo; + /* The JPEG decompression parameters and pointers to + working data (which is allocated as needed by the JPEG library). + */ + struct jpeg_error_mgr jerr; + JSAMPARRAY scanarray[3]; + int ci,cd,cp; + JDIMENSION ncols[3]; + JDIMENSION nrows[3]; + jpeg_component_info *compptr; + int buffer_height; + int current_row[3]; + uint8 **orig[3]; + int h_samp[3],v_samp[3]; + int max_h_samp,max_v_samp; + int temp_h, temp_v; + int temp; + + /* Allocate and initialize JPEG decompression object */ + cinfo.err = jpeg_std_error(&jerr); + + /* + ** If we're reading from stdin we want to create the cinfo struct + ** ONCE (during the first read). This is because when reading jpeg + ** from stdin we will not release the cinfo struct, because doing + ** so would totally screw up the read buffer and make it impossible + ** to read jpegs from stdin. + ** Dave Scott (dhs), UofO, 7/19/95 + */ + { + static int first_stdin; + first_stdin = TRUE; /* initial value */ + if ((fp != stdin) || first_stdin) { + first_stdin = FALSE; + /* Now we can initialize the JPEG decompression object. */ + jpeg_create_decompress(&cinfo); + /* specify data source (eg, a file) */ + jpeg_stdio_src(&cinfo, fp); + } + } + + /* specify data source (eg, a file) */ + + jpeg_stdio_src(&cinfo, fp); + + /* read file parameters with jpeg_read_header() */ + + + (void) jpeg_read_header(&cinfo, TRUE); + /* We can ignore the return value from jpeg_read_header since + * (a) suspension is not possible with the stdio data source, and + * (b) we passed TRUE to reject a tables-only JPEG file as an error. + */ + + /* set parameters for decompression */ +#ifdef JPEG4 + cinfo.want_raw_output = TRUE; +#else + cinfo.raw_data_out = TRUE; +#endif + cinfo.out_color_space = JCS_YCbCr; + + /* calculate image output dimensions */ + jpeg_calc_output_dimensions(&cinfo); + /* the above calculation will set these soon */ + /* for now we'll set them ourselves */ + + /* tell mpeg_encode the size of the JPEG Image*/ + Fsize_Note(mf->id,(int)(cinfo.image_width),(int)(cinfo.image_height)); + + /* Allocate memory for the raw YCbCr data to occupy*/ + Frame_AllocYCC(mf); /*allocate space for mpeg frame*/ + + /* copy pointers to array structure- this make the following + code more compact + */ + orig[0] = mf->orig_y; + orig[1] = mf->orig_cb; + orig[2] = mf->orig_cr; + + /* Note that we can use the info obtained from jpeg_read_header. + */ + + /* Start decompressor */ + + jpeg_start_decompress(&cinfo); + + + /* JSAMPLEs per row in output buffer */ + /* collect component subsample values*/ + for (cp=0, compptr = cinfo.comp_info; + cp < cinfo.num_components; + cp++, compptr++) { + h_samp[cp] = compptr->h_samp_factor; + v_samp[cp] = compptr->v_samp_factor; + } + /* calculate max subsample values*/ + temp_h = (h_samp[0]<h_samp[1]) ? h_samp[1] : h_samp[0]; + max_h_samp = (temp_h<h_samp[2]) ? h_samp[2]:temp_h; + temp_v = (v_samp[0]<v_samp[1]) ? v_samp[1] : v_samp[0]; + max_v_samp = (temp_v<v_samp[2]) ? v_samp[2]:temp_v; + + /* Make an 8-row-high sample array that will go away when done + with image + */ +#ifdef JPEG4 + buffer_height = 8; /* could be 2, 4,8 rows high */ +#else + buffer_height = cinfo.max_v_samp_factor * cinfo.min_DCT_scaled_size; +#endif + + for(cp=0,compptr = cinfo.comp_info;cp<cinfo.num_components; + cp++,compptr++) { + ncols[cp] = (JDIMENSION)((cinfo.image_width*compptr->h_samp_factor)/ + max_h_samp); + + nrows[cp] = (JDIMENSION)((buffer_height*compptr->v_samp_factor)/ + max_v_samp); + + scanarray[cp] = (*cinfo.mem->alloc_sarray) + ((j_common_ptr) &cinfo, JPOOL_IMAGE, ncols[cp], nrows[cp]); + } + + /* while (scan lines remain to be read) + jpeg_read_scanlines(...); + */ + + /* Here we use the library's state variable cinfo.output_scanline as the + * loop counter, so that we don't have to keep track ourselves. + */ + + while (cinfo.output_scanline < cinfo.output_height) { + +#ifdef JPEG4 + (void) jpeg_read_raw_scanlines(&cinfo, scanarray, buffer_height); +#else + (void) jpeg_read_raw_data(&cinfo, scanarray, buffer_height); +#endif + + /* alter subsample ratio's if neccessary */ + if ((h_samp[0]==2) && (h_samp[1]==1) && (h_samp[2]==1) && + (v_samp[0]==2) && (v_samp[1]==1) && (v_samp[2]==1)) { + /* we are 4:1:1 as expected by the encoder*/ + } else if((h_samp[0] == 2) && (h_samp[1] == 1) && (h_samp[2]==1) && + (v_samp[0] == 1) && (v_samp[1] == 1) && (v_samp[2]==1)) { + /* must subsample 2:1 vertically and adjust params*/ + for (ci = 1; ci < 3; ++ci) { + for (cp = 0; cp < (buffer_height/2); cp = cp+1) { + for (cd = 0; cd < ncols[ci]; ++cd) { + temp = ((scanarray[ci][cp*2][cd] + + scanarray[ci][(cp*2)+1][cd]) / 2); + scanarray[ci][cp][cd] = (JSAMPLE)(temp); + } + } + } + /* only reset values the first time through*/ + if (cinfo.output_scanline == buffer_height) { + nrows[1] = nrows[1]/2; + nrows[2] = nrows[2]/2; + max_v_samp = 2; + v_samp[0] = 2; + } + } else + pm_error("Invalid subsampling ratio"); + + /* transfer data from jpeg buffer to MPEG frame */ + /* calculate the row we wish to output into */ + for (ci = 0, compptr = cinfo.comp_info; + ci < cinfo.num_components; + ++ci, ++compptr) { + current_row[ci] =((cinfo.output_scanline - buffer_height)* + (v_samp[ci])/max_v_samp); + + jcopy_sample_rows(scanarray[ci],0,(JSAMPARRAY)(orig[ci]), + current_row[ci],nrows[ci],ncols[ci]); + } + } + + /* Step 7: Finish decompression */ + + (void) jpeg_finish_decompress(&cinfo); + /* We can ignore the return value since suspension is not possible + * with the stdio data source. + */ + + /* Step 8: Release JPEG decompression object */ + + /* + ** DO NOT release the cinfo struct if we are reading from stdin, this + ** is because the cinfo struct contains the read buffer, and the read + ** buffer may (and almost always does) contain the end of one image and + ** the beginning of another. If we throw away the read buffer then + ** we loose the beginning of the next image, and we're screwed. + ** Dave Scott (dhs), UofO, 7/19/95 + */ + if (fp == stdin) { + static int no_from_stdin = 0; + ++no_from_stdin; + } else { + /* This is an important step since it will release a good deal + of memory. + */ + jpeg_destroy_decompress(&cinfo); + } + + /* After finish_decompress, we can close the input file. Here we + postpone it until after no more JPEG errors are possible, so as + to simplify the setjmp error logic above. (Actually, I don't + think that jpeg_destroy can do an error exit, but why assume + anything...) + */ + + /* At this point you may want to check to see whether any corrupt-data + * warnings occurred (test whether jerr.pub.num_warnings is nonzero). + * If you prefer to treat corrupt data as a fatal error, override the + * error handler's emit_message method to call error_exit on a warning. + */ +} + + + +/* + * SOME FINE POINTS: + * + * In the above loop, we ignored the return value of jpeg_read_scanlines, + * which is the number of scanlines actually read. We could get away with + * this for the same reasons discussed in the compression example. Actually + * there is one perfectly normal situation in which jpeg_read_scanlines may + * return fewer lines than you asked for: at the bottom of the image. But the + * loop above can't ask for more lines than there are in the image since it + * reads only one line at a time. + * + * In some high-speed operating modes, some data copying can be saved by + * making the buffer passed to jpeg_read_scanlines be cinfo.rec_outbuf_height + * lines high (or a multiple thereof). This will usually be 1, 2, or 4 lines. + * + * To decompress multiple images, you can repeat the whole sequence, or you + * can keep the JPEG object around and just repeat steps 2-7. This will + * save a little bit of startup/shutdown time. + * + * As with compression, some operating modes may require temporary files. + * On some systems you may need to set up a signal handler to ensure that + * temporary files are deleted if the program is interrupted. + * + * Scanlines are returned in the same order as they appear in the JPEG file, + * which is standardly top-to-bottom. If you must have data supplied + * bottom-to-top, you can use one of the virtual arrays provided by the + * JPEG memory manager to invert the data. See wrrle.c for an example. + */ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/jrevdct.c b/converter/ppm/ppmtompeg/jrevdct.c new file mode 100644 index 00000000..2e99a67a --- /dev/null +++ b/converter/ppm/ppmtompeg/jrevdct.c @@ -0,0 +1,1278 @@ +/* + * jrevdct.c + * + * Copyright (C) 1991, 1992, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file contains the basic inverse-DCT transformation subroutine. + * + * This implementation is based on an algorithm described in + * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + * The primary algorithm described there uses 11 multiplies and 29 adds. + * We use their alternate method with 12 multiplies and 32 adds. + * The advantage of this method is that no data path contains more than one + * multiplication; this allows a very simple and accurate implementation in + * scaled fixed-point arithmetic, with a minimal number of shifts. + * + * I've made lots of modifications to attempt to take advantage of the + * sparse nature of the DCT matrices we're getting. Although the logic + * is cumbersome, it's straightforward and the resulting code is much + * faster. + * + * A better way to do this would be to pass in the DCT block as a sparse + * matrix, perhaps with the difference cases encoded. + */ + +#include <memory.h> +#include "all.h" +#include "ansi.h" +#include "dct.h" + + +#define CONST_BITS 13 + +/* + * This routine is specialized to the case DCTSIZE = 8. + */ + +#if DCTSIZE != 8 + Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ +#endif + + +/* + * A 2-D IDCT can be done by 1-D IDCT on each row followed by 1-D IDCT + * on each column. Direct algorithms are also available, but they are + * much more complex and seem not to be any faster when reduced to code. + * + * The poop on this scaling stuff is as follows: + * + * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + * larger than the true IDCT outputs. The final outputs are therefore + * a factor of N larger than desired; since N=8 this can be cured by + * a simple right shift at the end of the algorithm. The advantage of + * this arrangement is that we save two multiplications per 1-D IDCT, + * because the y0 and y4 inputs need not be divided by sqrt(N). + * + * We have to do addition and subtraction of the integer inputs, which + * is no problem, and multiplication by fractional constants, which is + * a problem to do in integer arithmetic. We multiply all the constants + * by CONST_SCALE and convert them to integer constants (thus retaining + * CONST_BITS bits of precision in the constants). After doing a + * multiplication we have to divide the product by CONST_SCALE, with proper + * rounding, to produce the correct output. This division can be done + * cheaply as a right shift of CONST_BITS bits. We postpone shifting + * as long as possible so that partial sums can be added together with + * full fractional precision. + * + * The outputs of the first pass are scaled up by PASS1_BITS bits so that + * they are represented to better-than-integral precision. These outputs + * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + * with the recommended scaling. (To scale up 12-bit sample data further, an + * intermediate int32 array would be needed.) + * + * To avoid overflow of the 32-bit intermediate results in pass 2, we must + * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + * shows that the values given below are the most effective. + */ + +#ifdef EIGHT_BIT_SAMPLES +#define PASS1_BITS 2 +#else +#define PASS1_BITS 1 /* lose a little precision to avoid overflow */ +#endif + +#define ONE ((int32) 1) + +#define CONST_SCALE (ONE << CONST_BITS) + +/* Convert a positive real constant to an integer scaled by CONST_SCALE. + * IMPORTANT: if your compiler doesn't do this arithmetic at compile time, + * you will pay a significant penalty in run time. In that case, figure + * the correct integer constant values and insert them by hand. + */ + +/* Actually FIX is no longer used, we precomputed them all */ +#define FIX(x) ((int32) ((x) * CONST_SCALE + 0.5)) + +/* Descale and correctly round an int32 value that's scaled by N bits. + * We assume RIGHT_SHIFT rounds towards minus infinity, so adding + * the fudge factor is correct for either sign of X. + */ + +#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) + +/* Multiply an int32 variable by an int32 constant to yield an int32 result. + * For 8-bit samples with the recommended scaling, all the variable + * and constant values involved are no more than 16 bits wide, so a + * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; + * this provides a useful speedup on many machines. + * There is no way to specify a 16x16->32 multiply in portable C, but + * some C compilers will do the right thing if you provide the correct + * combination of casts. + * NB: for 12-bit samples, a full 32-bit multiplication will be needed. + */ + +#ifdef EIGHT_BIT_SAMPLES +#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ +#define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) +#endif +#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ +#define MULTIPLY(var,const) (((INT16) (var)) * ((int32) (const))) +#endif +#endif + +#ifndef MULTIPLY /* default definition */ +#define MULTIPLY(var,const) ((var) * (const)) +#endif + + +/* + Unlike our decoder where we approximate the FIXes, we need to use exact +ones here or successive P-frames will drift too much with Reference frame coding +*/ +#define FIX_0_211164243 1730 +#define FIX_0_275899380 2260 +#define FIX_0_298631336 2446 +#define FIX_0_390180644 3196 +#define FIX_0_509795579 4176 +#define FIX_0_541196100 4433 +#define FIX_0_601344887 4926 +#define FIX_0_765366865 6270 +#define FIX_0_785694958 6436 +#define FIX_0_899976223 7373 +#define FIX_1_061594337 8697 +#define FIX_1_111140466 9102 +#define FIX_1_175875602 9633 +#define FIX_1_306562965 10703 +#define FIX_1_387039845 11363 +#define FIX_1_451774981 11893 +#define FIX_1_501321110 12299 +#define FIX_1_662939225 13623 +#define FIX_1_847759065 15137 +#define FIX_1_961570560 16069 +#define FIX_2_053119869 16819 +#define FIX_2_172734803 17799 +#define FIX_2_562915447 20995 +#define FIX_3_072711026 25172 + +/* + Switch on reverse_dct choices +*/ +void reference_rev_dct _ANSI_ARGS_((int16 *block)); +void mpeg_jrevdct_quick _ANSI_ARGS_((int16 *block)); +void init_idctref _ANSI_ARGS_((void)); + +extern boolean pureDCT; + +void +mpeg_jrevdct(data) + DCTBLOCK data; +{ + if (pureDCT) reference_rev_dct(data); + else mpeg_jrevdct_quick(data); +} + +/* + * Perform the inverse DCT on one block of coefficients. + */ + +void +mpeg_jrevdct_quick(data) + DCTBLOCK data; +{ + int32 tmp0, tmp1, tmp2, tmp3; + int32 tmp10, tmp11, tmp12, tmp13; + int32 z1, z2, z3, z4, z5; + int32 d0, d1, d2, d3, d4, d5, d6, d7; + register DCTELEM *dataptr; + int rowctr; + SHIFT_TEMPS + + /* Pass 1: process rows. */ + /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ + /* furthermore, we scale the results by 2**PASS1_BITS. */ + + dataptr = data; + + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any row in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * row DCT calculations can be simplified this way. + */ + + register int *idataptr = (int*)dataptr; + d0 = dataptr[0]; + d1 = dataptr[1]; + if ((d1 == 0) && (idataptr[1] | idataptr[2] | idataptr[3]) == 0) { + /* AC terms all zero */ + if (d0) { + /* Compute a 32 bit value to assign. */ + DCTELEM dcval = (DCTELEM) (d0 << PASS1_BITS); + register int v = (dcval & 0xffff) | ((dcval << 16) & 0xffff0000); + + idataptr[0] = v; + idataptr[1] = v; + idataptr[2] = v; + idataptr[3] = v; + } + + dataptr += DCTSIZE; /* advance pointer to next row */ + continue; + } + d2 = dataptr[2]; + d3 = dataptr[3]; + d4 = dataptr[4]; + d5 = dataptr[5]; + d6 = dataptr[6]; + d7 = dataptr[7]; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ +{ + if (d6) { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } + } + } else { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = d4 << CONST_BITS; + tmp11 = tmp12 = -tmp10; + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = 0; + } + } + } + } + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + + if (d7) { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5 + d3; + z3 = d7 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ + z2 = d5 + d3; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d5, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d5, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 = z1 + z4; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z4 = d5 + d1; + z5 = MULTIPLY(d7 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z3 = MULTIPLY(-d7, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 = z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z5 = MULTIPLY(d5 + d7, FIX_1_175875602); + + z3 += z5; + z4 += z5; + + tmp0 += z3; + tmp1 += z4; + tmp2 = z2 + z3; + tmp3 = z1 + z4; + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d1, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d1, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 = z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ + z3 = d7 + d3; + + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + tmp2 = MULTIPLY(d3, FIX_0_509795579); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z5 = MULTIPLY(z3, FIX_1_175875602); + z3 = MULTIPLY(-z3, FIX_0_785694958); + + tmp0 += z3; + tmp1 = z2 + z5; + tmp2 += z3; + tmp3 = z1 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z5 = MULTIPLY(z1, FIX_1_175875602); + + z1 = MULTIPLY(z1, FIX_0_275899380); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp0 = MULTIPLY(-d7, FIX_1_662939225); + z4 = MULTIPLY(-d1, FIX_0_390180644); + tmp3 = MULTIPLY(d1, FIX_1_111140466); + + tmp0 += z1; + tmp1 = z4 + z5; + tmp2 = z3 + z5; + tmp3 += z1; + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_1_387039845); + tmp1 = MULTIPLY(d7, FIX_1_175875602); + tmp2 = MULTIPLY(-d7, FIX_0_785694958); + tmp3 = MULTIPLY(d7, FIX_0_275899380); + } + } + } + } else { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(d3 + z4, FIX_1_175875602); + + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-d1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-d3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 = z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + + z5 = MULTIPLY(z2, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_1_662939225); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z2 = MULTIPLY(-z2, FIX_1_387039845); + tmp2 = MULTIPLY(d3, FIX_1_111140466); + z3 = MULTIPLY(-d3, FIX_1_961570560); + + tmp0 = z3 + z5; + tmp1 += z2; + tmp2 += z2; + tmp3 = z4 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ + z4 = d5 + d1; + + z5 = MULTIPLY(z4, FIX_1_175875602); + z1 = MULTIPLY(-d1, FIX_0_899976223); + tmp3 = MULTIPLY(d1, FIX_0_601344887); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(z4, FIX_0_785694958); + + tmp0 = z1 + z5; + tmp1 += z4; + tmp2 = z2 + z5; + tmp3 += z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ + tmp0 = MULTIPLY(d5, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_0_275899380); + tmp2 = MULTIPLY(-d5, FIX_1_387039845); + tmp3 = MULTIPLY(d5, FIX_0_785694958); + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ + z5 = d1 + d3; + tmp3 = MULTIPLY(d1, FIX_0_211164243); + tmp2 = MULTIPLY(-d3, FIX_1_451774981); + z1 = MULTIPLY(d1, FIX_1_061594337); + z2 = MULTIPLY(-d3, FIX_2_172734803); + z4 = MULTIPLY(z5, FIX_0_785694958); + z5 = MULTIPLY(z5, FIX_1_175875602); + + tmp0 = z1 - z4; + tmp1 = z2 + z4; + tmp2 += z5; + tmp3 += z5; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(-d3, FIX_0_785694958); + tmp1 = MULTIPLY(-d3, FIX_1_387039845); + tmp2 = MULTIPLY(-d3, FIX_0_275899380); + tmp3 = MULTIPLY(d3, FIX_1_175875602); + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(d1, FIX_0_275899380); + tmp1 = MULTIPLY(d1, FIX_0_785694958); + tmp2 = MULTIPLY(d1, FIX_1_175875602); + tmp3 = MULTIPLY(d1, FIX_1_387039845); + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = tmp1 = tmp2 = tmp3 = 0; + } + } + } + } +} + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[0] = (DCTELEM) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); + dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); + dataptr[2] = (DCTELEM) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); + dataptr[4] = (DCTELEM) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + dataptr = data; + for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { + /* Columns of zeroes can be exploited in the same way as we did with rows. + * However, the row calculation has created many nonzero AC terms, so the + * simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + + d0 = dataptr[DCTSIZE*0]; + d1 = dataptr[DCTSIZE*1]; + d2 = dataptr[DCTSIZE*2]; + d3 = dataptr[DCTSIZE*3]; + d4 = dataptr[DCTSIZE*4]; + d5 = dataptr[DCTSIZE*5]; + d6 = dataptr[DCTSIZE*6]; + d7 = dataptr[DCTSIZE*7]; + + /* Even part: reverse the even part of the forward DCT. */ + /* The rotator is sqrt(2)*c(-6). */ + if (d6) { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 != 0 */ + z1 = MULTIPLY(d2 + d6, FIX_0_541196100); + tmp2 = z1 + MULTIPLY(-d6, FIX_1_847759065); + tmp3 = z1 + MULTIPLY(d2, FIX_0_765366865); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 != 0 */ + tmp2 = MULTIPLY(-d6, FIX_1_306562965); + tmp3 = MULTIPLY(d6, FIX_0_541196100); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } + } + } else { + if (d4) { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = (d0 + d4) << CONST_BITS; + tmp1 = (d0 - d4) << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 != 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d4 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp2 - tmp0; + tmp12 = -(tmp0 + tmp2); + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = (d0 + d4) << CONST_BITS; + tmp11 = tmp12 = (d0 - d4) << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 != 0, d6 == 0 */ + tmp10 = tmp13 = d4 << CONST_BITS; + tmp11 = tmp12 = -tmp10; + } + } + } else { + if (d2) { + if (d0) { + /* d0 != 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp0 = d0 << CONST_BITS; + + tmp10 = tmp0 + tmp3; + tmp13 = tmp0 - tmp3; + tmp11 = tmp0 + tmp2; + tmp12 = tmp0 - tmp2; + } else { + /* d0 == 0, d2 != 0, d4 == 0, d6 == 0 */ + tmp2 = MULTIPLY(d2, FIX_0_541196100); + tmp3 = MULTIPLY(d2, FIX_1_306562965); + + tmp10 = tmp3; + tmp13 = -tmp3; + tmp11 = tmp2; + tmp12 = -tmp2; + } + } else { + if (d0) { + /* d0 != 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = d0 << CONST_BITS; + } else { + /* d0 == 0, d2 == 0, d4 == 0, d6 == 0 */ + tmp10 = tmp13 = tmp11 = tmp12 = 0; + } + } + } + } + + /* Odd part per figure 8; the matrix is unitary and hence its + * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. + */ + if (d7) { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5 + d3; + z3 = d7 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 != 0 */ + z1 = d7; + z2 = d5 + d3; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d5, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d5, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 = z1 + z4; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 != 0 */ + z1 = d7 + d1; + z2 = d5; + z3 = d7; + z4 = d5 + d1; + z5 = MULTIPLY(z3 + z4, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z3 = MULTIPLY(-d7, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 += z2 + z4; + tmp2 = z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z5 = MULTIPLY(d5 + d7, FIX_1_175875602); + + z3 += z5; + z4 += z5; + + tmp0 += z3; + tmp1 += z4; + tmp2 = z2 + z3; + tmp3 = z1 + z4; + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z3 = d7 + d3; + z5 = MULTIPLY(z3 + d1, FIX_1_175875602); + + tmp0 = MULTIPLY(d7, FIX_0_298631336); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-z1, FIX_0_899976223); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z3 = MULTIPLY(-z3, FIX_1_961570560); + z4 = MULTIPLY(-d1, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 += z1 + z3; + tmp1 = z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 != 0 */ + z3 = d7 + d3; + + tmp0 = MULTIPLY(-d7, FIX_0_601344887); + z1 = MULTIPLY(-d7, FIX_0_899976223); + tmp2 = MULTIPLY(d3, FIX_0_509795579); + z2 = MULTIPLY(-d3, FIX_2_562915447); + z5 = MULTIPLY(z3, FIX_1_175875602); + z3 = MULTIPLY(-z3, FIX_0_785694958); + + tmp0 += z3; + tmp1 = z2 + z5; + tmp2 += z3; + tmp3 = z1 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 != 0 */ + z1 = d7 + d1; + z5 = MULTIPLY(z1, FIX_1_175875602); + + z1 = MULTIPLY(z1, FIX_0_275899380); + z3 = MULTIPLY(-d7, FIX_1_961570560); + tmp0 = MULTIPLY(-d7, FIX_1_662939225); + z4 = MULTIPLY(-d1, FIX_0_390180644); + tmp3 = MULTIPLY(d1, FIX_1_111140466); + + tmp0 += z1; + tmp1 = z4 + z5; + tmp2 = z3 + z5; + tmp3 += z1; + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 != 0 */ + tmp0 = MULTIPLY(-d7, FIX_1_387039845); + tmp1 = MULTIPLY(d7, FIX_1_175875602); + tmp2 = MULTIPLY(-d7, FIX_0_785694958); + tmp3 = MULTIPLY(d7, FIX_0_275899380); + } + } + } + } else { + if (d5) { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + z4 = d5 + d1; + z5 = MULTIPLY(d3 + z4, FIX_1_175875602); + + tmp1 = MULTIPLY(d5, FIX_2_053119869); + tmp2 = MULTIPLY(d3, FIX_3_072711026); + tmp3 = MULTIPLY(d1, FIX_1_501321110); + z1 = MULTIPLY(-d1, FIX_0_899976223); + z2 = MULTIPLY(-z2, FIX_2_562915447); + z3 = MULTIPLY(-d3, FIX_1_961570560); + z4 = MULTIPLY(-z4, FIX_0_390180644); + + z3 += z5; + z4 += z5; + + tmp0 = z1 + z3; + tmp1 += z2 + z4; + tmp2 += z2 + z3; + tmp3 += z1 + z4; + } else { + /* d1 == 0, d3 != 0, d5 != 0, d7 == 0 */ + z2 = d5 + d3; + + z5 = MULTIPLY(z2, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_1_662939225); + z4 = MULTIPLY(-d5, FIX_0_390180644); + z2 = MULTIPLY(-z2, FIX_1_387039845); + tmp2 = MULTIPLY(d3, FIX_1_111140466); + z3 = MULTIPLY(-d3, FIX_1_961570560); + + tmp0 = z3 + z5; + tmp1 += z2; + tmp2 += z2; + tmp3 = z4 + z5; + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 != 0, d7 == 0 */ + z4 = d5 + d1; + + z5 = MULTIPLY(z4, FIX_1_175875602); + z1 = MULTIPLY(-d1, FIX_0_899976223); + tmp3 = MULTIPLY(d1, FIX_0_601344887); + tmp1 = MULTIPLY(-d5, FIX_0_509795579); + z2 = MULTIPLY(-d5, FIX_2_562915447); + z4 = MULTIPLY(z4, FIX_0_785694958); + + tmp0 = z1 + z5; + tmp1 += z4; + tmp2 = z2 + z5; + tmp3 += z4; + } else { + /* d1 == 0, d3 == 0, d5 != 0, d7 == 0 */ + tmp0 = MULTIPLY(d5, FIX_1_175875602); + tmp1 = MULTIPLY(d5, FIX_0_275899380); + tmp2 = MULTIPLY(-d5, FIX_1_387039845); + tmp3 = MULTIPLY(d5, FIX_0_785694958); + } + } + } else { + if (d3) { + if (d1) { + /* d1 != 0, d3 != 0, d5 == 0, d7 == 0 */ + z5 = d1 + d3; + tmp3 = MULTIPLY(d1, FIX_0_211164243); + tmp2 = MULTIPLY(-d3, FIX_1_451774981); + z1 = MULTIPLY(d1, FIX_1_061594337); + z2 = MULTIPLY(-d3, FIX_2_172734803); + z4 = MULTIPLY(z5, FIX_0_785694958); + z5 = MULTIPLY(z5, FIX_1_175875602); + + tmp0 = z1 - z4; + tmp1 = z2 + z4; + tmp2 += z5; + tmp3 += z5; + } else { + /* d1 == 0, d3 != 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(-d3, FIX_0_785694958); + tmp1 = MULTIPLY(-d3, FIX_1_387039845); + tmp2 = MULTIPLY(-d3, FIX_0_275899380); + tmp3 = MULTIPLY(d3, FIX_1_175875602); + } + } else { + if (d1) { + /* d1 != 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = MULTIPLY(d1, FIX_0_275899380); + tmp1 = MULTIPLY(d1, FIX_0_785694958); + tmp2 = MULTIPLY(d1, FIX_1_175875602); + tmp3 = MULTIPLY(d1, FIX_1_387039845); + } else { + /* d1 == 0, d3 == 0, d5 == 0, d7 == 0 */ + tmp0 = tmp1 = tmp2 = tmp3 = 0; + } + } + } + } + + /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ + + dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3); + dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3); + + dataptr++; /* advance pointer to next column */ + } +} + + +/* here is the reference one, in case of problems with the normal one */ + +/* idctref.c, Inverse Discrete Fourier Transform, double precision */ + +/* Copyright (C) 1994, 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. + * + */ + +/* Perform IEEE 1180 reference (64-bit floating point, separable 8x1 + * direct matrix multiply) Inverse Discrete Cosine Transform +*/ + + +/* Here we use math.h to generate constants. Compiler results may + vary a little */ + +#ifndef PI +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 +#endif +#endif + +/* cosine transform matrix for 8x1 IDCT */ +static double itrans_coef[8][8]; + +/* initialize DCT coefficient matrix */ + +void init_idctref() +{ + int freq, time; + double scale; + + for (freq=0; freq < 8; freq++) + { + scale = (freq == 0) ? sqrt(0.125) : 0.5; + for (time=0; time<8; time++) + itrans_coef[freq][time] = scale*cos((PI/8.0)*freq*(time + 0.5)); + } +} + +/* perform IDCT matrix multiply for 8x8 coefficient block */ + +void reference_rev_dct(block) +int16 *block; +{ + int i, j, k, v; + double partial_product; + double tmp[64]; + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + partial_product = 0.0; + + for (k=0; k<8; k++) + partial_product+= itrans_coef[k][j]*block[8*i+k]; + + tmp[8*i+j] = partial_product; + } + + /* Transpose operation is integrated into address mapping by switching + loop order of i and j */ + + for (j=0; j<8; j++) + for (i=0; i<8; i++) + { + partial_product = 0.0; + + for (k=0; k<8; k++) + partial_product+= itrans_coef[k][i]*tmp[8*k+j]; + + v = floor(partial_product+0.5); + block[8*i+j] = (v<-256) ? -256 : ((v>255) ? 255 : v); + } +} diff --git a/converter/ppm/ppmtompeg/memory.c b/converter/ppm/ppmtompeg/memory.c new file mode 100644 index 00000000..f117994a --- /dev/null +++ b/converter/ppm/ppmtompeg/memory.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/memory.c,v 1.3 1995/01/19 23:08:43 eyhung Exp $ + * $Log: memory.c,v $ + * Revision 1.3 1995/01/19 23:08:43 eyhung + * Changed copyrights + * + * Revision 1.2 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/04/27 21:32:26 keving + * nothing + * + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include "memory.h" + + +/* memory handling routines + * + */ + +long totalMemory = 0; +long maxMemory = 0; + + +char *MemAlloc(size_t size) +{ + totalMemory += (long)size; + if ( totalMemory > maxMemory ) + { + maxMemory = totalMemory; + } + + return malloc(size); +} + +void MemFree(char *ptr, long bytes) +{ + totalMemory -= bytes; + free(ptr); +} + +void PrintMaxMemory(void) +{ + fprintf(stdout, "MMMMM-----MAX MEMORY-----MMMMM = %ld\n", maxMemory); +} diff --git a/converter/ppm/ppmtompeg/mfwddct.c b/converter/ppm/ppmtompeg/mfwddct.c new file mode 100644 index 00000000..4643bf25 --- /dev/null +++ b/converter/ppm/ppmtompeg/mfwddct.c @@ -0,0 +1,393 @@ + +/* + * mfwddct.c (derived from jfwddct.c, which carries the following info) + * + * Copyright (C) 1991, 1992, Thomas G. Lane. This file is part of the + * Independent JPEG Group's software. For conditions of distribution and use, + * see the accompanying README file. + * + * This file contains the basic DCT (Discrete Cosine Transform) transformation + * subroutine. + * + * This implementation is based on Appendix A.2 of the book "Discrete Cosine + * Transform---Algorithms, Advantages, Applications" by K.R. Rao and P. Yip + * (Academic Press, Inc, London, 1990). It uses scaled fixed-point arithmetic + * instead of floating point. + */ + +#include "all.h" + +#include "dct.h" +#include "mtypes.h" +#include "opts.h" + +/* + * The poop on this scaling stuff is as follows: + * + * We have to do addition and subtraction of the integer inputs, which is no + * problem, and multiplication by fractional constants, which is a problem to + * do in integer arithmetic. We multiply all the constants by DCT_SCALE and + * convert them to integer constants (thus retaining LG2_DCT_SCALE bits of + * precision in the constants). After doing a multiplication we have to + * divide the product by DCT_SCALE, with proper rounding, to produce the + * correct output. The division can be implemented cheaply as a right shift + * of LG2_DCT_SCALE bits. The DCT equations also specify an additional + * division by 2 on the final outputs; this can be folded into the + * right-shift by shifting one more bit (see UNFIXH). + * + * If you are planning to recode this in assembler, you might want to set + * LG2_DCT_SCALE to 15. This loses a bit of precision, but then all the + * multiplications are between 16-bit quantities (given 8-bit JSAMPLEs!) so + * you could use a signed 16x16=>32 bit multiply instruction instead of full + * 32x32 multiply. Unfortunately there's no way to describe such a multiply + * portably in C, so we've gone for the extra bit of accuracy here. + */ + +#define EIGHT_BIT_SAMPLES +#ifdef EIGHT_BIT_SAMPLES +#define LG2_DCT_SCALE 16 +#else +#define LG2_DCT_SCALE 15 /* lose a little precision to avoid overflow */ +#endif + +#define ONE ((int32) 1) + +#define DCT_SCALE (ONE << LG2_DCT_SCALE) + +/* In some places we shift the inputs left by a couple more bits, */ +/* so that they can be added to fractional results without too much */ +/* loss of precision. */ +#define LG2_OVERSCALE 2 +#define OVERSCALE (ONE << LG2_OVERSCALE) +#define OVERSHIFT(x) ((x) <<= LG2_OVERSCALE) + +/* Scale a fractional constant by DCT_SCALE */ +#define FIX(x) ((int32) ((x) * DCT_SCALE + 0.5)) + +/* Scale a fractional constant by DCT_SCALE/OVERSCALE */ +/* Such a constant can be multiplied with an overscaled input */ +/* to produce something that's scaled by DCT_SCALE */ +#define FIXO(x) ((int32) ((x) * DCT_SCALE / OVERSCALE + 0.5)) + +/* Descale and correctly round a value that's scaled by DCT_SCALE */ +#define UNFIX(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1)), LG2_DCT_SCALE) + +/* Same with an additional division by 2, ie, correctly rounded UNFIX(x/2) */ +#define UNFIXH(x) RIGHT_SHIFT((x) + (ONE << LG2_DCT_SCALE), LG2_DCT_SCALE+1) + +/* Take a value scaled by DCT_SCALE and round to integer scaled by OVERSCALE */ +#define UNFIXO(x) RIGHT_SHIFT((x) + (ONE << (LG2_DCT_SCALE-1-LG2_OVERSCALE)),\ + LG2_DCT_SCALE-LG2_OVERSCALE) + +/* Here are the constants we need */ +/* SIN_i_j is sine of i*pi/j, scaled by DCT_SCALE */ +/* COS_i_j is cosine of i*pi/j, scaled by DCT_SCALE */ + +#define SIN_1_4 FIX(0.707106781) +#define COS_1_4 SIN_1_4 + +#define SIN_1_8 FIX(0.382683432) +#define COS_1_8 FIX(0.923879533) +#define SIN_3_8 COS_1_8 +#define COS_3_8 SIN_1_8 + +#define SIN_1_16 FIX(0.195090322) +#define COS_1_16 FIX(0.980785280) +#define SIN_7_16 COS_1_16 +#define COS_7_16 SIN_1_16 + +#define SIN_3_16 FIX(0.555570233) +#define COS_3_16 FIX(0.831469612) +#define SIN_5_16 COS_3_16 +#define COS_5_16 SIN_3_16 + +/* OSIN_i_j is sine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */ +/* OCOS_i_j is cosine of i*pi/j, scaled by DCT_SCALE/OVERSCALE */ + +#define OSIN_1_4 FIXO(0.707106781) +#define OCOS_1_4 OSIN_1_4 + +#define OSIN_1_8 FIXO(0.382683432) +#define OCOS_1_8 FIXO(0.923879533) +#define OSIN_3_8 OCOS_1_8 +#define OCOS_3_8 OSIN_1_8 + +#define OSIN_1_16 FIXO(0.195090322) +#define OCOS_1_16 FIXO(0.980785280) +#define OSIN_7_16 OCOS_1_16 +#define OCOS_7_16 OSIN_1_16 + +#define OSIN_3_16 FIXO(0.555570233) +#define OCOS_3_16 FIXO(0.831469612) +#define OSIN_5_16 OCOS_3_16 +#define OCOS_5_16 OSIN_3_16 + +/* Prototypes */ +void reference_fwd_dct _ANSI_ARGS_((Block block, Block dest)); +void mp_fwd_dct_fast _ANSI_ARGS_((Block data2d, Block dest2d)); +void init_fdct _ANSI_ARGS_((void)); + +/* + * -------------------------------------------------------------- + * + * mp_fwd_dct_block2 -- + * + * Select the appropriate mp_fwd_dct routine + * + * Results: None + * + * Side effects: None + * + * -------------------------------------------------------------- + */ +extern boolean pureDCT; +void +mp_fwd_dct_block2(data, dest) + Block data, dest; +{ + if (pureDCT) reference_fwd_dct(data, dest); + else mp_fwd_dct_fast(data, dest); +} + +/* + * -------------------------------------------------------------- + * + * mp_fwd_dct_fast -- + * + * Perform the forward DCT on one block of samples. + * + * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT on each + * column. + * + * Results: None + * + * Side effects: Overwrites the input data + * + * -------------------------------------------------------------- + */ + +void +mp_fwd_dct_fast(data2d, dest2d) + Block data2d, dest2d; +{ + int16 *data = (int16 *) data2d; /* this algorithm wants + * a 1-d array */ + int16 *dest = (int16 *) dest2d; + int pass, rowctr; + register int16 *inptr, *outptr; + int16 workspace[DCTSIZE_SQ]; + SHIFT_TEMPS + +#ifdef ndef + { + int y; + + printf("fwd_dct (beforehand):\n"); + for (y = 0; y < 8; y++) + printf("%4d %4d %4d %4d %4d %4d %4d %4d\n", + data2d[y][0], data2d[y][1], + data2d[y][2], data2d[y][3], + data2d[y][4], data2d[y][5], + data2d[y][6], data2d[y][7]); + } +#endif + + /* + * Each iteration of the inner loop performs one 8-point 1-D DCT. It + * reads from a *row* of the input matrix and stores into a *column* + * of the output matrix. In the first pass, we read from the data[] + * array and store into the local workspace[]. In the second pass, + * we read from the workspace[] array and store into data[], thus + * performing the equivalent of a columnar DCT pass with no variable + * array indexing. + */ + + inptr = data; /* initialize pointers for first pass */ + outptr = workspace; + for (pass = 1; pass >= 0; pass--) { + for (rowctr = DCTSIZE - 1; rowctr >= 0; rowctr--) { + /* + * many tmps have nonoverlapping lifetime -- flashy + * register colorers should be able to do this lot + * very well + */ + int32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + int32 tmp10, tmp11, tmp12, tmp13; + int32 tmp14, tmp15, tmp16, tmp17; + int32 tmp25, tmp26; + /* SHIFT_TEMPS */ + + /* temp0 through tmp7: -512 to +512 */ + /* if I-block, then -256 to +256 */ + tmp0 = inptr[7] + inptr[0]; + tmp1 = inptr[6] + inptr[1]; + tmp2 = inptr[5] + inptr[2]; + tmp3 = inptr[4] + inptr[3]; + tmp4 = inptr[3] - inptr[4]; + tmp5 = inptr[2] - inptr[5]; + tmp6 = inptr[1] - inptr[6]; + tmp7 = inptr[0] - inptr[7]; + + /* tmp10 through tmp13: -1024 to +1024 */ + /* if I-block, then -512 to +512 */ + tmp10 = tmp3 + tmp0; + tmp11 = tmp2 + tmp1; + tmp12 = tmp1 - tmp2; + tmp13 = tmp0 - tmp3; + + outptr[0] = (int16) UNFIXH((tmp10 + tmp11) * SIN_1_4); + outptr[DCTSIZE * 4] = (int16) UNFIXH((tmp10 - tmp11) * COS_1_4); + + outptr[DCTSIZE * 2] = (int16) UNFIXH(tmp13 * COS_1_8 + tmp12 * SIN_1_8); + outptr[DCTSIZE * 6] = (int16) UNFIXH(tmp13 * SIN_1_8 - tmp12 * COS_1_8); + + tmp16 = UNFIXO((tmp6 + tmp5) * SIN_1_4); + tmp15 = UNFIXO((tmp6 - tmp5) * COS_1_4); + + OVERSHIFT(tmp4); + OVERSHIFT(tmp7); + + /* + * tmp4, tmp7, tmp15, tmp16 are overscaled by + * OVERSCALE + */ + + tmp14 = tmp4 + tmp15; + tmp25 = tmp4 - tmp15; + tmp26 = tmp7 - tmp16; + tmp17 = tmp7 + tmp16; + + outptr[DCTSIZE] = (int16) UNFIXH(tmp17 * OCOS_1_16 + tmp14 * OSIN_1_16); + outptr[DCTSIZE * 7] = (int16) UNFIXH(tmp17 * OCOS_7_16 - tmp14 * OSIN_7_16); + outptr[DCTSIZE * 5] = (int16) UNFIXH(tmp26 * OCOS_5_16 + tmp25 * OSIN_5_16); + outptr[DCTSIZE * 3] = (int16) UNFIXH(tmp26 * OCOS_3_16 - tmp25 * OSIN_3_16); + + inptr += DCTSIZE; /* advance inptr to next row */ + outptr++; /* advance outptr to next column */ + } + /* end of pass; in case it was pass 1, set up for pass 2 */ + inptr = workspace; + outptr = dest; + } +#ifdef ndef + { + int y; + + printf("fwd_dct (afterward):\n"); + for (y = 0; y < 8; y++) + printf("%4d %4d %4d %4d %4d %4d %4d %4d\n", + dest2d[y][0], dest2d[y][1], + dest2d[y][2], dest2d[y][3], + dest2d[y][4], dest2d[y][5], + dest2d[y][6], dest2d[y][7]); + } +#endif +} + + +/* Modifies from the MPEG2 verification coder */ +/* fdctref.c, forward discrete cosine transform, double precision */ + +/* Copyright (C) 1994, 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. + * + */ + +#ifndef PI +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 +#endif +#endif + +/* private data */ +static double trans_coef[8][8]; /* transform coefficients */ + +void init_fdct() +{ + int i, j; + double s; + + for (i=0; i<8; i++) + { + s = (i==0) ? sqrt(0.125) : 0.5; + + for (j=0; j<8; j++) + trans_coef[i][j] = s * cos((PI/8.0)*i*(j+0.5)); + } +} + +void reference_fwd_dct(block, dest) +Block block, dest; +{ + int i, j, k; + double s; + double tmp[64]; + + if (DoLaplace) { + LaplaceNum++; + } + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + s = 0.0; + + for (k=0; k<8; k++) + s += trans_coef[j][k] * block[i][k]; + + tmp[8*i+j] = s; + } + + for (i=0; i<8; i++) + for (j=0; j<8; j++) + { + s = 0.0; + + for (k=0; k<8; k++) + s += trans_coef[i][k] * tmp[8*k+j]; + + if (collect_quant) { + fprintf(collect_quant_fp, "%d %f\n", 8*i+j, s); + } + if (DoLaplace) { + L1[LaplaceCnum][i*8+j] += s*s; + L2[LaplaceCnum][i*8+j] += s; + } + + + dest[i][j] = (int)floor(s+0.499999); + /* + * reason for adding 0.499999 instead of 0.5: + * s is quite often x.5 (at least for i and/or j = 0 or 4) + * and setting the rounding threshold exactly to 0.5 leads to an + * extremely high arithmetic implementation dependency of the result; + * s being between x.5 and x.500001 (which is now incorrectly rounded + * downwards instead of upwards) is assumed to occur less often + * (if at all) + */ + } +} diff --git a/converter/ppm/ppmtompeg/mheaders.c b/converter/ppm/ppmtompeg/mheaders.c new file mode 100644 index 00000000..2a5f2c63 --- /dev/null +++ b/converter/ppm/ppmtompeg/mheaders.c @@ -0,0 +1,1192 @@ +/*===========================================================================* + * mheaders.c * + * * + * Procedures to generate MPEG headers * + * * + * EXPORTED PROCEDURES: * + * Mhead_GenPictureHeader * + * Mhead_GenSequenceHeader * + * Mhead_GenSequenceEnder * + * Mhead_GenGOPHeader * + * Mhead_GenSliceHeader * + * Mhead_GenSliceEnder * + * Mhead_GenMBHeader * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/mheaders.c,v 1.15 1995/08/07 21:45:19 smoot Exp $ + * $Log: mheaders.c,v $ + * Revision 1.15 1995/08/07 21:45:19 smoot + * check for illegal MVs (shouldnt ever be called, but....) + * fix bug which made us not weite Iframe Qscale changes + * warns if writing a size=0 mpeg + * + * Revision 1.14 1995/05/22 20:53:35 smoot + * corrected bit_rate value in constrained params flag + * + * Revision 1.13 1995/05/02 01:50:38 eyhung + * made VidRateNum un-static + * + * Revision 1.12 1995/03/27 19:28:23 smoot + * auto-determines Qscale changes (was mb_quant) + * + * Revision 1.11 1995/02/16 09:12:39 eyhung + * fixed compile bug with HP7xx + * + * Revision 1.10 1995/01/25 22:53:50 smoot + * Better buf_size checking, and actually check constrained params + * + * Revision 1.9 1995/01/19 23:08:47 eyhung + * Changed copyrights + * + * Revision 1.8 1995/01/16 08:45:10 eyhung + * BLEAH'ed hsize and vsize + * + * Revision 1.7 1994/12/09 22:27:17 smoot + * Fixed buffer size in stream + * + * Revision 1.6 1994/11/12 02:11:54 keving + * nothing + * + * Revision 1.5 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.4 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.3 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.2 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.1 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.6 1993/03/01 23:03:40 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "bitio.h" +#include "frames.h" +#include "mheaders.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int gopStartFrame = 0; +static int lastGOPStart = 0; +static int lastQSSet; + +static uint32 mbAddrIncrTable[][2] = { + {0x0, 0}, + {0x1, 1}, + {0x3, 3}, + {0x2, 3}, + {0x3, 4}, + {0x2, 4}, + {0x3, 5}, + {0x2, 5}, + {0x7, 7}, + {0x6, 7}, + {0xb, 8}, + {0xa, 8}, + {0x9, 8}, + {0x8, 8}, + {0x7, 8}, + {0x6, 8}, + {0x17, 10}, + {0x16, 10}, + {0x15, 10}, + {0x14, 10}, + {0x13, 10}, + {0x12, 10}, + {0x23, 11}, + {0x22, 11}, + {0x21, 11}, + {0x20, 11}, + {0x1f, 11}, + {0x1e, 11}, + {0x1d, 11}, + {0x1c, 11}, + {0x1b, 11}, + {0x1a, 11}, + {0x19, 11}, + {0x18, 11}}; + +static uint32 mbMotionVectorTable[][2] = { + {0x19, 11}, + {0x1b, 11}, + {0x1d, 11}, + {0x1f, 11}, + {0x21, 11}, + {0x23, 11}, + {0x13, 10}, + {0x15, 10}, + {0x17, 10}, + {0x7, 8}, + {0x9, 8}, + {0xb, 8}, + {0x7, 7}, + {0x3, 5}, + {0x3, 4}, + {0x3, 3}, + {0x1, 1}, + {0x2, 3}, + {0x2, 4}, + {0x2, 5}, + {0x6, 7}, + {0xa, 8}, + {0x8, 8}, + {0x6, 8}, + {0x16, 10}, + {0x14, 10}, + {0x12, 10}, + {0x22, 11}, + {0x20, 11}, + {0x1e, 11}, + {0x1c, 11}, + {0x1a, 11}, + {0x18, 11}}; + +static uint32 mbPatTable[][2] = { + {0x0, 0}, + {0xb, 5}, + {0x9, 5}, + {0xd, 6}, + {0xd, 4}, + {0x17, 7}, + {0x13, 7}, + {0x1f, 8}, + {0xc, 4}, + {0x16, 7}, + {0x12, 7}, + {0x1e, 8}, + {0x13, 5}, + {0x1b, 8}, + {0x17, 8}, + {0x13, 8}, + {0xb, 4}, + {0x15, 7}, + {0x11, 7}, + {0x1d, 8}, + {0x11, 5}, + {0x19, 8}, + {0x15, 8}, + {0x11, 8}, + {0xf, 6}, + {0xf, 8}, + {0xd, 8}, + {0x3, 9}, + {0xf, 5}, + {0xb, 8}, + {0x7, 8}, + {0x7, 9}, + {0xa, 4}, + {0x14, 7}, + {0x10, 7}, + {0x1c, 8}, + {0xe, 6}, + {0xe, 8}, + {0xc, 8}, + {0x2, 9}, + {0x10, 5}, + {0x18, 8}, + {0x14, 8}, + {0x10, 8}, + {0xe, 5}, + {0xa, 8}, + {0x6, 8}, + {0x6, 9}, + {0x12, 5}, + {0x1a, 8}, + {0x16, 8}, + {0x12, 8}, + {0xd, 5}, + {0x9, 8}, + {0x5, 8}, + {0x5, 9}, + {0xc, 5}, + {0x8, 8}, + {0x4, 8}, + {0x4, 9}, + {0x7, 3}, + {0xa, 5}, /* grrr... 61, 62, 63 added - Kevin */ + {0x8, 5}, + {0xc, 6} +}; + +/*===========* + * CONSTANTS * + *===========*/ + +#define SEQ_HEAD_CODE 0x000001b3 +#define EXT_START_CODE 0x000001b5 +#define USER_START_CODE 0x000001b2 +#define GOP_START_CODE 0x000001b8 +#define PICT_START_CODE 0x00000100 +#define SLICE_BASE_CODE 0x00000100 + +#define SEQ_END_CODE 0x000001b7 + +/* not static anymore because information is used for computing frame rate + * and for statistics */ +const double VidRateNum[9]={1.0, 23.976, 24.0, 25.0, 29.97, 30.0, + 50.0 ,59.94, 60.0}; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void GenMBAddrIncr _ANSI_ARGS_((BitBucket *bb, uint32 addr_incr)); +static void GenPictHead _ANSI_ARGS_((BitBucket *bb, uint32 temp_ref, + uint32 code_type, uint32 vbv_delay, + int32 full_pel_forw_flag, uint32 forw_f_code, + int32 full_pel_back_flag, uint32 back_f_code, + uint8 *extra_info, uint32 extra_info_size, + uint8 *ext_data, uint32 ext_data_size, + uint8 *user_data, uint32 user_data_size)); +static void GenMBType _ANSI_ARGS_((BitBucket *bb, uint32 pict_code_type, + uint32 mb_quant, uint32 motion_forw, uint32 motion_back, + uint32 mb_pattern, uint32 mb_intra)); +static void GenMotionCode _ANSI_ARGS_((BitBucket *bb, int32 vector)); +static void GenBlockPattern _ANSI_ARGS_((BitBucket *bb, + uint32 mb_pattern)); + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +/*===========================================================================* + * + * SetGOPStartTime + * + * sets the start frame of the GOP; to be used with GenPictureHeader + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +SetGOPStartTime(index) + int index; +{ + lastGOPStart = gopStartFrame; + gopStartFrame = index; +} + + +/*===========================================================================* + * + * Mhead_GenPictureHeader + * + * generate picture header with given frame type and picture count + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenPictureHeader(bbPtr, frameType, pictCount, f_code) + BitBucket *bbPtr; + int frameType; + int pictCount; + int f_code; +{ + int temporalRef; + + if ( pictCount >= gopStartFrame ) { + temporalRef = (pictCount-gopStartFrame); + } else { + temporalRef = (pictCount-lastGOPStart); + } + temporalRef = (temporalRef % 1024); + + DBG_PRINT(("Picture Header\n")); + GenPictHead(bbPtr, temporalRef, frameType, + 0 /* vbv_delay */, + pixelFullSearch /* full_pel_forw_flag */, + f_code /* forw_f_code */, + pixelFullSearch /* full_pel_back_flag */, + f_code /* back_f_code */, + NULL, 0, NULL, 0, NULL, 0); +} + + +/*===========================================================================* + * + * Mhead_GenSequenceHeader + * + * generate sequence header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSequenceHeader(BitBucket * const bbPtr, + uint32 const hsize, + uint32 const vsize, + int32 const pratio, + int32 const pict_rate, + int32 const bit_rate_arg, + int32 const buf_size_arg, + int32 const c_param_flag_arg, + const int32 * const iq_matrix, + const int32 * const niq_matrix, + uint8 * const ext_data, + int32 const ext_data_size, + uint8 * const user_data, + int32 const user_data_size) { + + extern int ZAG[]; + int i; + int32 bit_rate; + int32 buf_size; + int32 c_param_flag; + + /* Write seq start code. */ + + Bitio_Write(bbPtr, SEQ_HEAD_CODE, 32); + + /* Write horiz. and vert. sizes. */ + +#ifdef BLEAH + fprintf(stdout, "hsize, vsize = %d, %d\n", hsize, vsize); +#endif + + if (hsize==0 || vsize==0) { + fprintf(stderr, "Writing zero size to stream!\n"); + } + Bitio_Write(bbPtr, hsize, 12); + Bitio_Write(bbPtr, vsize, 12); + + /* Write pixel aspect ratio, negative values default to 1. */ + + if (pratio < 0) { + fprintf(stderr, "PROGRAMMER ERROR: pratio = %d\n", pratio); + exit(1); + } + Bitio_Write(bbPtr, pratio, 4); + + /* Wrtie picture rate, negative values default to 30 fps. */ + + if (pict_rate < 0) { + fprintf(stderr, "PROGRAMMER ERROR: pict_rate = %d\n", pict_rate); + exit(1); + } + Bitio_Write(bbPtr, pict_rate, 4); + + /* Write bit rate, negative values default to variable. */ + + if (bit_rate_arg < 0) { + bit_rate = -1; + } else { + bit_rate = bit_rate_arg / 400; + } + + Bitio_Write(bbPtr, bit_rate, 18); + + /* Marker bit. */ + Bitio_Write(bbPtr, 0x1, 1); + + /* Write VBV buffer size. Negative values default to zero. */ + if (buf_size_arg < 0) + buf_size = 0; + else + buf_size = buf_size_arg; + + buf_size = (buf_size + (16*1024 - 1)) / (16*1024); + if (buf_size>=0x400) + buf_size=0x3ff; + Bitio_Write(bbPtr, buf_size, 10); + + /* Write constrained parameter flag. */ + { + int num_mb = ((hsize+15)/16) * ((vsize+15)/16); + /* At present we cheat on buffer size */ + c_param_flag = ((bit_rate <= 4640) && + (bit_rate >0) && + (buf_size <= 20) && + (pict_rate >= 1) && + (pict_rate <= 5) && + (hsize <= 768) && + (vsize <= 576) && + (num_mb <= 396) && + (num_mb*VidRateNum[pict_rate] <= 9900) && + (fCodeP<=4) && + (fCodeB<=4)); + } + + if (c_param_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Write intra quant matrix if present. */ + + if (iq_matrix != NULL) { + Bitio_Write(bbPtr, 0x01, 1); + for (i = 0; i < 64; i++) { + Bitio_Write(bbPtr, iq_matrix[ZAG[i]], 8); + } + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Write non intra quant matrix if present. */ + + if (niq_matrix != NULL) { + Bitio_Write(bbPtr, 0x01, 1); + for (i = 0; i < 64; i++) { + Bitio_Write(bbPtr, niq_matrix[ZAG[i]], 8); + } + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* next start code */ + Bitio_BytePad(bbPtr); + + + /* Write ext data if present. */ + + if (ext_data != NULL) { + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; i++) { + Bitio_Write(bbPtr, ext_data[i], 8); + } + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if ((user_data != NULL) && (user_data_size != 0)) { + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; i++) { + Bitio_Write(bbPtr, user_data[i], 8); + } + Bitio_BytePad(bbPtr); + } +} + + +/*===========================================================================* + * + * Mhead_GenSequenceEnder + * + * generate sequence ender + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSequenceEnder(bbPtr) + BitBucket *bbPtr; +{ + Bitio_Write(bbPtr, SEQ_END_CODE, 32); +} + + +/*===========================================================================* + * + * Mhead_GenGOPHeader + * + * generate GOP header with specified attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenGOPHeader(bbPtr, drop_frame_flag, tc_hrs, tc_min, tc_sec, tc_pict, + closed_gop, broken_link, ext_data, ext_data_size, + user_data, user_data_size) + BitBucket *bbPtr; + int32 drop_frame_flag; + int32 tc_hrs; + int32 tc_min; + int32 tc_sec; + int32 tc_pict; + int32 closed_gop; + int32 broken_link; + uint8 *ext_data; + int32 ext_data_size; + uint8 *user_data; + int32 user_data_size; +{ + int i; + + /* Write gop start code. */ + Bitio_Write(bbPtr, GOP_START_CODE, 32); + + /* Construct and write timecode. */ + + /* Drop frame flag. */ + if (drop_frame_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Time code hours. */ + Bitio_Write(bbPtr, tc_hrs, 5); + + /* Time code minutes. */ + Bitio_Write(bbPtr, tc_min, 6); + + /* Marker bit. */ + Bitio_Write(bbPtr, 0x01, 1); + + /* Time code seconds. */ + Bitio_Write(bbPtr, tc_sec, 6); + + /* Time code pictures. */ + Bitio_Write(bbPtr, tc_pict, 6); + + + /* Closed gop flag. */ + if (closed_gop) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Broken link flag. */ + if (broken_link) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* next start code */ + Bitio_BytePad(bbPtr); + + /* Write ext data if present. */ + + if (ext_data != NULL) { + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; i++) { + Bitio_Write(bbPtr, ext_data[i], 8); + } + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if (user_data != NULL) { + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; i++) { + Bitio_Write(bbPtr, user_data[i], 8); + } + Bitio_BytePad(bbPtr); + } +} + + +/*===========================================================================* + * + * Mhead_GenSliceHeader + * + * generate slice header with specified attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSliceHeader(bbPtr, verticalPos, qscale, extra_info, extra_info_size) + BitBucket *bbPtr; + uint32 verticalPos; + uint32 qscale; + uint8 *extra_info; + uint32 extra_info_size; +{ + int i; + + /* Write slice start code. */ + Bitio_Write(bbPtr, (SLICE_BASE_CODE + verticalPos), 32); + + /* Quant. scale. */ + Bitio_Write(bbPtr, qscale, 5); + lastQSSet = qscale; + + /* Extra bit slice info. */ + + if (extra_info != NULL) { + for (i = 0; i < extra_info_size; i++) { + Bitio_Write(bbPtr, 0x01, 1); + Bitio_Write(bbPtr, extra_info[i], 8); + } + } + + /* extra_bit_slice */ + Bitio_Write(bbPtr, 0x00, 1); +} + + +/*===========================================================================* + * + * Mhead_GenSliceEnder + * + * generate slice ender + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenSliceEnder(bbPtr) + BitBucket *bbPtr; +{ + Bitio_BytePad(bbPtr); +} + + +/*===========================================================================* + * + * Mhead_GenMBHeader + * + * generate macroblock header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mhead_GenMBHeader(bbPtr, pict_code_type, addr_incr, q_scale, + forw_f_code, back_f_code, horiz_forw_r, vert_forw_r, + horiz_back_r, vert_back_r, motion_forw, m_horiz_forw, + m_vert_forw, motion_back, m_horiz_back, m_vert_back, + mb_pattern, mb_intra) + BitBucket *bbPtr; + uint32 pict_code_type; + uint32 addr_incr; + uint32 q_scale; + uint32 forw_f_code; + uint32 back_f_code; + uint32 horiz_forw_r; + uint32 vert_forw_r; + uint32 horiz_back_r; + uint32 vert_back_r; + int32 motion_forw; + int32 m_horiz_forw; + int32 m_vert_forw; + int32 motion_back; + int32 m_horiz_back; + int32 m_vert_back; + uint32 mb_pattern; + uint32 mb_intra; +{ + uint32 mb_quant; + + /* MB escape sequences if necessary. */ + +#ifdef BLEAH +if ( addr_incr != 1 ) + fprintf(stdout, "Creating MB_INCR: %d\n", addr_incr); +#endif + + while (addr_incr > 33) { + Bitio_Write(bbPtr, 0x008, 11); + addr_incr -= 33; + } + + /* Generate addr incr code. */ + GenMBAddrIncr(bbPtr, addr_incr); + + /* Determine mb_quant (true if change in q scale) */ + if ((q_scale != lastQSSet) && ((mb_pattern != 0) || (mb_intra == TRUE))) { + mb_quant = TRUE; + lastQSSet = q_scale; + } else { + mb_quant = FALSE; + } + + /* Generate mb type code. */ + GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, mb_pattern, mb_intra); + + /* MB quant. */ + if (mb_quant) { + Bitio_Write(bbPtr, q_scale, 5); + } + /* Forward predictive vector stuff. */ + + if (motion_forw) { + int forw_f, forw_r_size; + + forw_r_size = forw_f_code - 1; + forw_f = 1 << forw_r_size; /* 1 > 0 */ + if ((m_horiz_forw > 16*forw_f-1) || (m_horiz_forw < -16*forw_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_horiz_forw, 16*forw_f); + } + if ((m_vert_forw > 16*forw_f-1) || (m_vert_forw < -16*forw_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_vert_forw, 16*forw_f); + } + GenMotionCode(bbPtr, m_horiz_forw); + + if ((forw_f != 1) && (m_horiz_forw != 0)) { + Bitio_Write(bbPtr, horiz_forw_r, forw_r_size); + } + GenMotionCode(bbPtr, m_vert_forw); + + if ((forw_f != 1) && (m_vert_forw != 0)) { + Bitio_Write(bbPtr, vert_forw_r, forw_r_size); + } + } + /* Back predicted vector stuff. */ + + if (motion_back) { + int back_f, back_r_size; + + back_r_size = back_f_code - 1; + back_f = 1 << back_r_size; /* 1 > 0 */ + + if ((m_horiz_back > 16*back_f-1) || (m_horiz_back < -16*back_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_horiz_back, 16*back_f); + } + if ((m_vert_back > 16*back_f-1) || (m_vert_back < -16*back_f)) { + fprintf(stderr, "Illegal motion? %d %d\n", m_vert_back, 16*back_f); + } + + GenMotionCode(bbPtr, m_horiz_back); + + if ((back_f != 1) && (m_horiz_back != 0)) { + Bitio_Write(bbPtr, horiz_back_r, back_r_size); + } + GenMotionCode(bbPtr, m_vert_back); + + if ((back_f != 1) && (m_vert_back != 0)) { + Bitio_Write(bbPtr, vert_back_r, back_r_size); + } + } + /* MB pattern. */ + + if (mb_pattern) { + GenBlockPattern(bbPtr, mb_pattern); + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenMBType + * + * generate macroblock type with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBType(bbPtr, pict_code_type, mb_quant, motion_forw, motion_back, + mb_pattern, mb_intra) + BitBucket *bbPtr; + uint32 pict_code_type; + uint32 mb_quant; + uint32 motion_forw; + uint32 motion_back; + uint32 mb_pattern; + uint32 mb_intra; +{ + int code; + + switch (pict_code_type) { + case 1: + if ((motion_forw != 0) || (motion_back != 0) || (mb_pattern != 0) || (mb_intra != 1)) { + perror("Illegal parameters for macroblock type."); + exit(-1); + } + if (mb_quant) { + Bitio_Write(bbPtr, 0x1, 2); + } else { + Bitio_Write(bbPtr, 0x1, 1); + } + break; + + case 2: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 2: + Bitio_Write(bbPtr, 0x1, 2); + break; + case 8: + Bitio_Write(bbPtr, 0x1, 3); + break; + case 10: + Bitio_Write(bbPtr, 0x1, 1); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + case 18: + Bitio_Write(bbPtr, 0x1, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x2, 5); + break; + default: + perror("Illegal parameters for macroblock type."); + exit(-1); + break; + } + break; + + case 3: + code = 0; + if (mb_quant) { + code += 16; + } + if (motion_forw) { + code += 8; + } + if (motion_back) { + code += 4; + } + if (mb_pattern) { + code += 2; + } + if (mb_intra) { + code += 1; + } + + switch (code) { + case 12: + Bitio_Write(bbPtr, 0x2, 2); + break; + case 14: + Bitio_Write(bbPtr, 0x3, 2); + break; + case 4: + Bitio_Write(bbPtr, 0x2, 3); + break; + case 6: + Bitio_Write(bbPtr, 0x3, 3); + break; + case 8: + Bitio_Write(bbPtr, 0x2, 4); + break; + case 10: + Bitio_Write(bbPtr, 0x3, 4); + break; + case 1: + Bitio_Write(bbPtr, 0x3, 5); + break; + case 30: + Bitio_Write(bbPtr, 0x2, 5); + break; + case 26: + Bitio_Write(bbPtr, 0x3, 6); + break; + case 22: + Bitio_Write(bbPtr, 0x2, 6); + break; + case 17: + Bitio_Write(bbPtr, 0x1, 6); + break; + default: + perror("Illegal parameters for macroblock type."); + exit(-1); + break; + } + break; + } +} + + +/*===========================================================================* + * + * GenMotionCode + * + * generate motion vector output with given value + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMotionCode(BitBucket * const bbPtr, + int32 const vector) { + + uint32 code, num; + + if ((vector < -16) || (vector > 16)) { + perror("Motion vector out of range."); + fprintf(stderr, "Motion vector out of range: vector = %d\n", vector); + exit(-1); + } + code = mbMotionVectorTable[vector + 16][0]; + num = mbMotionVectorTable[vector + 16][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenBlockPattern + * + * generate macroblock pattern output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenBlockPattern(bbPtr, mb_pattern) + BitBucket *bbPtr; + uint32 mb_pattern; +{ + uint32 code, num; + + code = mbPatTable[mb_pattern][0]; + num = mbPatTable[mb_pattern][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenMBAddrIncr + * + * generate macroblock address increment output + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenMBAddrIncr(bbPtr, addr_incr) + BitBucket *bbPtr; + uint32 addr_incr; +{ + uint32 code; + uint32 num; + + code = mbAddrIncrTable[addr_incr][0]; + num = mbAddrIncrTable[addr_incr][1]; + + Bitio_Write(bbPtr, code, num); +} + + +/*===========================================================================* + * + * GenPictHead + * + * generate picture header with given attributes + * append result to the specified bitstream + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +GenPictHead(bbPtr, temp_ref, code_type, vbv_delay, full_pel_forw_flag, + forw_f_code, full_pel_back_flag, back_f_code, extra_info, + extra_info_size, ext_data, ext_data_size, user_data, + user_data_size) + BitBucket *bbPtr; + uint32 temp_ref; + uint32 code_type; + uint32 vbv_delay; + int32 full_pel_forw_flag; + uint32 forw_f_code; + int32 full_pel_back_flag; + uint32 back_f_code; + uint8 *extra_info; + uint32 extra_info_size; + uint8 *ext_data; + uint32 ext_data_size; + uint8 *user_data; + uint32 user_data_size; +{ + int i; + + /* Write picture start code. */ + Bitio_Write(bbPtr, PICT_START_CODE, 32); + + /* Temp reference. */ + Bitio_Write(bbPtr, temp_ref, 10); + + /* Code_type. */ + if (code_type == 0) { + code_type = 1; + } + Bitio_Write(bbPtr, code_type, 3); + + /* vbv_delay. */ + vbv_delay = 0xffff; /* see page 36 (section 2.4.3.4) */ + Bitio_Write(bbPtr, vbv_delay, 16); + + if ((code_type == 2) || (code_type == 3)) { + + /* Full pel forw flag. */ + + if (full_pel_forw_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Forw f code. */ + + Bitio_Write(bbPtr, forw_f_code, 3); + } + if (code_type == 3) { + + /* Full pel back flag. */ + + if (full_pel_back_flag) { + Bitio_Write(bbPtr, 0x01, 1); + } else { + Bitio_Write(bbPtr, 0x00, 1); + } + + /* Back f code. */ + + Bitio_Write(bbPtr, back_f_code, 3); + } + /* Extra bit picture info. */ + + if (extra_info != NULL) { + for (i = 0; i < extra_info_size; i++) { + Bitio_Write(bbPtr, 0x01, 1); + Bitio_Write(bbPtr, extra_info[i], 8); + } + } + Bitio_Write(bbPtr, 0x00, 1); + + /* next start code */ + Bitio_BytePad(bbPtr); + + /* Write ext data if present. */ + + if (ext_data != NULL) { + Bitio_Write(bbPtr, EXT_START_CODE, 32); + + for (i = 0; i < ext_data_size; i++) { + Bitio_Write(bbPtr, ext_data[i], 8); + } + Bitio_BytePad(bbPtr); + } + /* Write user data if present. */ + if (user_data != NULL) { + Bitio_Write(bbPtr, USER_START_CODE, 32); + + for (i = 0; i < user_data_size; i++) { + Bitio_Write(bbPtr, user_data[i], 8); + } + Bitio_BytePad(bbPtr); + } +} + + +#ifdef UNUSED_PROCEDURES + +/* GenMBEnd only used for `D` pictures. Shouldn't really ever be called. */ +/* - dwallach */ +void +GenMBEnd(bbPtr) + BitBucket *bbPtr; +{ + Bitio_Write(bbPtr, 0x01, 1); +} + +#endif /* UNUSED_PROCEDURES */ diff --git a/converter/ppm/ppmtompeg/moutput.c b/converter/ppm/ppmtompeg/moutput.c new file mode 100644 index 00000000..b682efab --- /dev/null +++ b/converter/ppm/ppmtompeg/moutput.c @@ -0,0 +1,442 @@ +/*===========================================================================* + * moutput.c * + * * + * Procedures concerned with quantization and RLE * + * * + * EXPORTED PROCEDURES: * + * mp_quant_zig_block * + * mp_rle_huff_block * + * mp_rle_huff_pblock * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/moutput.c,v 1.12 1995/01/19 23:08:49 eyhung Exp $ + * $Log: moutput.c,v $ + * Revision 1.12 1995/01/19 23:08:49 eyhung + * Changed copyrights + * + * Revision 1.11 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.10 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.9 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.8 1993/02/24 18:57:19 keving + * nothing + * + * Revision 1.7 1993/02/23 22:58:36 keving + * nothing + * + * Revision 1.6 1993/02/23 22:54:56 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "mproto.h" +#include "huff.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */ +static int ZAG[] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + + +/* + * possible optimization: reorder the qtable in the correct zigzag order, to + * reduce the number of necessary lookups + * + * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15. + */ +static int qtable[] = +{ + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83}; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +void UnQuantZig(FlatBlock in, Block out, int qscale, boolean iblock) +{ + register int index; + int start; + int position; + register int qentry; + int level, coeff; + register int16 temp; + + if ( iblock ) + { + ((int16 *)out)[0] = (int16)(in[0]*qtable[0]); + + start = 1; + } + else + start = 0; + + for ( index = start; index < DCTSIZE_SQ; index++ ) + { + position = ZAG[index]; + + if (iblock) + qentry = qtable[position] * qscale; + else + qentry = 16 * qscale; + + level = in[index]; + coeff = (level * qentry) >> 3; + if (level < 0) { + coeff += (coeff & 1); + } else { + coeff -= (coeff & 1); + } + + ((int16 *)out)[position] = coeff; + } + +#ifdef BLEAH + for ( index = 0; index < 64; index++ ) + fprintf(stdout, "DCT[%d] = %d\n", index, + ((int16 *)out)[index]); +#endif +} + + +/* + * -------------------------------------------------------------- + * + * mp_quant_zig_block -- + * + * Quantizes and zigzags a block -- removing information + * + * Results: TRUE iff resulting 'out' is non-zero, FALSE if all + * zero + * + * Side effects: Modifies the out block. + * + * -------------------------------------------------------------- + */ +boolean mp_quant_zig_block(Block in, FlatBlock out, int qscale, int iblock) +{ + register int i; + register int y, x; + register int16 temp; + register int qentry; + int start; + boolean nonZero = FALSE; + + DBG_PRINT(("mp_quant_zig_block...\n")); + if (iblock) { + /* + * the DC coefficient is handled specially -- it's not + * sensitive to qscale, but everything else is + */ + temp = ((int16 *) in)[ZAG[0]]; + qentry = qtable[ZAG[0]]; + if (temp < 0) { + temp = -temp; + temp += qentry >> 1; + temp /= qentry; + temp = -temp; + } else { + temp += qentry >> 1; + temp /= qentry; + } + if ( temp != 0 ) + nonZero = TRUE; + out[0] = temp; + start = 1; + } else + start = 0; + + for (i = start; i < DCTSIZE_SQ; i++) { + x = ZAG[i] % 8; + y = ZAG[i] / 8; + temp = in[y][x]; + DBG_PRINT((" in[%d][%d] = %d; ", y, x, temp)); + + if (iblock) + qentry = qtable[ZAG[i]] * qscale; + else + qentry = 16 * qscale; + + DBG_PRINT(("quantized with %d = ", qentry)); + + if (temp < 0) { + temp = -temp; + temp *= 8; + temp += qentry >> 1; + temp /= qentry; + temp = -temp; + } else { + temp *= 8; + temp += qentry >> 1; + temp /= qentry; + } + if ( temp != 0 ) + nonZero = TRUE; + out[i] = temp; + DBG_PRINT(("%d\n", temp)); + } + + return nonZero; +} + + + +/* + * -------------------------------------------------------------- + * + * mp_rle_huff_block -- + * + * Given a FlatBlock, generates the Huffman bits + * + * Results: None. + * + * Side effects: Output bits changed + * + * -------------------------------------------------------------- + */ + +void mp_rle_huff_block(FlatBlock in, BitBucket *out) +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register uint32 code; + register int nbits; + + /* + * yes, Virginia, we start at 1. The DC coefficient is handled + * specially, elsewhere. Not here. + */ + for (i = 1; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) { + /* + * encode using the Huffman tables + */ + + DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur)); + assert(cur); + + code = (huff_table[nzeros])[acur]; + nbits = (huff_bits[nzeros])[acur]; + + assert(nbits); + + if (cur < 0) + code |= 1; /* the sign bit */ + Bitio_Write(out, code, nbits); + } else { + /* + * encode using the escape code + */ + DBG_PRINT(("Escape\n")); + Bitio_Write(out, 0x1, 6); /* ESCAPE */ + DBG_PRINT(("Run Length\n")); + Bitio_Write(out, nzeros, 6); /* Run-Length */ + + assert(cur != 0); + + /* + * this shouldn't happen, but the other + * choice is to bomb out and dump core... + */ + if (cur < -255) + cur = -255; + else if (cur > 255) + cur = 255; + + DBG_PRINT(("Level\n")); + if (acur < 128) { + Bitio_Write(out, cur, 8); + } else { + if (cur < 0) { + Bitio_Write(out, 0x8001 + cur + 255, 16); + } else + Bitio_Write(out, cur, 16); + } + } + nzeros = 0; + } else + nzeros++; + } + DBG_PRINT(("End of block\n")); + Bitio_Write(out, 0x2, 2); /* end of block marker */ +} + + +/* + * -------------------------------------------------------------- + * + * mp_rle_huff_pblock -- + * + * Given a FlatBlock, generates the Huffman bits for P DCT + * + * Results: None. + * + * Side effects: Output bits changed + * + * -------------------------------------------------------------- + */ + +void mp_rle_huff_pblock(FlatBlock in, BitBucket *out) +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register uint32 code; + register int nbits; + boolean first_dct = TRUE; + + /* + * yes, Virginia, we start at 0. + */ + for (i = 0; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) { + /* + * encode using the Huffman tables + */ + + DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur)); + assert(cur); + + if ( first_dct && (nzeros == 0) && (acur == 1) ) + { + /* actually, only needs = 0x2 */ + code = (cur == 1) ? 0x2 : 0x3; + nbits = 2; + } + else + { + code = (huff_table[nzeros])[acur]; + nbits = (huff_bits[nzeros])[acur]; + } + + assert(nbits); + + if (cur < 0) + code |= 1; /* the sign bit */ + Bitio_Write(out, code, nbits); + first_dct = FALSE; + } else { + /* + * encode using the escape code + */ + DBG_PRINT(("Escape\n")); + Bitio_Write(out, 0x1, 6); /* ESCAPE */ + DBG_PRINT(("Run Length\n")); + Bitio_Write(out, nzeros, 6); /* Run-Length */ + + assert(cur != 0); + + /* + * this shouldn't happen, but the other + * choice is to bomb out and dump core... + */ + if (cur < -255) + cur = -255; + else if (cur > 255) + cur = 255; + + DBG_PRINT(("Level\n")); + if (acur < 128) { + Bitio_Write(out, cur, 8); + } else { + if (cur < 0) { + Bitio_Write(out, 0x8001 + cur + 255, 16); + } else + Bitio_Write(out, cur, 16); + } + + first_dct = FALSE; + } + nzeros = 0; + } else + nzeros++; + } + + /* actually, should REALLY return FALSE and not use this! */ + if ( first_dct ) /* have to give a first_dct even if all 0's */ + { + fprintf(stdout, "HUFF called with all-zero coefficients\n"); + fprintf(stdout, "exiting...\n"); + exit(1); + } + + DBG_PRINT(("End of block\n")); + Bitio_Write(out, 0x2, 2); /* end of block marker */ +} diff --git a/converter/ppm/ppmtompeg/mpeg.c b/converter/ppm/ppmtompeg/mpeg.c new file mode 100644 index 00000000..a934ed09 --- /dev/null +++ b/converter/ppm/ppmtompeg/mpeg.c @@ -0,0 +1,1717 @@ +/*===========================================================================* + * mpeg.c + * + * Procedures to generate the MPEG sequence + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#define _BSD_SOURCE /* Make sure strdup() is in string.h */ + +#include "all.h" +#include <time.h> +#include <errno.h> +#include <unistd.h> +#include <assert.h> +#include <string.h> +#ifdef MIPS +#include <sys/types.h> +#endif +#include <sys/stat.h> + +#include "ppm.h" +#include "nstring.h" + +#include "mtypes.h" +#include "frames.h" +#include "motion_search.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "mheaders.h" +#include "rate.h" +#include "input.h" +#include "frametype.h" +#include "mpeg.h" + + +/*===========* + * VERSION * + *===========*/ + +#define VERSION "1.5b" + + +/*===========* + * CONSTANTS * + *===========*/ + +#define FPS_30 0x5 /* from MPEG standard sect. 2.4.3.2 */ +#define ASPECT_1 0x1 /* aspect ratio, from MPEG standard sect. 2.4.3.2 */ + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static unsigned int framesOutput; +static int realStart, realEnd; +static int currentGOP; +static int timeMask; +static int numI, numP, numB; +static boolean frameCountsUnknown; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +/* important -- don't initialize anything here */ +/* must be re-initted anyway in GenMPEGStream */ + +extern int IOtime; +extern boolean resizeFrame; +extern int outputWidth, outputHeight; +int gopSize = 100; /* default */ +int32 tc_hrs, tc_min, tc_sec, tc_pict, tc_extra; +int totalFramesSent; +int yuvWidth, yuvHeight; +int realWidth, realHeight; +char currentPath[MAXPATHLEN]; +char statFileName[256]; +char bitRateFileName[256]; +time_t timeStart, timeEnd; +FILE *statFile; +FILE *bitRateFile = NULL; +char *framePattern; +int framePatternLen; +int referenceFrame; +int frameRate = FPS_30; +int frameRateRounded = 30; +boolean frameRateInteger = TRUE; +int aspectRatio = ASPECT_1; +extern char userDataFileName[]; +extern int mult_seq_headers; + +int32 bit_rate, buf_size; + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText)); +static void OpenBitRateFile _ANSI_ARGS_((void)); +static void CloseBitRateFile _ANSI_ARGS_((void)); + + +static void +ShowRemainingTime(boolean const childProcess) { +/*---------------------------------------------------------------------------- + Print out an estimate of the time left to encode +-----------------------------------------------------------------------------*/ + + if (childProcess) { + /* nothing */; + } else if ( numI + numP + numB == 0 ) { + /* no time left */ + } else if ( timeMask != 0 ) { + /* haven't encoded all types yet */ + } else { + static int lastTime = 0; + float total; + time_t nowTime; + float secondsPerFrame; + + time(&nowTime); + secondsPerFrame = (nowTime-timeStart)/(float)framesOutput; + total = secondsPerFrame*(float)(numI+numP+numB); + + if ((quietTime >= 0) && (!realQuiet) && (!frameCountsUnknown) && + ((lastTime < (int)total) || ((lastTime-(int)total) >= quietTime) || + (lastTime == 0) || (quietTime == 0))) { + if (total > 270.0) + pm_message("ESTIMATED TIME OF COMPLETION: %d minutes", + ((int)total+30)/60); + else + pm_message("ESTIMATED TIME OF COMPLETION: %d seconds", + (int)total); + } + lastTime = (int)total; + } +} + + + +static void +initTCTime(unsigned int const firstFrameNumber) { + + unsigned int frameNumber; + + tc_hrs = 0; tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0; + for (frameNumber = 0; frameNumber < firstFrameNumber; ++frameNumber) + IncrementTCTime(); +} + + + +/*===========================================================================* + * + * IncrementTCTime + * + * increment the tc time by one second (and update min, hrs if necessary) + * also increments totalFramesSent + * + * RETURNS: nothing + * + * SIDE EFFECTS: totalFramesSent, tc_pict, tc_sec, tc_min, tc_hrs, tc_extra + * + *===========================================================================*/ +void +IncrementTCTime() { + /* if fps = an integer, then tc_extra = 0 and is ignored + + otherwise, it is the number of extra 1/1001 frames we've passed by + + so far; for example, if fps = 24000/1001, then 24 frames = 24024/24000 + seconds = 1 second + 24/24000 seconds = 1 + 1/1000 seconds; similary, + if fps = 30000/1001, then 30 frames = 30030/30000 = 1 + 1/1000 seconds + and if fps = 60000/1001, then 60 frames = 1 + 1/1000 seconds + + if fps = 24000/1001, then 1/1000 seconds = 24/1001 frames + if fps = 30000/1001, then 1/1000 seconds = 30/1001 frames + if fps = 60000/1001, then 1/1000 seconds = 60/1001 frames + */ + + totalFramesSent++; + tc_pict++; + if ( tc_pict >= frameRateRounded ) { + tc_pict = 0; + tc_sec++; + if ( tc_sec == 60 ) { + tc_sec = 0; + tc_min++; + if ( tc_min == 60 ) { + tc_min = 0; + tc_hrs++; + } + } + if ( ! frameRateInteger ) { + tc_extra += frameRateRounded; + if ( tc_extra >= 1001 ) { /* a frame's worth */ + tc_pict++; + tc_extra -= 1001; + } + } + } +} + + + +static void +initializeRateControl(bool const wantUnderflowWarning, + bool const wantOverflowWarning) { +/*---------------------------------------------------------------------------- + Initialize rate control +-----------------------------------------------------------------------------*/ + int32 const bitstreamMode = getRateMode(); + + if (bitstreamMode == FIXED_RATE) { + initRateControl(wantUnderflowWarning, wantOverflowWarning); + /* + SetFrameRate(); + */ + } +} + + + +/*===========================================================================* + * + * SetReferenceFrameType + * + * set the reference frame type to be original or decoded + * + * RETURNS: nothing + * + * SIDE EFFECTS: referenceFrame + * + *===========================================================================*/ +void +SetReferenceFrameType(const char * const type) { + + if (strcmp(type, "ORIGINAL") == 0) + referenceFrame = ORIGINAL_FRAME; + else if ( strcmp(type, "DECODED") == 0 ) + referenceFrame = DECODED_FRAME; + else + pm_error("INTERNAL ERROR: Illegal reference frame type: '%s'", type); +} + + + +void +SetBitRateFileName(fileName) + char *fileName; +{ + strcpy(bitRateFileName, fileName); +} + + + + +static void +finishFrameOutput(MpegFrame * const frameP, + BitBucket * const bbP, + boolean const separateFiles, + int const referenceFrame, + boolean const childProcess, + boolean const remoteIO) { + + if ((referenceFrame == DECODED_FRAME) && + childProcess && NonLocalRefFrame(frameP->id)) { + if (remoteIO) + SendDecodedFrame(frameP); + else + WriteDecodedFrame(frameP); + + NotifyDecodeServerReady(frameP->id); + } + + if (separateFiles) { + if (remoteIO) + SendRemoteFrame(frameP->id, bbP); + else { + Bitio_Flush(bbP); + Bitio_Close(bbP); + } + } +} + + + + +static void +outputIFrame(MpegFrame * const frameP, + BitBucket * const bb, + int const realStart, + int const realEnd, + MpegFrame * const pastRefFrameP, + boolean const separateFiles) { + + /* only start a new GOP with I */ + /* don't start GOP if only doing frames */ + if ((!separateFiles) && (currentGOP >= gopSize)) { + boolean const closed = + (totalFramesSent == frameP->id || pastRefFrameP == NULL); + + static int num_gop = 0; + + /* first, check to see if closed GOP */ + + /* new GOP */ + if (num_gop != 0 && mult_seq_headers && + num_gop % mult_seq_headers == 0) { + if (!realQuiet) { + fprintf(stdout, + "Creating new Sequence before GOP %d\n", num_gop); + fflush(stdout); + } + + Mhead_GenSequenceHeader( + bb, Fsize_x, Fsize_y, + /* pratio */ aspectRatio, + /* pict_rate */ frameRate, /* bit_rate */ bit_rate, + /* buf_size */ buf_size, /* c_param_flag */ 1, + /* iq_matrix */ customQtable, + /* niq_matrix */ customNIQtable, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + } + + if (!realQuiet) + pm_message("Creating new GOP (closed = %s) before frame %d\n", + closed ? "YES" : "NO", frameP->id); + + ++num_gop; + Mhead_GenGOPHeader(bb, /* drop_frame_flag */ 0, + tc_hrs, tc_min, tc_sec, tc_pict, + closed, /* broken_link */ 0, + /* ext_data */ NULL, /* ext_data_size */ 0, + /* user_data */ NULL, /* user_data_size */ 0); + currentGOP -= gopSize; + if (pastRefFrameP == NULL) + SetGOPStartTime(0); + else + SetGOPStartTime(pastRefFrameP->id+1); + } + + if ((frameP->id >= realStart) && (frameP->id <= realEnd)) + GenIFrame(bb, frameP); + + numI--; + timeMask &= 0x6; + + currentGOP++; + IncrementTCTime(); +} + + + +static void +outputPFrame(MpegFrame * const frameP, + BitBucket * const bbP, + int const realStart, + int const realEnd, + MpegFrame * const pastRefFrameP) { + + if ((frameP->id >= realStart) && (frameP->id <= realEnd)) + GenPFrame(bbP, frameP, pastRefFrameP); + + numP--; + timeMask &= 0x5; + + currentGOP++; + IncrementTCTime(); +} + + + +static BitBucket * +bitioNew(const char * const outputFileName, + unsigned int const frameNumber, + boolean const remoteIO) { + + BitBucket * bbP; + + if (remoteIO) + bbP = Bitio_New(NULL); + else { + const char * fileName; + + asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber); + + bbP = Bitio_New_Filename(fileName); + + strfree(fileName); + } + return bbP; +} + + + +static void +getBFrame(int const frameNum, + struct inputSource * const inputSourceP, + MpegFrame * const pastRefFrameP, + boolean const childProcess, + boolean const remoteIO, + MpegFrame ** const bFramePP, + int * const IOtimeP, + unsigned int * const framesReadP) { +/*---------------------------------------------------------------------------- + Get Frame 'frameNum', which is a B frame related to previous reference + frame 'pastRefFrameP'. Return it as *bFramePP. + + We have various ways of getting the frame, corresponding to the + multitude of modes in which Ppmtompeg works. +-----------------------------------------------------------------------------*/ + if (!inputSourceP->stdinUsed) { + time_t tempTimeStart, tempTimeEnd; + MpegFrame * bFrameP; + bool endOfStream; + + bFrameP = Frame_New(frameNum, 'b'); + + time(&tempTimeStart); + + ReadNthFrame(inputSourceP, frameNum, remoteIO, childProcess, + separateConversion, slaveConversion, inputConversion, + bFrameP, &endOfStream); + + assert(!endOfStream); /* Because it's not a stream */ + + time(&tempTimeEnd); + *IOtimeP += (tempTimeEnd-tempTimeStart); + + ++(*framesReadP); + *bFramePP = bFrameP; + } else { + /* As the frame input is serial, we can't read the B frame now. + Rather, Caller has already read it and chained it to + the previous reference frame. So we get that copy now. + */ + *bFramePP = pastRefFrameP->next; + pastRefFrameP->next = (*bFramePP)->next; /* unlink from list */ + } +} + + + +static void +processBFrames(MpegFrame * const pastRefFrameP, + MpegFrame * const futureRefFrameP, + int const realStart, + int const realEnd, + struct inputSource * const inputSourceP, + boolean const remoteIo, + boolean const childProcess, + int * const IOtimeP, + BitBucket * const wholeStreamBbP, + const char * const outputFileName, + unsigned int * const framesReadP, + unsigned int * const framesOutputP, + int * const currentGopP) { +/*---------------------------------------------------------------------------- + Process the B frames that go between 'pastRefFrameP' and + 'futureRefFrame' in the movie (but go after 'futureRefFrameP' in the + MPEG stream, so reader doesn't have to read ahead). + + Remember that a B frame is one which is described by data in the + MPEG stream that describes the frame with respect to a frame somewhere + before it, and a frame somewhere after it (i.e. reference frames). + + But do only those B frames whose frame numbers are within the range + 'realStart' through 'realEnd'. +-----------------------------------------------------------------------------*/ + boolean const separateFiles = (wholeStreamBbP == NULL); + unsigned int const firstBFrameNum = pastRefFrameP->id + 1; + + int frameNum; + + assert(pastRefFrameP != NULL); + assert(futureRefFrameP != NULL); + + for (frameNum = MAX(realStart, firstBFrameNum); + frameNum < MIN(realEnd, futureRefFrameP->id); + ++frameNum) { + + MpegFrame * bFrame; + BitBucket * bbP; + + getBFrame(frameNum, inputSourceP, pastRefFrameP, childProcess, + remoteIO, + &bFrame, IOtimeP, framesReadP); + + if (separateFiles) + bbP = bitioNew(outputFileName, bFrame->id, remoteIO); + else + bbP = wholeStreamBbP; + + GenBFrame(bbP, bFrame, pastRefFrameP, futureRefFrameP); + ++(*framesOutputP); + + if (separateFiles) { + if (remoteIO) + SendRemoteFrame(bFrame->id, bbP); + else { + Bitio_Flush(bbP); + Bitio_Close(bbP); + } + } + + /* free this B frame right away */ + Frame_Free(bFrame); + + numB--; + timeMask &= 0x3; + ShowRemainingTime(childProcess); + + ++(*currentGopP); + IncrementTCTime(); + } +} + + + +static void +processRefFrame(MpegFrame * const frameP, + BitBucket * const bb_arg, + int const realStart, + int const realEnd, + MpegFrame * const pastRefFrameP, + boolean const childProcess, + const char * const outputFileName, + unsigned int * const framesReadP, + unsigned int * const framesOutputP) { +/*---------------------------------------------------------------------------- + Process an I or P frame. Encode and output it. + + But only if its frame number is within the range 'realStart' + through 'realEnd'. +-----------------------------------------------------------------------------*/ + if (frameP->id >= realStart && frameP->id <= realEnd) { + boolean separateFiles; + BitBucket * bb; + + separateFiles = (bb_arg == NULL); + + if ( separateFiles ) + bb = bitioNew(outputFileName, frameP->id, remoteIO); + else + bb = bb_arg; + + /* first, output this reference frame */ + switch (frameP->type) { + case TYPE_IFRAME: + outputIFrame(frameP, bb, realStart, realEnd, pastRefFrameP, + separateFiles); + break; + case TYPE_PFRAME: + outputPFrame(frameP, bb, realStart, realEnd, pastRefFrameP); + ShowRemainingTime(childProcess); + break; + default: + pm_error("INTERNAL ERROR: non-reference frame passed to " + "ProcessRefFrame()"); + } + + ++(*framesOutputP); + + finishFrameOutput(frameP, bb, separateFiles, referenceFrame, + childProcess, remoteIO); + } +} + + + +static void +countFrames(unsigned int const firstFrame, + unsigned int const lastFrame, + boolean const stdinUsed, + int * const numIP, + int * const numPP, + int * const numBP, + int * const timeMaskP, + boolean * const frameCountsUnknownP) { +/*---------------------------------------------------------------------------- + Count number of I, P, and B frames +-----------------------------------------------------------------------------*/ + unsigned int numI, numP, numB; + unsigned int timeMask; + + numI = 0; numP = 0; numB = 0; + timeMask = 0; + if (stdinUsed) { + numI = numP = numB = MAXINT/4; + *frameCountsUnknownP = TRUE; + } else { + unsigned int i; + for (i = firstFrame; i <= lastFrame; ++i) { + char const frameType = FType_Type(i); + switch(frameType) { + case 'i': numI++; timeMask |= 0x1; break; + case 'p': numP++; timeMask |= 0x2; break; + case 'b': numB++; timeMask |= 0x4; break; + } + } + *frameCountsUnknownP = FALSE; + } + + *numIP = numI; + *numPP = numP; + *numBP = numB; + *timeMaskP = timeMask; + *frameCountsUnknownP = frameCountsUnknown; +} + + + +static void +readAndSaveFrame(struct inputSource * const inputSourceP, + unsigned int const frameNumber, + char const frameType, + const char * const inputConversion, + MpegFrame * const pastRefFrameP, + unsigned int * const framesReadP, + int * const ioTimeP, + bool * const endOfStreamP) { +/*---------------------------------------------------------------------------- + Read the next frame from Standard Input and add it to the linked list + at *pastRefFrameP. Assume it is Frame Number 'frameNumber' and is of + type 'frameType'. + + Increment *framesReadP. + + Add the time it took to read it, in seconds, to *iotimeP. + + Iff we can't read because we hit end of file, return + *endOfStreamP == TRUE and *framesReadP and *iotimeP untouched. +-----------------------------------------------------------------------------*/ + /* This really should be part of ReadNthFrame. The frame should be chained + to the input object, not the past reference frame. + */ + + MpegFrame * p; + MpegFrame * frameP; + time_t ioTimeStart, ioTimeEnd; + + time(&ioTimeStart); + + frameP = Frame_New(frameNumber, frameType); + ReadFrame(frameP, inputSourceP, frameNumber, inputConversion, + endOfStreamP); + + if (*endOfStreamP) + Frame_Free(frameP); + else { + ++(*framesReadP); + + time(&ioTimeEnd); + *ioTimeP += (ioTimeEnd - ioTimeStart); + + /* Add the B frame to the end of the queue of B-frames + for later encoding. + */ + assert(pastRefFrameP != NULL); + + p = pastRefFrameP; + while (p->next != NULL) + p = p->next; + p->next = frameP; + } +} + + + +static void +doFirstFrameStuff(enum frameContext const context, + const char * const userDataFileName, + BitBucket * const bb, + int const fsize_x, + int const fsize_y, + int const aspectRatio, + int const frameRate, + int32 const qtable[], + int32 const niqtable[], + unsigned int * const inputFrameBitsP) { +/*---------------------------------------------------------------------------- + Do stuff we have to do after reading the first frame in a sequence + of frames requested of GenMPEGStream(). +-----------------------------------------------------------------------------*/ + *inputFrameBitsP = 24*Fsize_x*Fsize_y; + SetBlocksPerSlice(); + + if (context == CONTEXT_WHOLESTREAM) { + int32 const bitstreamMode = getRateMode(); + char * userData; + unsigned int userDataSize; + + assert(bb != NULL); + + DBG_PRINT(("Generating sequence header\n")); + if (bitstreamMode == FIXED_RATE) { + bit_rate = getBitRate(); + buf_size = getBufferSize(); + } else { + bit_rate = -1; + buf_size = -1; + } + + if (strlen(userDataFileName) != 0) { + struct stat statbuf; + FILE *fp; + + stat(userDataFileName,&statbuf); + userDataSize = statbuf.st_size; + userData = malloc(userDataSize); + fp = fopen(userDataFileName,"rb"); + if (fp == NULL) { + pm_message("Could not open userdata file '%s'.", + userDataFileName); + userData = NULL; + userDataSize = 0; + } else { + size_t bytesRead; + + bytesRead = fread(userData,1,userDataSize,fp); + if (bytesRead != userDataSize) { + pm_message("Could not read %d bytes from " + "userdata file '%s'.", + userDataSize,userDataFileName); + userData = NULL; + userDataSize = 0; + } + } + } else { /* Put in our UserData Header */ + const char * userDataString; + time_t now; + + time(&now); + asprintfN(&userDataString,"MPEG stream encoded by UCB Encoder " + "(mpeg_encode) v%s on %s.", + VERSION, ctime(&now)); + userData = strdup(userDataString); + userDataSize = strlen(userData); + strfree(userDataString); + } + Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y, + /* pratio */ aspectRatio, + /* pict_rate */ frameRate, + /* bit_rate */ bit_rate, + /* buf_size */ buf_size, + /*c_param_flag */ 1, + /* iq_matrix */ qtable, + /* niq_matrix */ niqtable, + /* ext_data */ NULL, + /* ext_data_size */ 0, + /* user_data */ (uint8*) userData, + /* user_data_size */ userDataSize); + } +} + + + +static void +getPreviousFrame(unsigned int const frameStart, + int const referenceFrame, + struct inputSource * const inputSourceP, + boolean const childProcess, + const char * const slaveConversion, + const char * const inputConversion, + MpegFrame ** const framePP, + unsigned int * const framesReadP, + int * const ioTimeP) { + + /* This needs to be modularized. It shouldn't issue messages about + encoding GOPs and B frames, since it knows nothing about those. + It should work for Standard Input too, through a generic Standard + Input reader that buffers stuff for backward reading. + */ + + MpegFrame * frameP; + time_t ioTimeStart, ioTimeEnd; + + /* can't find the previous frame interactively */ + if (inputSourceP->stdinUsed) + pm_error("Cannot encode GOP from stdin when " + "first frame is a B-frame."); + + if (frameStart < 1) + pm_error("Cannot encode GOP when first frame is a B-frame " + "and is not preceded by anything."); + + /* need to load in previous frame; call it an I frame */ + frameP = Frame_New(frameStart-1, 'i'); + + time(&ioTimeStart); + + if ((referenceFrame == DECODED_FRAME) && childProcess) { + WaitForDecodedFrame(frameStart); + + if (remoteIO) + GetRemoteDecodedRefFrame(frameP, frameStart - 1); + else + ReadDecodedRefFrame(frameP, frameStart - 1); + } else { + bool endOfStream; + ReadNthFrame(inputSourceP, frameStart - 1, remoteIO, childProcess, + separateConversion, slaveConversion, inputConversion, + frameP, &endOfStream); + assert(!endOfStream); /* Because Stdin causes failure above */ + } + ++(*framesReadP); + + time(&ioTimeEnd); + *ioTimeP += (ioTimeEnd-ioTimeStart); + + *framePP = frameP; +} + + + +static void +computeFrameRange(unsigned int const frameStart, + unsigned int const frameEnd, + enum frameContext const context, + struct inputSource * const inputSourceP, + unsigned int * const firstFrameP, + unsigned int * const lastFrameP) { + + switch (context) { + case CONTEXT_GOP: + *firstFrameP = frameStart; + *lastFrameP = frameEnd; + break; + case CONTEXT_JUSTFRAMES: { + /* if first frame is P or B, need to read in P or I frame before it */ + if (FType_Type(frameStart) != 'i') { + /* can't find the previous frame interactively */ + if (inputSourceP->stdinUsed) + pm_error("Cannot encode frames from Standard Input " + "when first frame is not an I-frame."); + + *firstFrameP = FType_PastRef(frameStart); + } else + *firstFrameP = frameStart; + + /* if last frame is B, need to read in P or I frame after it */ + if ((FType_Type(frameEnd) == 'b') && + (frameEnd != inputSourceP->numInputFiles-1)) { + /* can't find the next reference frame interactively */ + if (inputSourceP->stdinUsed) + pm_error("Cannot encode frames from Standard Input " + "when last frame is a B-frame."); + + *lastFrameP = FType_FutureRef(frameEnd); + } else + *lastFrameP = frameEnd; + } + break; + case CONTEXT_WHOLESTREAM: + *firstFrameP = frameStart; + *lastFrameP = frameEnd; + } +} + + + +static void +getFrame(MpegFrame ** const framePP, + struct inputSource * const inputSourceP, + unsigned int const frameNumber, + char const frameType, + unsigned int const realStart, + unsigned int const realEnd, + int const referenceFrame, + boolean const childProcess, + boolean const remoteIo, + boolean const separateConversion, + const char * const slaveConversion, + const char * const inputConversion, + unsigned int * const framesReadP, + int * const ioTimeP) { +/*---------------------------------------------------------------------------- + Get frame with number 'frameNumber' as *frameP. + + Increment *framesReadP. + + Add to *ioTimeP the time in seconds we spent reading it. + + Iff we fail to get the frame because the stream ends, return + *frameP == NULL, don't increment *framesReadP, and leave + *ioTimeP unchanged. +-----------------------------------------------------------------------------*/ + time_t ioTimeStart, ioTimeEnd; + MpegFrame * frameP; + bool endOfStream; + + time(&ioTimeStart); + + frameP = Frame_New(frameNumber, frameType); + + if ((referenceFrame == DECODED_FRAME) && + ((frameNumber < realStart) || (frameNumber > realEnd)) ) { + WaitForDecodedFrame(frameNumber); + + if (remoteIo) + GetRemoteDecodedRefFrame(frameP, frameNumber); + else + ReadDecodedRefFrame(frameP, frameNumber); + + /* I don't know what this block of code does, so I don't know + what endOfStream should be. Here's a guess: + */ + endOfStream = FALSE; + } else + ReadNthFrame(inputSourceP, frameNumber, remoteIO, childProcess, + separateConversion, slaveConversion, inputConversion, + frameP, &endOfStream); + + if (endOfStream) { + Frame_Free(frameP); + *framePP = NULL; + } else { + ++(*framesReadP); + + time(&ioTimeEnd); + *ioTimeP += (ioTimeEnd - ioTimeStart); + + *framePP = frameP; + } +} + + + +static void +handleBitRate(unsigned int const realEnd, + unsigned int const numBits, + boolean const childProcess, + boolean const showBitRatePerFrame) { + + extern void PrintItoIBitRate (int numBits, int frameNum); + + if (FType_Type(realEnd) != 'i') + PrintItoIBitRate(numBits, realEnd+1); + + if ((!childProcess) && showBitRatePerFrame) + CloseBitRateFile(); +} + + + +static void +doAFrame(unsigned int const frameNumber, + struct inputSource * const inputSourceP, + enum frameContext const context, + unsigned int const frameStart, + unsigned int const frameEnd, + unsigned int const realStart, + unsigned int const realEnd, + bool const childProcess, + const char * const outputFileName, + MpegFrame * const pastRefFrameP, + MpegFrame ** const newPastRefFramePP, + unsigned int * const framesReadP, + unsigned int * const framesOutputP, + bool * const firstFrameDoneP, + BitBucket * const bbP, + unsigned int * const inputFrameBitsP, + bool * const endOfStreamP) { +/*---------------------------------------------------------------------------- + *endOfStreamP returned means we were unable to do a frame because + the input stream has ended. In that case, none of the other outputs + are valid. +-----------------------------------------------------------------------------*/ + char const frameType = FType_Type(frameNumber); + + *endOfStreamP = FALSE; /* initial assumption */ + + if (frameType == 'b') { + /* We'll process this non-reference frame later. If reading + from stdin, we read it now and save it. Otherwise, we can + just read it later. + */ + *newPastRefFramePP = pastRefFrameP; + if (inputSourceP->stdinUsed) + readAndSaveFrame(inputSourceP, + frameNumber, frameType, inputConversion, + pastRefFrameP, framesReadP, &IOtime, + endOfStreamP); + } else { + MpegFrame * frameP; + + getFrame(&frameP, inputSourceP, frameNumber, frameType, + realStart, realEnd, referenceFrame, childProcess, + remoteIO, + separateConversion, slaveConversion, inputConversion, + framesReadP, &IOtime); + + if (frameP) { + *endOfStreamP = FALSE; + + if (!*firstFrameDoneP) { + doFirstFrameStuff(context, userDataFileName, + bbP, Fsize_x, Fsize_y, aspectRatio, + frameRate, qtable, niqtable, + inputFrameBitsP); + + *firstFrameDoneP = TRUE; + } + processRefFrame(frameP, bbP, frameStart, frameEnd, + pastRefFrameP, childProcess, outputFileName, + framesReadP, framesOutputP); + + if (pastRefFrameP) { + processBFrames(pastRefFrameP, frameP, realStart, realEnd, + inputSourceP, remoteIO, childProcess, + &IOtime, bbP, outputFileName, + framesReadP, framesOutputP, ¤tGOP); + } + if (pastRefFrameP != NULL) + Frame_Free(pastRefFrameP); + + *newPastRefFramePP = frameP; + } else + *endOfStreamP = TRUE; + } +} + + + +void +GenMPEGStream(struct inputSource * const inputSourceP, + enum frameContext const context, + unsigned int const frameStart, + unsigned int const frameEnd, + int32 const qtable[], + int32 const niqtable[], + bool const childProcess, + FILE * const ofP, + const char * const outputFileName, + bool const wantVbvUnderflowWarning, + bool const wantVbvOverflowWarning, + unsigned int * const inputFrameBitsP, + unsigned int * const totalBitsP) { +/*---------------------------------------------------------------------------- + Encode a bunch of frames into an MPEG sequence stream or a part thereof. + + 'context' tells what in addition to the frames themselves must go into + the stream: + + CONTEXT_JUSTFRAMES: Nothing but the indicated frames + CONTEXT_GOP: GOP header/trailer stuff to make a single GOP + that contains the indicated frames + CONTEXT_WHOLESTREAM: A whole stream consisting of the indicated + frames -- a sequence of whole GOPS, with stream + header/trailer stuff as well. + + 'frameStart' and 'frameEnd' are the numbers of the first and last + frames we are to encode, except that if the input source is a stream, + we stop where the stream ends if that is before 'frameEnd'. + +-----------------------------------------------------------------------------*/ + BitBucket * bbP; + unsigned int frameNumber; + bool endOfStream; + bool firstFrameDone; + int numBits; + unsigned int firstFrame, lastFrame; + /* Frame numbers of the first and last frames we look at. This + could be more than the the frames we actually encode because + we may need context (i.e. to encode a B frame, we need the subsequent + I or P frame). + */ + unsigned int framesRead; + /* Number of frames we have read; for statistical purposes */ + MpegFrame * pastRefFrameP; + /* The frame that will be the past reference frame for the next + B or P frame that we put into the stream + */ + if (frameEnd + 1 > inputSourceP->numInputFiles) + pm_error("Last frame (number %u) is beyond the end of the stream " + "(%u frames)", frameEnd, inputSourceP->numInputFiles); + + if (context == CONTEXT_WHOLESTREAM && + !inputSourceP->stdinUsed && + FType_Type(inputSourceP->numInputFiles-1) == 'b') + pm_message("WARNING: " + "One or more B-frames at end will not be encoded. " + "See FORCE_ENCODE_LAST_FRAME parameter file statement."); + + time(&timeStart); + + framesRead = 0; + + ResetIFrameStats(); + ResetPFrameStats(); + ResetBFrameStats(); + + Fsize_Reset(); + + framesOutput = 0; + + if (childProcess && separateConversion) + SetFileType(slaveConversion); + else + SetFileType(inputConversion); + + realStart = frameStart; + realEnd = frameEnd; + + computeFrameRange(frameStart, frameEnd, context, inputSourceP, + &firstFrame, &lastFrame); + + if (context == CONTEXT_GOP && FType_Type(frameStart) == 'b') + getPreviousFrame(frameStart, referenceFrame, inputSourceP, + childProcess, slaveConversion, inputConversion, + &pastRefFrameP, &framesRead, &IOtime); + else + pastRefFrameP = NULL; + + countFrames(firstFrame, lastFrame, inputSourceP->stdinUsed, + &numI, &numP, &numB, &timeMask, &frameCountsUnknown); + + if (showBitRatePerFrame) + OpenBitRateFile(); /* May modify showBitRatePerFrame */ + + if (context == CONTEXT_WHOLESTREAM) + bbP = Bitio_New(ofP); + else + bbP = NULL; + + initTCTime(firstFrame); + + totalFramesSent = firstFrame; + currentGOP = gopSize; /* so first I-frame generates GOP Header */ + + initializeRateControl(wantVbvUnderflowWarning, wantVbvOverflowWarning); + + firstFrameDone = FALSE; + for (frameNumber = firstFrame, endOfStream = FALSE; + frameNumber <= lastFrame && !endOfStream; + ++frameNumber) { + + doAFrame(frameNumber, inputSourceP, context, + frameStart, frameEnd, realStart, realEnd, + childProcess, outputFileName, + pastRefFrameP, &pastRefFrameP, + &framesRead, &framesOutput, &firstFrameDone, bbP, + inputFrameBitsP, &endOfStream); + } + + if (pastRefFrameP != NULL) + Frame_Free(pastRefFrameP); + + /* SEQUENCE END CODE */ + if (context == CONTEXT_WHOLESTREAM) + Mhead_GenSequenceEnder(bbP); + + if (context == CONTEXT_WHOLESTREAM) + numBits = bbP->cumulativeBits; + else { + /* What should the correct value be? Most likely 1. "numBits" is + used below, so we need to make sure it's properly initialized + to somthing (anything). + */ + numBits = 1; + } + + if (context != CONTEXT_JUSTFRAMES) { + Bitio_Flush(bbP); + bbP = NULL; + fclose(ofP); + } + handleBitRate(realEnd, numBits, childProcess, showBitRatePerFrame); + + *totalBitsP = numBits; +} + + + +/*===========================================================================* + * + * SetStatFileName + * + * set the statistics file name + * + * RETURNS: nothing + * + * SIDE EFFECTS: statFileName + * + *===========================================================================*/ +void +SetStatFileName(const char * const fileName) { + strcpy(statFileName, fileName); +} + + +/*===========================================================================* + * + * SetGOPSize + * + * set the GOP size (frames per GOP) + * + * RETURNS: nothing + * + * SIDE EFFECTS: gopSize + * + *===========================================================================*/ +void +SetGOPSize(size) + int size; +{ + gopSize = size; +} + + +/*===========================================================================* + * + * PrintStartStats + * + * print out the starting statistics (stuff from the param file) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +PrintStartStats(time_t const startTime, + bool const specificFrames, + unsigned int const firstFrame, + unsigned int const lastFrame, + struct inputSource * const inputSourceP) { + + FILE *fpointer; + int i; + + if (statFileName[0] == '\0') { + statFile = NULL; + } else { + statFile = fopen(statFileName, "a"); /* open for appending */ + if (statFile == NULL) { + fprintf(stderr, "ERROR: Could not open stat file: %s\n", + statFileName); + fprintf(stderr, " Sending statistics to stdout only.\n"); + fprintf(stderr, "\n\n"); + } else if (! realQuiet) { + fprintf(stdout, "Appending statistics to file: %s\n", + statFileName); + fprintf(stdout, "\n\n"); + } + } + + for (i = 0; i < 2; ++i) { + if ( ( i == 0 ) && (! realQuiet) ) { + fpointer = stdout; + } else if ( statFile != NULL ) { + fpointer = statFile; + } else { + continue; + } + + fprintf(fpointer, "MPEG ENCODER STATS (%s)\n",VERSION); + fprintf(fpointer, "------------------------\n"); + fprintf(fpointer, "TIME STARTED: %s", ctime(&startTime)); + if (getenv("HOST") != NULL) + fprintf(fpointer, "MACHINE: %s\n", getenv("HOST")); + else + fprintf(fpointer, "MACHINE: unknown\n"); + + if (inputSourceP->stdinUsed) + fprintf(fpointer, "INPUT: stdin\n"); + else { + const char * inputFileName; + + fprintf(fpointer, "INPUT FROM FILES:\n"); + + GetNthInputFileName(inputSourceP, 0, &inputFileName); + fprintf(fpointer, "FIRST FILE: %s/%s\n", + currentPath, inputFileName); + strfree(inputFileName); + GetNthInputFileName(inputSourceP, inputSourceP->numInputFiles-1, + &inputFileName); + fprintf(fpointer, "LAST FILE: %s/%s\n", + currentPath, inputFileName); + strfree(inputFileName); + } + fprintf(fpointer, "OUTPUT: %s\n", outputFileName); + + if (resizeFrame) + fprintf(fpointer, "RESIZED TO: %dx%d\n", + outputWidth, outputHeight); + fprintf(fpointer, "PATTERN: %s\n", framePattern); + fprintf(fpointer, "GOP_SIZE: %d\n", gopSize); + fprintf(fpointer, "SLICES PER FRAME: %d\n", slicesPerFrame); + if (searchRangeP==searchRangeB) + fprintf(fpointer, "RANGE: +/-%d\n", searchRangeP/2); + else fprintf(fpointer, "RANGES: +/-%d %d\n", + searchRangeP/2,searchRangeB/2); + fprintf(fpointer, "PIXEL SEARCH: %s\n", + pixelFullSearch ? "FULL" : "HALF"); + fprintf(fpointer, "PSEARCH: %s\n", PSearchName()); + fprintf(fpointer, "BSEARCH: %s\n", BSearchName()); + fprintf(fpointer, "QSCALE: %d %d %d\n", qscaleI, + GetPQScale(), GetBQScale()); + if (specificsOn) + fprintf(fpointer, "(Except as modified by Specifics file)\n"); + if ( referenceFrame == DECODED_FRAME ) { + fprintf(fpointer, "REFERENCE FRAME: DECODED\n"); + } else if ( referenceFrame == ORIGINAL_FRAME ) { + fprintf(fpointer, "REFERENCE FRAME: ORIGINAL\n"); + } else + pm_error("Illegal referenceFrame!!!"); + + /* For new Rate control parameters */ + if (getRateMode() == FIXED_RATE) { + fprintf(fpointer, "PICTURE RATE: %d\n", frameRateRounded); + if (getBitRate() != -1) { + fprintf(fpointer, "\nBIT RATE: %d\n", getBitRate()); + } + if (getBufferSize() != -1) { + fprintf(fpointer, "BUFFER SIZE: %d\n", getBufferSize()); + } + } + } + if (!realQuiet) + fprintf(stdout, "\n\n"); +} + + + +boolean +NonLocalRefFrame(int const id) { +/*---------------------------------------------------------------------------- + Return TRUE if frame number 'id' might be referenced from a non-local + process. This is a conservative estimate. We return FALSE iff there + is no way based on the information we have that the frame could be + referenced by a non-local process. +-----------------------------------------------------------------------------*/ + boolean retval; + + int const lastIPid = FType_PastRef(id); + + /* might be accessed by B-frame */ + + if (lastIPid+1 < realStart) + retval = TRUE; + else { + unsigned int const nextIPid = FType_FutureRef(id); + + /* if B-frame is out of range, then current frame can be + ref'd by it + */ + + /* might be accessed by B-frame */ + if (nextIPid > realEnd+1) + retval = TRUE; + + /* might be accessed by P-frame */ + if ((nextIPid > realEnd) && (FType_Type(nextIPid) == 'p')) + retval = TRUE; + } + return retval; +} + + + +/*===========================================================================* + * + * SetFrameRate + * + * sets global frame rate variables. value passed is MPEG frame rate code. + * + * RETURNS: TRUE or FALSE + * + * SIDE EFFECTS: frameRateRounded, frameRateInteger + * + *===========================================================================*/ +void +SetFrameRate() +{ + switch(frameRate) { + case 1: + frameRateRounded = 24; + frameRateInteger = FALSE; + break; + case 2: + frameRateRounded = 24; + frameRateInteger = TRUE; + break; + case 3: + frameRateRounded = 25; + frameRateInteger = TRUE; + break; + case 4: + frameRateRounded = 30; + frameRateInteger = FALSE; + break; + case 5: + frameRateRounded = 30; + frameRateInteger = TRUE; + break; + case 6: + frameRateRounded = 50; + frameRateInteger = TRUE; + break; + case 7: + frameRateRounded = 60; + frameRateInteger = FALSE; + break; + case 8: + frameRateRounded = 60; + frameRateInteger = TRUE; + break; + } + printf("frame rate(%d) set to %d\n", frameRate, frameRateRounded); +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * ComputeDHMSTime + * + * turn some number of seconds (someTime) into a string which + * summarizes that time according to scale (days, hours, minutes, or + * seconds) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ComputeDHMSTime(someTime, timeText) + int32 someTime; + char *timeText; +{ + int days, hours, mins, secs; + + days = someTime / (24*60*60); + someTime -= days*24*60*60; + hours = someTime / (60*60); + someTime -= hours*60*60; + mins = someTime / 60; + secs = someTime - mins*60; + + if ( days > 0 ) { + sprintf(timeText, "Total time: %d days and %d hours", days, hours); + } else if ( hours > 0 ) { + sprintf(timeText, "Total time: %d hours and %d minutes", hours, mins); + } else if ( mins > 0 ) { + sprintf(timeText, "Total time: %d minutes and %d seconds", mins, secs); + } else { + sprintf(timeText, "Total time: %d seconds", secs); + } +} + + + +void +ComputeGOPFrames(int const whichGOP, + unsigned int * const firstFrameP, + unsigned int * const lastFrameP, + unsigned int const numFrames) { +/*---------------------------------------------------------------------------- + Figure out which frames are in GOP number 'whichGOP'. +-----------------------------------------------------------------------------*/ + unsigned int passedB; + unsigned int currGOP; + unsigned int gopNum; + unsigned int frameNum; + unsigned int firstFrame, lastFrame; + bool foundGop; + + /* calculate first, last frames of whichGOP GOP */ + + gopNum = 0; + frameNum = 0; + passedB = 0; + currGOP = 0; + foundGop = FALSE; + + while (!foundGop) { + if (frameNum >= numFrames) + pm_error("There aren't that many GOPs!"); + + if (gopNum == whichGOP) { + foundGop = TRUE; + firstFrame = frameNum; + } + + /* go past one gop */ + /* must go past at least one frame */ + do { + currGOP += (1 + passedB); + + ++frameNum; + + passedB = 0; + while ((frameNum < numFrames) && (FType_Type(frameNum) == 'b')) { + ++frameNum; + ++passedB; + } + } while ((frameNum < numFrames) && + ((FType_Type(frameNum) != 'i') || (currGOP < gopSize))); + + currGOP -= gopSize; + + if (gopNum == whichGOP) + lastFrame = (frameNum - passedB - 1); + + ++gopNum; + } + *firstFrameP = firstFrame; + *lastFrameP = lastFrame; +} + + + +static void +doEndStats(FILE * const fpointer, + time_t const startTime, + time_t const endTime, + unsigned int const inputFrameBits, + unsigned int const totalBits, + float const totalCPU) { + + int32 const diffTime = endTime - startTime; + + char timeText[256]; + + ComputeDHMSTime(diffTime, timeText); + + fprintf(fpointer, "TIME COMPLETED: %s", ctime(&endTime)); + fprintf(fpointer, "%s\n\n", timeText); + + ShowIFrameSummary(inputFrameBits, totalBits, fpointer); + ShowPFrameSummary(inputFrameBits, totalBits, fpointer); + ShowBFrameSummary(inputFrameBits, totalBits, fpointer); + + fprintf(fpointer, "---------------------------------------------\n"); + fprintf(fpointer, "Total Compression: %3d:1 (%9.4f bpp)\n", + framesOutput*inputFrameBits/totalBits, + 24.0*(float)(totalBits)/(float)(framesOutput*inputFrameBits)); + if (diffTime > 0) { + fprintf(fpointer, "Total Frames Per Sec Elapsed: %f (%ld mps)\n", + (float)framesOutput/(float)diffTime, + (long)((float)framesOutput * + (float)inputFrameBits / + (256.0*24.0*(float)diffTime))); + } else { + fprintf(fpointer, "Total Frames Per Sec Elapsed: Infinite!\n"); + } + if ( totalCPU == 0.0 ) { + fprintf(fpointer, "CPU Time: NONE!\n"); + } else { + fprintf(fpointer, "Total Frames Per Sec CPU : %f (%ld mps)\n", + (float)framesOutput/totalCPU, + (long)((float)framesOutput * + (float)inputFrameBits/(256.0*24.0*totalCPU))); + } + fprintf(fpointer, "Total Output Bit Rate (%d fps): %d bits/sec\n", + frameRateRounded, frameRateRounded*totalBits/framesOutput); + fprintf(fpointer, "MPEG file created in : %s\n", outputFileName); + fprintf(fpointer, "\n\n"); + + if ( computeMVHist ) { + ShowPMVHistogram(fpointer); + ShowBBMVHistogram(fpointer); + ShowBFMVHistogram(fpointer); + } +} + + + +/*===========================================================================* + * + * PrintEndStats + * + * print end statistics (summary, time information) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +PrintEndStats(time_t const startTime, + time_t const endTime, + unsigned int const inputFrameBits, + unsigned int const totalBits) { + + float totalCPU; + + totalCPU = 0.0; + totalCPU += IFrameTotalTime(); + totalCPU += PFrameTotalTime(); + totalCPU += BFrameTotalTime(); + + if (!realQuiet) { + fprintf(stdout, "\n\n"); + doEndStats(stdout, startTime, endTime, inputFrameBits, + totalBits, totalCPU); + } + + if (statFile) { + doEndStats(statFile, startTime, endTime, inputFrameBits, + totalBits, totalCPU); + + fclose(statFile); + } +} + + + +void +ReadDecodedRefFrame(MpegFrame * const frameP, + unsigned int const frameNumber) { + + FILE *fpointer; + char fileName[256]; + int width, height; + register int y; + + width = Fsize_x; + height = Fsize_y; + + sprintf(fileName, "%s.decoded.%u", outputFileName, frameNumber); + if (! realQuiet) { + fprintf(stdout, "reading %s\n", fileName); + fflush(stdout); + } + + if ((fpointer = fopen(fileName, "rb")) == NULL) { + sleep(1); + if ((fpointer = fopen(fileName, "rb")) == NULL) { + fprintf(stderr, "Cannot open %s\n", fileName); + exit(1); + }} + + Frame_AllocDecoded(frameP, TRUE); + + for ( y = 0; y < height; y++ ) { + size_t bytesRead; + + bytesRead = fread(frameP->decoded_y[y], 1, width, fpointer); + if (bytesRead != width) + pm_error("Could not read enough bytes from '%s;", fileName); + } + + for (y = 0; y < (height >> 1); y++) { /* U */ + size_t const bytesToRead = width/2; + size_t bytesRead; + + bytesRead = fread(frameP->decoded_cb[y], 1, bytesToRead, fpointer); + if (bytesRead != bytesToRead) + pm_message("Could not read enough bytes from '%s'", fileName); + } + + for (y = 0; y < (height >> 1); y++) { /* V */ + size_t const bytesToRead = width/2; + size_t bytesRead; + bytesRead = fread(frameP->decoded_cr[y], 1, bytesToRead, fpointer); + if (bytesRead != bytesToRead) + pm_message("Could not read enough bytes from '%s'", fileName); + } + fclose(fpointer); +} + + + +static void +OpenBitRateFile() { + bitRateFile = fopen(bitRateFileName, "w"); + if ( bitRateFile == NULL ) { + pm_message("ERROR: Could not open bit rate file: '%s'", + bitRateFileName); + showBitRatePerFrame = FALSE; + } +} + + + +static void +CloseBitRateFile() { + fclose(bitRateFile); +} diff --git a/converter/ppm/ppmtompeg/mquant.c b/converter/ppm/ppmtompeg/mquant.c new file mode 100644 index 00000000..1f8ca63a --- /dev/null +++ b/converter/ppm/ppmtompeg/mquant.c @@ -0,0 +1,44 @@ +#include "mtypes.h" +#include "mproto.h" + +static int qtable[][8] = { + { 8,16,19,22,26,27,29,34}, + {16,16,22,24,27,29,34,37}, + {19,22,26,27,29,34,34,38}, + {22,22,26,27,29,34,37,40}, + {22,26,27,29,32,35,40,48}, + {26,27,29,32,35,40,48,58}, + {26,27,29,34,38,46,56,69}, + {27,29,35,38,46,56,69,83} }; + + +/* + *-------------------------------------------------------------- + * + * mp_quant_block -- + * + * Quantizes a block -- removing information + * It's safe for out == in. + * + * Results: + * None. + * + * Side effects: + * Modifies the out block. + * + *-------------------------------------------------------------- + */ +void mp_quant_block(Block in, Block out) { + int i; + + for(i=0;i<8;i++) { + out[i][0] = in[i][0] / qtable[i][0]; + out[i][1] = in[i][1] / qtable[i][1]; + out[i][2] = in[i][2] / qtable[i][2]; + out[i][3] = in[i][3] / qtable[i][3]; + out[i][4] = in[i][4] / qtable[i][4]; + out[i][5] = in[i][5] / qtable[i][5]; + out[i][6] = in[i][6] / qtable[i][6]; + out[i][7] = in[i][7] / qtable[i][7]; + } +} diff --git a/converter/ppm/ppmtompeg/nojpeg.c b/converter/ppm/ppmtompeg/nojpeg.c new file mode 100644 index 00000000..38c05a9e --- /dev/null +++ b/converter/ppm/ppmtompeg/nojpeg.c @@ -0,0 +1,61 @@ +/*===========================================================================* + * nojpeg.c * + * * + * procedures to deal with JPEG files * + * * + * EXPORTED PROCEDURES: * + * JMovie2JPEG * + * ReadJPEG * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "readframe.h" +#include "fsize.h" +#include "rgbtoycc.h" +#include "jpeg.h" + + +void +JMovie2JPEG(const char * const infilename, + const char * const obase, + int const start, + int const end) { + + pm_error("This program has not been built with the " + "ability to handle JPEG input files"); +} + + +void +ReadJPEG(MpegFrame * const mf, + FILE * const fp) { + + pm_error("This program has not been built with the " + "ability to handle JPEG input files"); +} diff --git a/converter/ppm/ppmtompeg/noparallel.c b/converter/ppm/ppmtompeg/noparallel.c new file mode 100644 index 00000000..016e3c44 --- /dev/null +++ b/converter/ppm/ppmtompeg/noparallel.c @@ -0,0 +1,229 @@ +/*===========================================================================* + * noparallel.c + * + * Would be procedures to make encoder to run in parallel -- except + * this machine doesn't have sockets, so we can only run sequentially + * so this file has dummy procedures which lets it compile + * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <time.h> + +#include <pm.h> + +#include "all.h" +#include "mtypes.h" +#include "parallel.h" +#include "frame.h" + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +int parallelTestFrames = 10; +int parallelTimeChunks = 60; +const char *IOhostName; +int ioPortNumber; +int combinePortNumber; +int decodePortNumber; +boolean niceProcesses = FALSE; +boolean forceIalign = FALSE; +int machineNumber = -1; +boolean remoteIO = FALSE; +boolean separateConversion; +time_t IOtime = 0; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*=================* + * IO SERVER STUFF * + *=================*/ + + +void +IoServer(struct inputSource * const inputSourceP, + const char * const parallelHostName, + int const portNum) { + + pm_error("This version of Ppmtompeg cannot run an I/O server because " + "it does not have socket capability."); +} + + + +void +SetIOConvert(boolean const separate) { + /* do nothing -- this may be called during non-parallel execution */ +} + + + +void +SetParallelPerfect(boolean const val) { + /* do nothing -- this may be called during non-parallel execution */ +} + + +void +SetRemoteShell(const char * const shell) { + /* do nothing -- this may be called during non-parallel execution */ +} + + + +void +NoteFrameDone(int const frameStart, + int const frameEnd) { + fprintf(stdout, + "ERROR: (NoteFrameDone) " + "This machine can NOT run parallel version\n"); + exit(1); +} + + + +/* SendRemoteFrame + */ +void +SendRemoteFrame(int const frameNumber, + BitBucket * const bb) { + fprintf(stdout, "ERROR: (SendRemoteFrame) " + "This machine can NOT run parallel version\n"); + exit(1); +} + + + +/* GetRemoteFrame + */ +void +GetRemoteFrame(MpegFrame * const frame, + int const frameNumber) { + + fprintf(stdout, "ERROR: (GetRemoteFrame) " + "This machine can NOT run parallel version\n"); + exit(1); +} + + + +void +WaitForOutputFile(int const number) { + fprintf(stdout, "ERROR: (WaitForOutputFile) " + "This machine can NOT run parallel version\n"); + exit(1); +} + + + +/*=======================* + * PARALLEL SERVER STUFF * + *=======================*/ + + +void +MasterServer(struct inputSource * const inputSourceP, + const char * const paramFileName, + const char * const outputFileName) { + + pm_error("This version of Ppmtompeg cannot run a master server because " + "it does not have socket capability."); +} + + + +void +CombineServer(int const numFrames, + const char * const masterHostName, + int const masterPortNum) { + + pm_error("This version of Ppmtompeg cannot run combine server because " + "it does not have socket capability."); +} + + + +void +DecodeServer(int const numInputFiles, + const char * const decodeFileName, + const char * const masterHostName, + int const masterPortNum) { + + pm_error("This version of Ppmtompeg cannot run a decode server because " + "it does not have socket capability."); +} + + + +void +NotifyMasterDone(const char * const hostName, + int const portNum, + int const machineNumber, + unsigned int const seconds, + boolean * const moreWorkToDoP, + int * const frameStartP, + int * const frameEndP) { + pm_error("This version of Ppmtompeg cannot run parallel mode because " + "it does not have socket capability."); +} + + + +void +NotifyDecodeServerReady(int const id) { + pm_error("This version of Ppmtompeg cannot run parallel mode because " + "it does not have socket capability."); +} + + + +void +WaitForDecodedFrame(int const id) { + pm_error("This version of Ppmtompeg cannot run parallel mode because " + "it does not have socket capability."); +} + + + +void +SendDecodedFrame(MpegFrame * const frame) { + pm_error("This version of Ppmtompeg cannot run parallel mode because " + "it does not have socket capability."); +} + + + +void +GetRemoteDecodedRefFrame(MpegFrame * const frame, + int const frameNumber) { + pm_error("This version of Ppmtompeg cannot run parallel mode because " + "it does not have socket capability."); +} diff --git a/converter/ppm/ppmtompeg/opts.c b/converter/ppm/ppmtompeg/opts.c new file mode 100644 index 00000000..c4d0c0b3 --- /dev/null +++ b/converter/ppm/ppmtompeg/opts.c @@ -0,0 +1,536 @@ +/*===========================================================================* + * opts.c * + * * + * Special C code to handle TUNEing options * + * * + * EXPORTED PROCEDURES: * + * Tune_Init * + * CollectQuantStats * + * * + *===========================================================================*/ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include "opts.h" + +/*==============* + * EXTERNALS * + *==============*/ + +extern char outputFileName[]; +extern boolean pureDCT; +extern int32 qtable[], niqtable[]; +extern int ZAG[]; +extern boolean printSNR, decodeRefFrames; + +void init_idctref _ANSI_ARGS_((void)); +void init_fdct _ANSI_ARGS_((void)); + + +/*===================* + * GLOBALS MADE HERE * + *===================*/ + +boolean tuneingOn = FALSE; +int block_bound = 128; +boolean collect_quant = FALSE; +int collect_quant_detailed = 0; +FILE *collect_quant_fp; +int kill_dim = FALSE; +int kill_dim_break, kill_dim_end; +float kill_dim_slope; +int SearchCompareMode = DEFAULT_SEARCH; +boolean squash_small_differences = FALSE; +int SquashMaxLum, SquashMaxChr; +float LocalDCTRateScale = 1.0, LocalDCTDistortScale = 1.0; +boolean IntraPBAllowed = TRUE; +boolean WriteDistortionNumbers = FALSE; +int collect_distortion_detailed = 0; +FILE *distortion_fp; +FILE *fp_table_rate[31], *fp_table_dist[31]; +boolean DoLaplace = FALSE; +double **L1, **L2, **Lambdas; +int LaplaceNum, LaplaceCnum; +boolean BSkipBlocks = TRUE; + +/* define this as it too much of a pain to find toupper on different arch'es */ +#define ASCII_TOUPPER(c) ((c>='a') && (c<='z')) ? c-'a'+'A' : c + +/*===============* + * Internals * + *===============*/ + +/*===========================================================================* + * + * SkipSpacesTabs + * + * skip all spaces and tabs + * + * RETURNS: point to next character not a space or tab + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static const char * +SkipSpacesTabs(const char * const start) { + + const char * p; + + for (p = start; *p == ' ' || *p == '\t'; ++p); + + return p; +} + + + +/*===========================================================================* + * + * SetupCollectQuantStats + * + * Setup variables to collect statistics on quantization values + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets collect_quant and collect_quant_fp + * + *===========================================================================*/ +static void +SetupCollectQuantStats(const char * const charPtr) +{ + char fname[256]; + const char * cp; + cp = charPtr; + while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) { + cp++; + } + + strncpy(fname, charPtr, cp-charPtr); + fname[cp-charPtr] = '\0'; + collect_quant = TRUE; + if ((collect_quant_fp = fopen(fname,"w")) == NULL) { + fprintf(stderr, "Error opening %s for quant statistics\n", fname); + fprintf(stderr, "Using stdout (ick!)\n"); + collect_quant_fp = stdout; + } + + cp = SkipSpacesTabs(cp); + if (*cp != '\n') { + switch (*cp) { + case 'c': + collect_quant_detailed = 1; + break; + default: + fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp); + }} +} + + + + +/*===========================================================================* + * + * SetupKillDimAreas + * + * Do a transform on small lum values + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets kill_dim, kill_dim_break, kill_dim_end + * + *===========================================================================*/ +static void +SetupKillDimAreas(const char * const charPtr) +{ + int items_scanned; + + kill_dim = TRUE; + items_scanned = sscanf(charPtr, "%d %d %f", + &kill_dim_break, &kill_dim_end, &kill_dim_slope); + if (items_scanned != 3) { + kill_dim_slope = 0.25; + items_scanned = sscanf(charPtr, "%d %d", + &kill_dim_break, &kill_dim_end); + if (items_scanned != 2) { + /* Use defaults */ + kill_dim_break = 20; + kill_dim_end = 25; + } + } + /* check values */ + if (kill_dim_break > kill_dim_end) { + fprintf(stderr, "TUNE parameter k: break > end is illegal.\n"); + exit(-1); + } + if (kill_dim_slope < 0) { + fprintf(stderr, "TUNE parameter k: slope < 0 is illegal.\n"); + exit(-1); + } +} + + + +/*===========================================================================* + * + * SetupSquashSmall + * + * Setup encoder to squash small changes in Y or Cr/Cb values + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets squash_max_differences SquashMaxLum SquashMaxChr + * + *===========================================================================*/ +static void +SetupSquashSmall(const char * const charPtr) +{ + squash_small_differences = TRUE; + + if (sscanf(charPtr, "%d %d", &SquashMaxLum, &SquashMaxChr) == 1) { + /* Only set one, do both */ + SquashMaxChr = SquashMaxLum; + } +} + + +/*===========================================================================* + * + * SetupLocalDCT + * + * Setup encoder to use DCT for rate-distortion estimat ein Psearches + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets SearchCompareMode and + * can change LocalDCTRateScale, LocalDCTDistortScale + * + *===========================================================================*/ +static void +SetupLocalDCT(const char * const charPtr) +{ + int num_scales=0; + + SearchCompareMode = LOCAL_DCT; + + /* Set scaling factors if present */ + num_scales = sscanf(charPtr, "%f %f", &LocalDCTRateScale, &LocalDCTDistortScale); + if (num_scales == 1) { + fprintf(stderr, "Invalid number of scaling factors for local DCT\n"); + fprintf(stderr, "Must specify Rate Scale and Distorion scale (both floats)\n"); + fprintf(stderr, "Continuing with 1.0 1.0\n"); + LocalDCTRateScale = 1.0; + LocalDCTDistortScale = 1.0; + } +} + + +/*===========================================================================* + * + * SetupLaplace + * + * Setup encoder to find distrubution for I-frames, and use for -snr + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets DoLaplace, L1, L2, and Lambdas + * + *===========================================================================*/ +static void +SetupLaplace() +{ + int i; + + DoLaplace = TRUE; + LaplaceNum = 0; + L1 = (double **)malloc(sizeof(double *)*3); + L2 = (double **)malloc(sizeof(double *)*3); + Lambdas = (double **)malloc(sizeof(double *)*3); + if (L1 == NULL || L2 == NULL || Lambdas == NULL) { + fprintf(stderr,"Out of memory!!!\n"); + exit(1); + } + for (i = 0; i < 3; i++) { + L1[i] = (double *)calloc(64, sizeof(double)); + L2[i] = (double *)calloc(64, sizeof(double)); + Lambdas[i] = (double *)malloc(sizeof(double) * 64); + if (L1[i] == NULL || L2[i] == NULL || Lambdas[i] == NULL) { + fprintf(stderr,"Out of memory!!!\n"); + exit(1); + } + } +} + +static void +SetupWriteDistortions(const char * const charPtr) +{ + char fname[256]; + const char * cp; + int i; + + WriteDistortionNumbers = TRUE; + cp = charPtr; + while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) { + cp++; + } + + strncpy(fname, charPtr, cp-charPtr); + fname[cp-charPtr] = '\0'; + collect_quant = TRUE; + if ((distortion_fp = fopen(fname,"w")) == NULL) { + fprintf(stderr, "Error opening %s for quant statistics\n", fname); + fprintf(stderr, "Using stdout (ick!)\n"); + distortion_fp = stdout; + } + + cp = SkipSpacesTabs(cp); + if (*cp != '\n') { + switch (*cp) { + case 'c': + collect_distortion_detailed = TRUE; + break; + case 't': { + char scratch[256]; + collect_distortion_detailed = 2; + for (i = 1; i < 32; i++) { + sprintf(scratch, "%srate%d", fname, i); + fp_table_rate[i-1] = fopen(scratch, "w"); + sprintf(scratch, "%sdist%d", fname, i); + fp_table_dist[i-1] = fopen(scratch, "w"); + }} + break; + default: + fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp); + }} +} + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +void +CalcLambdas(void) { + + int i,j,n; + double var; + + n = LaplaceNum; + for (i = 0; i < 3; i++) { + for (j = 0; j < 64; j++) { + var = (n*L1[i][j] + L2[i][j]*L2[i][j]) / (n*(n-1)); + Lambdas[i][j] = sqrt(2.0) / sqrt(var); + } + } +} + + +/*===========================================================================* + * + * Mpost_UnQuantZigBlockLaplace + * + * unquantize and zig-zag (decode) a single block, using the distrib to get vals + * Iblocks only now + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_UnQuantZigBlockLaplace(in, out, qscale, iblock) + FlatBlock in; + Block out; + int qscale; + boolean iblock; +{ + register int index; + int position; + register int qentry; + int level, coeff; + double low, high; + double mid,lam; + + /* qtable[0] must be 8 */ + out[0][0] = (int16)(in[0] * 8); + + for ( index = 1; index < DCTSIZE_SQ; index++ ) { + position = ZAG[index]; + level = in[index]; + + if (level == 0) { + ((int16 *)out)[position] = 0; + continue; + } + qentry = qtable[position] * qscale; + coeff = (level*qentry)/8; + low = ((ABS(level)-.5)*qentry)/8; + high = ((ABS(level)+.5)*qentry)/8; + lam = Lambdas[LaplaceCnum][position]; + mid = (1.0/lam) * log(0.5*(exp(-lam*low)+exp(-lam*high))); + mid = ABS(mid); + if (mid - floor(mid) > .4999) { + mid = ceil(mid); + } else { + mid = floor(mid); + } + if (level<0) {mid = -mid;} +/*printf("(%2.1lf-%2.1lf): old: %d vs %d\n",low,high,coeff,(int) mid);*/ + coeff = mid; + if ( (coeff & 1) == 0 ) { + if ( coeff < 0 ) { + coeff++; + } else if ( coeff > 0 ) { + coeff--; + } + } + ((int16 *)out)[position] = coeff; + } +} + +int +mse(Block blk1, Block blk2) +{ + register int index, error, tmp; + int16 *bp1, *bp2; + + bp1 = (int16 *)blk1; + bp2 = (int16 *)blk2; + error = 0; + for ( index = 0; index < DCTSIZE_SQ; index++ ) { + tmp = *bp1++ - *bp2++; + error += tmp*tmp; + } + return error; +} + + + + +/*===========================================================================* + * + * Tune_Init + * + * Do any setup needed before coding stream + * + * RETURNS: nothing + * + * SIDE EFFECTS: varies + * + *===========================================================================*/ +void Tune_Init() +{ + int i; + + /* Just check for each, and do whats needed */ + if (collect_quant) { + if (!pureDCT) { + pureDCT = TRUE; + init_idctref(); + init_fdct(); + } + fprintf(collect_quant_fp, "# %s\n", outputFileName); + fprintf(collect_quant_fp, "#"); + for (i=0; i<64; i++) + fprintf(collect_quant_fp, " %d", qtable[i]); + fprintf(collect_quant_fp, "\n#"); + for (i=0; i<64; i++) + fprintf(collect_quant_fp, " %d", niqtable[i]); + fprintf(collect_quant_fp, "\n# %d %d %d\n\n", + GetIQScale(), GetPQScale(), GetBQScale()); + + } + + if (DoLaplace) { + if (!pureDCT) { + pureDCT = TRUE; + init_idctref(); + init_fdct(); + } + decodeRefFrames = TRUE; + printSNR = TRUE; + } + +} + +/*===========================================================================* + * + * ParseTuneParam + * + * Handle the strings following TUNE + * + * RETURNS: nothing + * + * SIDE EFFECTS: varies + * + *===========================================================================*/ +void ParseTuneParam(const char * const charPtr) +{ + switch (ASCII_TOUPPER(*charPtr)) { + case 'B': + if (1 != sscanf(charPtr+2, "%d", &block_bound)) { + fprintf(stderr, "Invalid tuning parameter (b) in parameter file.\n"); + } + break; + case 'C': + SetupCollectQuantStats(charPtr+2); + break; + case 'D': + SetupLocalDCT(SkipSpacesTabs(charPtr+1)); + break; + case 'K': + SetupKillDimAreas(SkipSpacesTabs(charPtr+1)); + break; + case 'L': + SetupLaplace(); + break; + case 'N': + SearchCompareMode = NO_DC_SEARCH; + break; + case 'Q': + SearchCompareMode = DO_Mean_Squared_Distortion; + break; + case 'S': + SetupSquashSmall(SkipSpacesTabs(charPtr+1)); + break; + case 'W': + SetupWriteDistortions(SkipSpacesTabs(charPtr+1)); + break; + case 'U': + BSkipBlocks = FALSE; + break; + case 'Z': + IntraPBAllowed = FALSE; + break; + default: + fprintf(stderr, "Unknown tuning (%s) in parameter file.\n",charPtr); + break; + } +} + + diff --git a/converter/ppm/ppmtompeg/parallel.c b/converter/ppm/ppmtompeg/parallel.c new file mode 100644 index 00000000..021e6d2b --- /dev/null +++ b/converter/ppm/ppmtompeg/parallel.c @@ -0,0 +1,2278 @@ +/*===========================================================================* + * parallel.c + * + * Procedures to make encoder run in parallel + * + *===========================================================================*/ + +/* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#define _XOPEN_SOURCE 500 /* Make sure stdio.h contains pclose() */ +/* _ALL_SOURCE is needed on AIX to make the C library include the + socket services (e.g. define struct sockaddr) + + Note that AIX standards.h actually sets feature declaration macros such + as _XOPEN_SOURCE, unless they are already set. +*/ +#define _ALL_SOURCE + +/* On AIX, pm_config.h includes standards.h, which expects to be included + after feature declaration macros such as _XOPEN_SOURCE. So we include + pm_config.h as late as possible. +*/ + + +#include <stdarg.h> +#include <time.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <signal.h> +#include <netdb.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/times.h> + +#include "mallocvar.h" +#include "nstring.h" + +#include "pm.h" + +#include "all.h" +#include "param.h" +#include "mpeg.h" +#include "prototypes.h" +#include "readframe.h" +#include "fsize.h" +#include "combine.h" +#include "frames.h" +#include "input.h" +#include "psocket.h" +#include "frametype.h" +#include "gethostname.h" + +#include "parallel.h" + + +struct childState { + boolean finished; + unsigned int startFrame; + unsigned int numFrames; + unsigned int lastNumFrames; + unsigned int numSeconds; + float fps; +}; + + +struct scheduler { + /* This tracks the state of the subsystem that determines the assignments + for the children + */ + unsigned int nextFrame; + /* The next frame that needs to be assigned to a child */ + unsigned int numFramesInJob; + /* Total number of frames in the whole run of Ppmtompeg */ + unsigned int numMachines; +}; + + + +#define MAX_IO_SERVERS 10 +#ifndef SOMAXCONN +#define SOMAXCONN 5 +#endif + +/*==================* + * CONSTANTS * + *==================*/ + +#define TERMINATE_PID_SIGNAL SIGTERM /* signal used to terminate forked childs */ +#ifndef MAXARGS +#define MAXARGS 1024 /* Max Number of arguments in safe_fork command */ +#endif + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static char rsh[256]; +static struct hostent *hostEntry = NULL; +static boolean *frameDone; +static int outputServerSocket; +static int decodeServerSocket; +static boolean parallelPerfect = FALSE; +static int current_max_forked_pid=0; + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int yuvHeight, yuvWidth; +extern char statFileName[256]; +extern FILE *statFile; +extern boolean debugMachines; +extern boolean debugSockets; +int parallelTestFrames = 10; +int parallelTimeChunks = 60; +const char *IOhostName; +int ioPortNumber; +int decodePortNumber; +boolean niceProcesses = FALSE; +boolean forceIalign = FALSE; +int machineNumber = -1; +boolean remoteIO = FALSE; +bool separateConversion; + /* The I/O server will convert from the input format to the base format, + and the slave will convert from the base format to the YUV internal + format. If false, the I/O server assumes the input format is the + base format and converts from the base format to the YUV internal + format; the slave does no conversion. + */ +time_t IOtime = 0; +extern char encoder_name[]; +int ClientPid[MAX_MACHINES+4]; + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + + +static void PM_GNU_PRINTF_ATTR(1,2) +machineDebug(const char format[], ...) { + + va_list args; + + va_start(args, format); + + if (debugMachines) { + const char * const hostname = GetHostName(); + fprintf(stderr, "%s: ---", hostname); + strfree(hostname); + vfprintf(stderr, format, args); + fputc('\n', stderr); + } + va_end(args); +} + + + +static void PM_GNU_PRINTF_ATTR(1,2) +errorExit(const char format[], ...) { + + const char * const hostname = GetHostName(); + + va_list args; + + va_start(args, format); + + fprintf(stderr, "%s: FATAL ERROR. ", hostname); + strfree(hostname); + vfprintf(stderr, format, args); + fputc('\n', stderr); + + exit(1); + + va_end(args); +} + + + +static void +TransmitPortNum(const char * const hostName, + int const portNum, + int const newPortNum) { +/*---------------------------------------------------------------------------- + Transmit the port number 'newPortNum' to the master on port 'portNum' + of host 'hostName'. +-----------------------------------------------------------------------------*/ + int clientSocket; + const char * error; + + ConnectToSocket(hostName, portNum, &hostEntry, &clientSocket, &error); + + if (error) + errorExit("Can't connect in order to transmit port number. %s", + error); + + WriteInt(clientSocket, newPortNum); + + close(clientSocket); +} + + + +static void +readYUVDecoded(int const socketFd, + unsigned int const Fsize_x, + unsigned int const Fsize_y, + MpegFrame * const frameP) { + + unsigned int y; + + for (y = 0; y < Fsize_y; ++y) /* Y */ + ReadBytes(socketFd, + (unsigned char *)frameP->decoded_y[y], Fsize_x); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* U */ + ReadBytes(socketFd, + (unsigned char *)frameP->decoded_cb[y], (Fsize_x >> 1)); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* V */ + ReadBytes(socketFd, + (unsigned char *)frameP->decoded_cr[y], (Fsize_x >> 1)); +} + + + +static void +writeYUVDecoded(int const socketFd, + unsigned int const Fsize_x, + unsigned int const Fsize_y, + MpegFrame * const frameP) { + + unsigned int y; + + for (y = 0; y < Fsize_y; ++y) /* Y */ + WriteBytes(socketFd, + (unsigned char *)frameP->decoded_y[y], Fsize_x); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* U */ + WriteBytes(socketFd, + (unsigned char *)frameP->decoded_cb[y], (Fsize_x >> 1)); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* V */ + WriteBytes(socketFd, + (unsigned char *)frameP->decoded_cr[y], (Fsize_x >> 1)); +} + + + +static void +writeYUVOrig(int const socketFd, + unsigned int const Fsize_x, + unsigned int const Fsize_y, + MpegFrame * const frameP) { + + unsigned int y; + + for (y = 0; y < Fsize_y; ++y) /* Y */ + WriteBytes(socketFd, + (unsigned char *)frameP->orig_y[y], Fsize_x); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* U */ + WriteBytes(socketFd, + (unsigned char *)frameP->orig_cb[y], (Fsize_x >> 1)); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* V */ + WriteBytes(socketFd, + (unsigned char *)frameP->orig_cr[y], (Fsize_x >> 1)); +} + + + +static void +readYUVOrig(int const socketFd, + unsigned int const Fsize_x, + unsigned int const Fsize_y, + MpegFrame * const frameP) { + + unsigned int y; + + for (y = 0; y < Fsize_y; ++y) /* Y */ + ReadBytes(socketFd, + (unsigned char *)frameP->orig_y[y], Fsize_x); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* U */ + ReadBytes(socketFd, + (unsigned char *)frameP->orig_cb[y], (Fsize_x >> 1)); + + for (y = 0; y < (Fsize_y >> 1); ++y) /* V */ + ReadBytes(socketFd, + (unsigned char *)frameP->orig_cr[y], (Fsize_x >> 1)); +} + + + +/*===========================================================================* + * + * EndIOServer + * + * called by the master process -- tells the I/O server to commit + * suicide + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void + EndIOServer() +{ + /* send signal to IO server: -1 as frame number */ + GetRemoteFrame(NULL, -1); +} + + +/*===========================================================================* + * + * NotifyDecodeServerReady + * + * called by a slave to the Decode Server to tell it a decoded frame + * is ready and waiting + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +NotifyDecodeServerReady(int const id) { + + int clientSocket; + time_t tempTimeStart, tempTimeEnd; + const char * error; + + time(&tempTimeStart); + + ConnectToSocket(IOhostName, decodePortNumber, &hostEntry, &clientSocket, + &error); + + if (error) + errorExit("CHILD: Can't connect to decode server to tell it a frame " + "is ready. %s", error); + + WriteInt(clientSocket, id); + + close(clientSocket); + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + + +/*===========================================================================* + * + * WaitForDecodedFrame + * + * blah blah blah + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void + WaitForDecodedFrame(id) +int id; +{ + int const negativeTwo = -2; + int clientSocket; + int ready; + const char * error; + + /* wait for a decoded frame */ + if ( debugSockets ) { + fprintf(stdout, "WAITING FOR DECODED FRAME %d\n", id); + } + + ConnectToSocket(IOhostName, decodePortNumber, &hostEntry, &clientSocket, + &error); + + if (error) + errorExit("CHILD: Can't connect to decode server " + "to get decoded frame. %s", + error); + + /* first, tell DecodeServer we're waiting for this frame */ + WriteInt(clientSocket, negativeTwo); + + WriteInt(clientSocket, id); + + ReadInt(clientSocket, &ready); + + if ( ! ready ) { + int waitSocket; + int waitPort; + int otherSock; + const char * error; + + /* it's not ready; set up a connection and wait for decode server */ + CreateListeningSocket(&waitSocket, &waitPort, &error); + if (error) + errorExit("Unable to create socket on which to listen for " + "decoded frame. %s", error); + + /* tell decode server where we are */ + WriteInt(clientSocket, machineNumber); + + WriteInt(clientSocket, waitPort); + + close(clientSocket); + + if ( debugSockets ) { + fprintf(stdout, "SLAVE: WAITING ON SOCKET %d\n", waitPort); + fflush(stdout); + } + + AcceptConnection(waitSocket, &otherSock, &error); + if (error) + errorExit("I/O SERVER: Failed to accept next connection. %s", error); + + /* should we verify this is decode server? */ + /* for now, we won't */ + + close(otherSock); + + close(waitSocket); + } else { + close(clientSocket); + } + + if ( debugSockets ) { + fprintf(stdout, "YE-HA FRAME %d IS NOW READY\n", id); + } +} + + +/*===========================================================================* + * + * SendDecodedFrame + * + * Send the frame to the decode server. + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +SendDecodedFrame(MpegFrame * const frameP) { +/*---------------------------------------------------------------------------- + Send frame *frameP to the decode server. +-----------------------------------------------------------------------------*/ + int const negativeTwo = -2; + + int clientSocket; + const char * error; + + /* send to IOServer */ + ConnectToSocket(IOhostName, ioPortNumber, &hostEntry, + &clientSocket, &error); + if (error) + errorExit("CHILD: Can't connect to decode server to " + "give it a decoded frame. %s", error); + + WriteInt(clientSocket, negativeTwo); + + WriteInt(clientSocket, frameP->id); + + writeYUVDecoded(clientSocket, Fsize_x, Fsize_y, frameP); + + close(clientSocket); +} + + +/*===========================================================================* + * + * GetRemoteDecodedFrame + * + * get the decoded frame from the decode server. + * + * RETURNS: nothing + * + * SIDE EFFECTS: + * + *===========================================================================*/ +void +GetRemoteDecodedRefFrame(MpegFrame * const frameP, + int const frameNumber) { +/*---------------------------------------------------------------------------- + Get decoded frame number 'frameNumber' *frameP from the decode server. +-----------------------------------------------------------------------------*/ + int const negativeThree = -3; + int clientSocket; + const char * error; + + /* send to IOServer */ + ConnectToSocket(IOhostName, ioPortNumber, &hostEntry, + &clientSocket, &error); + if (error) + errorExit("CHILD: Can't connect to decode server " + "to get a decoded frame. %s", + error); + + /* ask IOServer for decoded frame */ + WriteInt(clientSocket, negativeThree); + + WriteInt(clientSocket, frameP->id); + + readYUVDecoded(clientSocket, Fsize_x, Fsize_y, frameP); + + close(clientSocket); +} + + +/********* + routines handling forks, execs, PIDs and signals + save, system-style forks + apian@ise.fhg.de + *******/ + + +/*===========================================================================* + * + * cleanup_fork + * + * Kill all the children, to be used when we get killed + * + * RETURNS: nothing + * + * SIDE EFFECTS: kills other processes + * + *===========================================================================*/ +static void cleanup_fork( dummy ) /* try to kill all child processes */ + int dummy; +{ + register int i; + for (i = 0; i < current_max_forked_pid; ++i ) { + +#ifdef DEBUG_FORK + fprintf(stderr, "cleanup_fork: killing PID %d\n", ClientPid[i]); +#endif + + if (kill(ClientPid[i], TERMINATE_PID_SIGNAL)) { + fprintf(stderr, "cleanup_fork: killed PID=%d failed (errno %d)\n", + ClientPid[i], errno); + } + } +} + +/*===========================================================================* + * + * safe_fork + * + * fork a command + * + * RETURNS: success/failure + * + * SIDE EFFECTS: Fork the command, and save to PID so you can kil it later! + * + *===========================================================================*/ +static int safe_fork(command) /* fork child process and remember its PID */ + char *command; +{ + static int init=0; + char *argis[MAXARGS]; + register int i=1; + + if (!(argis[0] = strtok(command, " \t"))) return(0); /* tokenize */ + while ((argis[i] = strtok(NULL, " \t")) && i < MAXARGS) ++i; + argis[i] = NULL; + +#ifdef DEBUG_FORK + {register int i=0; + fprintf(stderr, "Command %s becomes:\n", command); + while(argis[i]) {fprintf(stderr, "--%s--\n", argis[i]); ++i;} } +#endif + + if (!init) { /* register clean-up routine */ + signal (SIGQUIT, cleanup_fork); + signal (SIGTERM, cleanup_fork); + signal (SIGINT , cleanup_fork); + init=1; + } + + if (-1 == (ClientPid[current_max_forked_pid] = fork()) ) { + perror("safe_fork: fork failed "); + return(-1); + } + if( !ClientPid[current_max_forked_pid]) { /* we are in child process */ + execvp(argis[0], argis ); + perror("safe_fork child: exec failed "); + exit(1); + } +#ifdef DEBUG_FORK + fprintf(stderr, "parallel: forked PID=%d\n", ClientPid[current_max_forked_pid]); +#endif + current_max_forked_pid++; + return(0); +} + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + /*=================* + * IO SERVER STUFF * + *=================*/ + + +/*===========================================================================* + * + * SetIOConvert + * + * sets the IO conversion to be separate or not. If separate, then + * some post-processing is done at slave end + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +SetIOConvert(bool const separate) { + separateConversion = separate; +} + + +/*===========================================================================* + * + * SetParallelPerfect + * + * If this is called, then frames will be divided up completely, and + * evenly (modulo rounding) between all the processors + * + * RETURNS: nothing + * + * SIDE EFFECTS: Sets parallelPerfect .... + * + *===========================================================================*/ +void +SetParallelPerfect(val) +boolean val; +{ + parallelPerfect = val; +} + + +/*===========================================================================* + * + * SetRemoteShell + * + * sets the remote shell program (usually rsh, but different on some + * machines) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +SetRemoteShell(const char * const shell) { + strcpy(rsh, shell); +} + + +static void +decodedFrameToDisk(int const otherSock) { +/*---------------------------------------------------------------------------- + Get a decoded from from socket 'otherSock' and write it to disk. +-----------------------------------------------------------------------------*/ + int frameNumber; + MpegFrame * frameP; + + ReadInt(otherSock, &frameNumber); + + if (debugSockets) { + fprintf(stdout, "INPUT SERVER: GETTING DECODED FRAME %d\n", + frameNumber); + fflush(stdout); + } + + /* should read frame from socket, then write to disk */ + frameP = Frame_New(frameNumber, 'i'); + + Frame_AllocDecoded(frameP, TRUE); + + readYUVDecoded(otherSock, Fsize_x, Fsize_y, frameP); + + /* now output to disk */ + WriteDecodedFrame(frameP); + + Frame_Free(frameP); +} + + + +static void +decodedFrameFromDisk(int const otherSock) { + + /* request for decoded frame from disk */ + + int frameNumber; + MpegFrame * frameP; + + ReadInt(otherSock, &frameNumber); + + if (debugSockets) { + fprintf(stdout, "INPUT SERVER: READING DECODED FRAME %d " + "from DISK\n", frameNumber); + fflush(stdout); + } + + /* should read frame from disk, then write to socket */ + frameP = Frame_New(frameNumber, 'i'); + + Frame_AllocDecoded(frameP, TRUE); + + ReadDecodedRefFrame(frameP, frameNumber); + + writeYUVDecoded(otherSock, Fsize_x, Fsize_y, frameP); + + Frame_Free(frameP); +} + + + +static void +routeFromSocketToDisk(int const otherSock, + unsigned char ** const bigBufferP, + unsigned int * const bigBufferSizeP) { + + /* routing output frame from socket to disk */ + + int frameNumber; + int numBytes; + unsigned char * bigBuffer; + unsigned int bigBufferSize; + const char * fileName; + FILE * filePtr; + + bigBuffer = *bigBufferP; + bigBufferSize = *bigBufferSizeP; + + ReadInt(otherSock, &frameNumber); + ReadInt(otherSock, &numBytes); + + /* Expand bigBuffer if necessary to fit this frame */ + if (numBytes > bigBufferSize) { + bigBufferSize = numBytes; + if (bigBuffer != NULL) + free(bigBuffer); + + MALLOCARRAY_NOFAIL(bigBuffer, bigBufferSize); + } + + /* now read in the bytes */ + ReadBytes(otherSock, bigBuffer, numBytes); + + /* open file to output this stuff to */ + asprintfN(&fileName, "%s.frame.%d", outputFileName, frameNumber); + filePtr = fopen(fileName, "wb"); + + if (filePtr == NULL) + errorExit("I/O SERVER: Could not open output file(3): %s", fileName); + + strfree(fileName); + + /* now write the bytes here */ + fwrite(bigBuffer, sizeof(char), numBytes, filePtr); + + fclose(filePtr); + + if (debugSockets) { + fprintf(stdout, "====I/O SERVER: WROTE FRAME %d to disk\n", + frameNumber); + fflush(stdout); + } + + *bigBufferP = bigBuffer; + *bigBufferSizeP = bigBufferSize; +} + + + +static void +readConvertWriteToSocket(struct inputSource * const inputSourceP, + int const otherSock, + int const frameNumber, + bool * const endOfStreamP) { +/*---------------------------------------------------------------------------- + Get the frame numbered 'frameNumber' from input source + *inputSourceP, apply format conversion User requested, and write + the "base format" result to socket 'otherSock'. +-----------------------------------------------------------------------------*/ + FILE * convertedFileP; + + convertedFileP = ReadIOConvert(inputSourceP, frameNumber); + if (convertedFileP) { + bool eof; + eof = FALSE; /* initial value */ + while (!eof) { + unsigned char buffer[1024]; + unsigned int numBytes; + + numBytes = fread(buffer, 1, sizeof(buffer), convertedFileP); + + if (numBytes > 0) { + WriteInt(otherSock, numBytes); + WriteBytes(otherSock, buffer, numBytes); + } else + eof = TRUE; + } + + if (strcmp(ioConversion, "*") == 0 ) + fclose(convertedFileP); + else + pclose(convertedFileP); + + *endOfStreamP = FALSE; + } else + *endOfStreamP = TRUE; +} + + + +static void +readWriteYuvToSocket(struct inputSource * const inputSourceP, + int const otherSock, + int const frameNumber, + bool * const endOfStreamP) { +/*---------------------------------------------------------------------------- + Read Frame number 'frameNumber' from the input source *inputSourceP, + assuming it is in base format, and write its contents in YUV format + to socket 'otherSock'. + + Wait for acknowledgement that consumer has received it. +-----------------------------------------------------------------------------*/ + MpegFrame * frameP; + + frameP = Frame_New(frameNumber, 'i'); + + ReadFrame(frameP, inputSourceP, frameNumber, inputConversion, + endOfStreamP); + + if (!*endOfStreamP) { + writeYUVOrig(otherSock, Fsize_x, Fsize_y, frameP); + + { + /* Make sure we don't leave until other processor read + everything + */ + int dummy; + ReadInt(otherSock, &dummy); + assert(dummy == 0); + } + } + Frame_Free(frameP); +} + + + +static void +readFrameWriteToSocket(struct inputSource * const inputSourceP, + int const otherSock, + int const frameNumber, + bool * const endOfStreamP) { +/*---------------------------------------------------------------------------- + Read Frame number 'frameNumber' from the input source *inputSourceP + and write it to socket 'otherSock'. +-----------------------------------------------------------------------------*/ + if (debugSockets) { + fprintf(stdout, "I/O SERVER GETTING FRAME %d\n", frameNumber); + fflush(stdout); + } + + if (separateConversion) + readConvertWriteToSocket(inputSourceP, otherSock, frameNumber, + endOfStreamP); + else + readWriteYuvToSocket(inputSourceP, otherSock, frameNumber, + endOfStreamP); + + if (debugSockets) { + fprintf(stdout, "====I/O SERVER: READ FRAME %d\n", frameNumber); + } +} + + + +static void +processNextConnection(int const serverSocket, + struct inputSource * const inputSourceP, + bool * const doneP, + unsigned char ** const bigBufferP, + unsigned int * const bigBufferSizeP) { + + int otherSock; + int command; + const char * error; + + AcceptConnection(serverSocket, &otherSock, &error); + if (error) + errorExit("I/O SERVER: Failed to accept next connection. %s", error); + + ReadInt(otherSock, &command); + + switch (command) { + case -1: + *doneP = TRUE; + break; + case -2: + decodedFrameToDisk(otherSock); + break; + case -3: + decodedFrameFromDisk(otherSock); + break; + case -4: + routeFromSocketToDisk(otherSock, bigBufferP, bigBufferSizeP); + break; + default: { + unsigned int const frameNumber = command; + + bool endOfStream; + + readFrameWriteToSocket(inputSourceP, otherSock, frameNumber, + &endOfStream); + + if (endOfStream) { + /* We don't do anything. Closing the socket with having written + anything is our signal that there is no more input. + + (Actually, Ppmtompeg cannot handle stream input in parallel + mode -- this code is just infrastructure so maybe it can some + day). + */ + } + } + } + close(otherSock); +} + + + +void +IoServer(struct inputSource * const inputSourceP, + const char * const parallelHostName, + int const portNum) { +/*---------------------------------------------------------------------------- + Execute an I/O server. + + An I/O server is the partner on the master machine of a child process + on a "remote" system. "Remote" here doesn't just mean on another system. + It means on a system that isn't even in the same cluster -- specifically, + a system that doesn't have access to the same filesystem as the master. + + The child process passes frame contents between it and the master via + the I/O server. +-----------------------------------------------------------------------------*/ + int ioPortNum; + int serverSocket; + boolean done; + unsigned char *bigBuffer; + /* A work buffer that we keep around permanently. We increase + its size as needed, but never shrink it. + */ + unsigned int bigBufferSize; + /* The current allocated size of bigBuffer[] */ + const char * error; + + bigBufferSize = 0; /* Start with no buffer */ + bigBuffer = NULL; + + /* once we get IO port num, should transmit it to parallel server */ + + CreateListeningSocket(&serverSocket, &ioPortNum, &error); + if (error) + errorExit("Unable to create socket on which to listen for " + "reports from children. %s", error); + + if (debugSockets) + fprintf(stdout, "====I/O USING PORT %d\n", ioPortNum); + + TransmitPortNum(parallelHostName, portNum, ioPortNum); + + if (separateConversion) + SetFileType(ioConversion); /* for reading */ + else + SetFileType(inputConversion); + + done = FALSE; /* initial value */ + + while (!done) + processNextConnection(serverSocket, inputSourceP, + &done, &bigBuffer, &bigBufferSize); + + close(serverSocket); + + if ( debugSockets ) { + fprintf(stdout, "====I/O SERVER: Shutting Down\n"); + } +} + + + +/*===========================================================================* + * + * SendRemoteFrame + * + * called by a slave to the I/O server; sends an encoded frame + * to the server to be sent to disk + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +SendRemoteFrame(int const frameNumber, BitBucket * const bb) { + + int const negativeFour = -4; + int clientSocket; + time_t tempTimeStart, tempTimeEnd; + const char * error; + + time(&tempTimeStart); + + ConnectToSocket(IOhostName, ioPortNumber, &hostEntry, + &clientSocket, &error); + if (error) + errorExit("CHILD: Can't connect to I/O server to deliver results. %s", + error); + + WriteInt(clientSocket, negativeFour); + + WriteInt(clientSocket, frameNumber); + + if (frameNumber != -1) { + /* send number of bytes */ + + WriteInt(clientSocket, (bb->totalbits+7)>>3); + + /* now send the bytes themselves */ + Bitio_WriteToSocket(bb, clientSocket); + } + + close(clientSocket); + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + + +void +GetRemoteFrame(MpegFrame * const frameP, + int const frameNumber) { +/*---------------------------------------------------------------------------- + Get a frame from the I/O server. + + This is intended for use by a child. +-----------------------------------------------------------------------------*/ + int clientSocket; + const char * error; + + Fsize_Note(frameNumber, yuvWidth, yuvHeight); + + if (debugSockets) { + fprintf(stdout, "MACHINE %s REQUESTING connection for FRAME %d\n", + getenv("HOST"), frameNumber); + fflush(stdout); + } + + ConnectToSocket(IOhostName, ioPortNumber, &hostEntry, + &clientSocket, &error); + + if (error) + errorExit("CHILD: Can't connect to I/O server to get a frame. %s", + error); + + WriteInt(clientSocket, frameNumber); + + if (frameNumber != -1) { + if (separateConversion) { + unsigned char buffer[1024]; + /* This is by design the exact size of the data per message (except + the last message for a frame) the I/O server sends. + */ + int numBytes; /* Number of data bytes in message */ + FILE * filePtr = pm_tmpfile(); + + /* read in stuff, write to file, perform local conversion */ + do { + ReadInt(clientSocket, &numBytes); + + if (numBytes > sizeof(buffer)) + errorExit("Invalid message received: numBytes = %d, " + "which is greater than %d\n", + numBytes, sizeof(numBytes)); + ReadBytes(clientSocket, buffer, numBytes); + + fwrite(buffer, 1, numBytes, filePtr); + } while ( numBytes == sizeof(buffer) ); + fflush(filePtr); + { + bool endOfStream; + rewind(filePtr); + /* I/O Server gave us base format. Read it as an MpegFrame */ + ReadFrameFile(frameP, filePtr, slaveConversion, &endOfStream); + assert(!endOfStream); + } + fclose(filePtr); + } else { + Frame_AllocYCC(frameP); + + if (debugSockets) { + fprintf(stdout, "MACHINE %s allocated YCC FRAME %d\n", + getenv("HOST"), frameNumber); + fflush(stdout); + } + /* I/O Server gave us internal YUV format. Read it as MpegFrame */ + readYUVOrig(clientSocket, yuvWidth, yuvHeight, frameP); + } + } + + WriteInt(clientSocket, 0); + + close(clientSocket); + + if (debugSockets) { + fprintf(stdout, "MACHINE %s READ COMPLETELY FRAME %d\n", + getenv("HOST"), frameNumber); + fflush(stdout); + } +} + + +struct combineControl { + unsigned int numFrames; +}; + + + + +static void +getAndProcessACombineConnection(int const outputServerSocket) { + int otherSock; + int command; + const char * error; + + AcceptConnection(outputServerSocket, &otherSock, &error); + + if (error) + errorExit("COMBINE SERVER: " + "Failed to accept next connection. %s", error); + + ReadInt(otherSock, &command); + + if (command == -2) { + /* this is notification from non-remote process that a + frame is done. + */ + int frameStart, frameEnd; + + ReadInt(otherSock, &frameStart); + ReadInt(otherSock, &frameEnd); + + machineDebug("COMBINE_SERVER: Frames %d - %d done", + frameStart, frameEnd); + { + unsigned int i; + for (i = frameStart; i <= frameEnd; ++i) + frameDone[i] = TRUE; + } + } else + errorExit("COMBINE SERVER: Unrecognized command %d received.", + command); + + close(otherSock); +} + + + +#define READ_ATTEMPTS 5 /* number of times (seconds) to retry an input file */ + + +static void +openInputFile(const char * const fileName, + FILE ** const inputFilePP) { + + FILE * inputFileP; + unsigned int attempts; + + inputFileP = NULL; + attempts = 0; + + while (!inputFileP && attempts < READ_ATTEMPTS) { + inputFileP = fopen(fileName, "rb"); + if (inputFileP == NULL) { + pm_message("ERROR Couldn't read frame file '%s' errno = %d (%s)" + "attempt %d", + fileName, errno, strerror(errno), attempts); + sleep(1); + } + ++attempts; + } + if (inputFileP == NULL) + pm_error("Unable to open file '%s' after %d attempts.", + fileName, attempts); + + *inputFilePP = inputFileP; +} + + + +static void +waitForOutputFile(void * const inputHandle, + unsigned int const frameNumber, + FILE ** const ifPP) { +/*---------------------------------------------------------------------------- + Keep handling output events until we get the specified frame number. + Open the file it's in and return the stream handle. +-----------------------------------------------------------------------------*/ + struct combineControl * const combineControlP = (struct combineControl *) + inputHandle; + + if (frameNumber >= combineControlP->numFrames) + *ifPP = NULL; + else { + const char * fileName; + + while (!frameDone[frameNumber]) { + machineDebug("COMBINE_SERVER: Waiting for frame %u done", + frameNumber); + + getAndProcessACombineConnection(outputServerSocket); + } + machineDebug("COMBINE SERVER: Wait for frame %u over", frameNumber); + + asprintfN(&fileName, "%s.frame.%u", outputFileName, frameNumber); + + openInputFile(fileName, ifPP); + + strfree(fileName); + } +} + + + +static void +unlinkFile(void * const inputHandle, + unsigned int const frameNumber) { + + if (!keepTempFiles) { + const char * fileName; + + asprintfN(&fileName, "%s.frame.%u", outputFileName, frameNumber); + + unlink(fileName); + + strfree(fileName); + } +} + + + +void +CombineServer(int const numFrames, + const char * const masterHostName, + int const masterPortNum, + const char * const outputFileName) { +/*---------------------------------------------------------------------------- + Execute a combine server. + + This handles combination of frames. +-----------------------------------------------------------------------------*/ + int combinePortNum; + FILE * ofP; + const char * error; + struct combineControl combineControl; + + /* once we get Combine port num, should transmit it to parallel server */ + + CreateListeningSocket(&outputServerSocket, &combinePortNum, &error); + if (error) + errorExit("Unable to create socket on which to listen. %s", error); + + machineDebug("COMBINE SERVER: LISTENING ON PORT %d", combinePortNum); + + TransmitPortNum(masterHostName, masterPortNum, combinePortNum); + + MALLOCARRAY_NOFAIL(frameDone, numFrames); + { + unsigned int i; + for (i = 0; i < numFrames; ++i) + frameDone[i] = FALSE; + } + ofP = pm_openw(outputFileName); + + combineControl.numFrames = numFrames; + + FramesToMPEG(ofP, &combineControl, &waitForOutputFile, &unlinkFile); + + machineDebug("COMBINE SERVER: Shutting down"); + + /* tell Master server we are done */ + TransmitPortNum(masterHostName, masterPortNum, combinePortNum); + + close(outputServerSocket); + + fclose(ofP); +} + + +/*=====================* + * MASTER SERVER STUFF * + *=====================*/ + + +static void +startCombineServer(const char * const encoderName, + unsigned int const numMachines, + const char * const masterHostName, + int const masterPortNum, + unsigned int const numInputFiles, + const char * const paramFileName, + int const masterSocket, + int * const combinePortNumP) { + + char command[1024]; + int otherSock; + const char * error; + + snprintf(command, sizeof(command), + "%s %s -max_machines %d -output_server %s %d %d %s", + encoderName, + debugMachines ? "-debug_machines" : "", + numMachines, masterHostName, masterPortNum, + numInputFiles, paramFileName); + + machineDebug("MASTER: Starting combine server with shell command '%s'", + command); + + safe_fork(command); + + machineDebug("MASTER: Listening for connection back from " + "new Combine server"); + + AcceptConnection(masterSocket, &otherSock, &error); + if (error) + errorExit("MASTER SERVER: " + "Failed to accept next connection. %s", error); + + ReadInt(otherSock, combinePortNumP); + close(otherSock); + + machineDebug("MASTER: Combine port number = %d", *combinePortNumP); +} + + + +static void +startDecodeServer(const char * const encoderName, + unsigned int const numMachines, + const char * const masterHostName, + int const masterPortNum, + unsigned int const numInputFiles, + const char * const paramFileName, + int const masterSocket, + int * const decodePortNumP) { + + char command[1024]; + int otherSock; + const char * error; + + snprintf(command, sizeof(command), + "%s %s -max_machines %d -decode_server %s %d %d %s", + encoder_name, + debugMachines ? "-debug_machines" : "", + numMachines, masterHostName, masterPortNum, + numInputFiles, paramFileName); + + machineDebug("MASTER: Starting decode server with shell command '%s'", + command); + + safe_fork(command); + + machineDebug("MASTER: Listening for connection back from " + "new Decode server"); + + AcceptConnection(masterSocket, &otherSock, &error); + if (error) + errorExit("MASTER SERVER: " + "Failed to accept connection back from the new " + "decode server. %s", error); + + ReadInt(otherSock, decodePortNumP); + + close(otherSock); + + machineDebug("MASTER: Decode port number = %d", *decodePortNumP); +} + + + +static void +startIoServer(const char * const encoderName, + unsigned int const numChildren, + const char * const masterHostName, + int const masterPortNum, + int const masterSocket, + const char * const paramFileName, + int * const ioPortNumP) { + + char command[1024]; + int otherSock; + const char * error; + + sprintf(command, "%s -max_machines %d -io_server %s %d %s", + encoderName, numChildren, masterHostName, masterPortNum, + paramFileName); + + machineDebug("MASTER: Starting I/O server with remote shell command '%s'", + command); + + safe_fork(command); + + machineDebug("MASTER: Listening for connection back from " + "new I/O server"); + + AcceptConnection(masterSocket, &otherSock, &error); + if (error) + errorExit("MASTER SERVER: " + "Failed to accept connection back from the new " + "I/O server. %s", error); + + ReadInt(otherSock, ioPortNumP); + close(otherSock); + + machineDebug("MASTER: I/O port number = %d", *ioPortNumP); +} + + + +static void +extendToEndOfPattern(unsigned int * const nFramesP, + unsigned int const startFrame, + unsigned int const framePatternLen, + unsigned int const numFramesInStream) { + + assert(framePatternLen >= 1); + + while (startFrame + *nFramesP < numFramesInStream && + (startFrame + *nFramesP) % framePatternLen != 0) + ++(*nFramesP); +} + + + +static void +allocateInitialFrames(struct scheduler * const schedulerP, + boolean const parallelPerfect, + boolean const forceIalign, + unsigned int const framePatternLen, + unsigned int const parallelTestFrames, + unsigned int const childNum, + unsigned int * const startFrameP, + unsigned int * const nFramesP) { +/*---------------------------------------------------------------------------- + Choose which frames, to hand out to the new child numbered 'childNum'. +-----------------------------------------------------------------------------*/ + unsigned int const framesPerChild = + MAX(1, ((schedulerP->numFramesInJob - schedulerP->nextFrame) / + (schedulerP->numMachines - childNum))); + + unsigned int nFrames; + + if (parallelPerfect) + nFrames = framesPerChild; + else { + assert(parallelTestFrames >= 1); + + nFrames = MIN(parallelTestFrames, framesPerChild); + } + if (forceIalign) + extendToEndOfPattern(&nFrames, schedulerP->nextFrame, + framePatternLen, schedulerP->numFramesInJob); + + nFrames = MIN(nFrames, schedulerP->numFramesInJob - schedulerP->nextFrame); + + *startFrameP = schedulerP->nextFrame; + *nFramesP = nFrames; + schedulerP->nextFrame += nFrames; +} + + + +static float +taperedGoalTime(struct childState const childState[], + unsigned int const remainingFrameCount) { + + float goalTime; + float allChildrenFPS; + float remainingJobTime; + /* How long we expect it to be before the whole movie is encoded*/ + float sum; + int numMachinesToEstimate; + unsigned int childNum; + + /* frames left = lastFrameInStream - startFrame + 1 */ + for (childNum = 0, sum = 0.0, numMachinesToEstimate = 0; + childNum < numMachines; ++childNum) { + if (!childState[childNum].finished) { + if (childState[childNum].fps < 0.0 ) + ++numMachinesToEstimate; + else + sum += childState[childNum].fps; + } + } + + allChildrenFPS = (float)numMachines * + (sum/(float)(numMachines-numMachinesToEstimate)); + + remainingJobTime = (float)remainingFrameCount/allChildrenFPS; + + goalTime = MAX(5.0, remainingJobTime/2); + + return goalTime; +} + + + +static void +allocateMoreFrames(struct scheduler * const schedulerP, + unsigned int const childNum, + struct childState const childState[], + bool const forceIalign, + unsigned int const framePatternLen, + bool const goalTimeSpecified, + unsigned int const goalTimeArg, + unsigned int * const startFrameP, + unsigned int * const nFramesP) { +/*---------------------------------------------------------------------------- + Decide which frames should be child 'childNum''s next assignment, + given the state/history of all children is childState[]. + + The lowest numbered frame which needs yet to be encoded is frame + number 'startFrame' and 'lastFrameInStream' is the highest. + + The allocation always starts at the lowest numbered frame that + hasn't yet been allocated and is sequential. We return as + *startFrameP the frame number of the first frame in the allocation + and as *nFramesP the number of frames. + + If 'goalTimeSpecified' is true, we try to make the assignment take + 'goalTimeArg' seconds. If 'goalTimeSpecified' is not true, we choose + a goal time ourselves, which is based on how long we think it will + take for all the children to finish all the remaining frames. +-----------------------------------------------------------------------------*/ + float goalTime; + /* Number of seconds we want the assignment to take. We size the + assignment to try to meet this goal. + */ + unsigned int nFrames; + float avgFps; + + if (!goalTimeSpecified) { + goalTime = taperedGoalTime(childState, + schedulerP->numFramesInJob - + schedulerP->nextFrame); + + pm_message("MASTER: ASSIGNING %s %.2f seconds of work", + machineName[childNum], goalTime); + } else + goalTime = goalTimeArg; + + if (childState[childNum].numSeconds != 0) + avgFps = (float)childState[childNum].numFrames / + childState[childNum].numSeconds; + else + avgFps = 0.1; /* arbitrary small value */ + + nFrames = MAX(1u, (unsigned int)(goalTime * avgFps + 0.5)); + + nFrames = MIN(nFrames, + schedulerP->numFramesInJob - schedulerP->nextFrame); + + if (forceIalign) + extendToEndOfPattern(&nFrames, schedulerP->nextFrame, + framePatternLen, schedulerP->numFramesInJob); + + *startFrameP = schedulerP->nextFrame; + *nFramesP = nFrames; + schedulerP->nextFrame += nFrames; +} + + + +static void +startChildren(struct scheduler * const schedulerP, + const char * const encoderName, + const char * const masterHostName, + int const masterPortNum, + const char * const paramFileName, + boolean const parallelPerfect, + boolean const forceIalign, + unsigned int const framePatternLen, + unsigned int const parallelTestFrames, + boolean const beNice, + int const masterSocket, + int const combinePortNum, + int const decodePortNum, + int * const ioPortNum, + unsigned int * const numIoServersP, + struct childState ** const childStateP) { +/*---------------------------------------------------------------------------- + Start up the children. Tell them to work for the master at + 'masterHostName':'masterPortNum'. + + Start I/O servers (as processes on this system) as required and return + the port numbers of the TCP ports on which they listen as + ioPortNum[] and the number of them as *numIoServersP. + + Give each of the children some initial work to do. This may be just + a small amount for timing purposes. + + We access and manipulate the various global variables that represent + the state of the children, and the scheduler structure. +-----------------------------------------------------------------------------*/ + struct childState * childState; /* malloc'ed */ + unsigned int childNum; + unsigned int numIoServers; + unsigned int childrenLeftCurrentIoServer; + /* The number of additional children we can hook up to the + current I/O server before reaching our maximum children per + I/O server. 0 if there is no current I/O server. + */ + + MALLOCARRAY_NOFAIL(childState, schedulerP->numMachines); + + childrenLeftCurrentIoServer = 0; /* No current I/O server yet */ + + numIoServers = 0; /* None created yet */ + + for (childNum = 0; childNum < schedulerP->numMachines; ++childNum) { + char command[1024]; + unsigned int startFrame; + unsigned int nFrames; + + childState[childNum].fps = -1.0; /* illegal value as flag */ + childState[childNum].numSeconds = 0; + + allocateInitialFrames(schedulerP, parallelPerfect, forceIalign, + framePatternLen, parallelTestFrames, + childNum, &startFrame, &nFrames); + + if (nFrames == 0) { + childState[childNum].finished = TRUE; + machineDebug("MASTER: No more frames; not starting child '%s'", + machineName[childNum]); + } else { + childState[childNum].finished = FALSE; + + if (remote[childNum]) { + if (childrenLeftCurrentIoServer == 0) { + startIoServer(encoderName, schedulerP->numMachines, + masterHostName, masterPortNum, masterSocket, + paramFileName, &ioPortNum[numIoServers++]); + + childrenLeftCurrentIoServer = SOMAXCONN; + } + --childrenLeftCurrentIoServer; + } + snprintf(command, sizeof(command), + "%s %s -l %s %s " + "%s %s -child %s %d %d %d %d %d %d " + "-frames %d %d %s", + rsh, + machineName[childNum], userName[childNum], + beNice ? "nice" : "", + executable[childNum], + debugMachines ? "-debug_machines" : "", + masterHostName, masterPortNum, + remote[childNum] ? ioPortNum[numIoServers-1] : 0, + combinePortNum, decodePortNum, childNum, + remote[childNum] ? 1 : 0, + startFrame, startFrame + nFrames - 1, + remote[childNum] ? + remoteParamFile[childNum] : paramFileName + ); + + machineDebug("MASTER: Starting child server " + "with shell command '%s'", command); + + safe_fork(command); + + machineDebug("MASTER: Frames %d-%d assigned to new child %s", + startFrame, startFrame + nFrames - 1, + machineName[childNum]); + } + childState[childNum].startFrame = startFrame; + childState[childNum].lastNumFrames = nFrames; + childState[childNum].numFrames = childState[childNum].lastNumFrames; + } + *childStateP = childState; + *numIoServersP = numIoServers; +} + + + +static void +noteFrameDone(const char * const combineHostName, + int const combinePortNum, + unsigned int const frameStart, + unsigned int const frameEnd) { +/*---------------------------------------------------------------------------- + Tell the Combine server that frames 'frameStart' through 'frameEnd' + are done. +-----------------------------------------------------------------------------*/ + int const negativeTwo = -2; + int clientSocket; + time_t tempTimeStart, tempTimeEnd; + const char * error; + struct hostent * hostEntP; + + time(&tempTimeStart); + + hostEntP = NULL; + + ConnectToSocket(combineHostName, combinePortNum, &hostEntP, + &clientSocket, &error); + + if (error) + errorExit("MASTER: Can't connect to Combine server to tell it frames " + "are done. %s", error); + + WriteInt(clientSocket, negativeTwo); + + WriteInt(clientSocket, frameStart); + + WriteInt(clientSocket, frameEnd); + + close(clientSocket); + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + + +static void +feedTheChildren(struct scheduler * const schedulerP, + struct childState childState[], + int const masterSocket, + const char * const combineHostName, + int const combinePortNum, + bool const forceIalign, + unsigned int const framePatternLen, + bool const goalTimeSpecified, + unsigned int const goalTime) { +/*---------------------------------------------------------------------------- + Listen for children to tell us they have finished their assignments + and give them new assignments, until all the frames have been assigned + and all the children have finished. + + As children finish assignments, inform the combine server at + 'combineHostName':'combinePortNum' of such. + + Note that the children got initial assigments when they were created. + So the first thing we do is wait for them to finish those. +-----------------------------------------------------------------------------*/ + unsigned int numFinished; + /* Number of child machines that have been excused because there + is no more work for them. + */ + unsigned int framesDone; + + numFinished = 0; + framesDone = 0; + + while (numFinished != schedulerP->numMachines) { + int otherSock; + int childNum; + int seconds; + float framesPerSecond; + struct childState * csP; + const char * error; + unsigned int nextFrame; + unsigned int nFrames; + + machineDebug("MASTER: Listening for a connection..."); + + AcceptConnection(masterSocket, &otherSock, &error); + if (error) + errorExit("MASTER SERVER: " + "Failed to accept next connection. %s", error); + + ReadInt(otherSock, &childNum); + ReadInt(otherSock, &seconds); + + csP = &childState[childNum]; + + csP->numSeconds += seconds; + csP->fps = (float)csP->numFrames / (float)csP->numSeconds; + + if (seconds != 0) + framesPerSecond = (float)csP->lastNumFrames / (float)seconds; + else + framesPerSecond = (float)csP->lastNumFrames * 2.0; + + machineDebug("MASTER: Child %s FINISHED ASSIGNMENT. " + "%f frames per second", + machineName[childNum], framesPerSecond); + + noteFrameDone(combineHostName, combinePortNum, csP->startFrame, + csP->startFrame + csP->lastNumFrames - 1); + + framesDone += csP->lastNumFrames; + + allocateMoreFrames(schedulerP, childNum, childState, + forceIalign, framePatternLen, + goalTimeSpecified, goalTime, + &nextFrame, &nFrames); + + if (nFrames == 0) { + WriteInt(otherSock, -1); + WriteInt(otherSock, 0); + + ++numFinished; + + machineDebug("MASTER: NO MORE WORK FOR CHILD %s. " + "(%d of %d children now done)", + machineName[childNum], numFinished, numMachines); + } else { + WriteInt(otherSock, nextFrame); + WriteInt(otherSock, nextFrame + nFrames - 1); + + machineDebug("MASTER: Frames %d-%d assigned to child %s", + nextFrame, nextFrame + nFrames - 1, + machineName[childNum]); + + csP->startFrame = nextFrame; + csP->lastNumFrames = nFrames; + csP->numFrames += csP->lastNumFrames; + } + close(otherSock); + + machineDebug("MASTER: %d/%d DONE; %d ARE ASSIGNED", + framesDone, schedulerP->numFramesInJob, + schedulerP->nextFrame - framesDone); + } +} + + + +static void +stopIoServers(const char * const hostName, + int const ioPortNum[], + unsigned int const numIoServers) { + + unsigned int childNum; + + IOhostName = hostName; + for (childNum = 0; childNum < numIoServers; ++childNum) { + ioPortNumber = ioPortNum[childNum]; + EndIOServer(); + } +} + + + +static void +waitForCombineServerToTerminate(int const masterSocket) { + + int otherSock; + const char * error; + + machineDebug("MASTER SERVER: Waiting for combine server to terminate"); + + AcceptConnection(masterSocket, &otherSock, &error); + if (error) + errorExit("MASTER SERVER: " + "Failed to accept connection expected from a " + "terminating combine server. %s", error); + + { + int dummy; + ReadInt(otherSock, &dummy); + } + close(otherSock); +} + + + +static void +printFinalStats(FILE * const statfileP, + time_t const startUpBegin, + time_t const startUpEnd, + time_t const shutDownBegin, + time_t const shutDownEnd, + unsigned int const numChildren, + struct childState const childState[], + unsigned int const numFrames) { + + unsigned int pass; + FILE * fileP; + + for (pass = 0; pass < 2; ++pass) { + if (pass == 0) + fileP = stdout; + else + fileP = statfileP; + + if (fileP) { + unsigned int childNum; + float totalFPS; + + fprintf(fileP, "\n\n"); + fprintf(fileP, "PARALLEL SUMMARY\n"); + fprintf(fileP, "----------------\n"); + fprintf(fileP, "\n"); + fprintf(fileP, "START UP TIME: %u seconds\n", + (unsigned int)(startUpEnd - startUpBegin)); + fprintf(fileP, "SHUT DOWN TIME: %u seconds\n", + (unsigned int)(shutDownEnd - shutDownBegin)); + + fprintf(fileP, + "%14.14s %8.8s %8.8s %12.12s %9.9s\n", + "MACHINE", "Frames", "Seconds", "Frames/Sec", + "Self Time"); + + fprintf(fileP, + "%14.14s %8.8s %8.8s %12.12s %9.9s\n", + "--------------", "--------", "--------", "------------", + "---------"); + + totalFPS = 0.0; + for (childNum = 0; childNum < numChildren; ++childNum) { + float const localFPS = + (float)childState[childNum].numFrames / + childState[childNum].numSeconds; + fprintf(fileP, "%14.14s %8u %8u %12.4f %8u\n", + machineName[childNum], + childState[childNum].numFrames, + childState[childNum].numSeconds, + localFPS, + (unsigned int)((float)numFrames/localFPS)); + totalFPS += localFPS; + } + + fprintf(fileP, + "%14.14s %8.8s %8.8s %12.12s %9.9s\n", + "--------------", "--------", "--------", "------------", + "---------"); + + fprintf(fileP, "%14s %8.8s %8u %12.4f\n", + "OPTIMAL", "", + (unsigned int)((float)numFrames/totalFPS), + totalFPS); + + { + unsigned int const diffTime = shutDownEnd - startUpBegin; + + fprintf(fileP, "%14s %8.8s %8u %12.4f\n", + "ACTUAL", "", diffTime, + (float)numFrames / diffTime); + } + fprintf(fileP, "\n\n"); + } + } +} + + + +void +MasterServer(struct inputSource * const inputSourceP, + const char * const paramFileName, + const char * const outputFileName) { +/*---------------------------------------------------------------------------- + Execute the master server function. + + Start all the other servers. +-----------------------------------------------------------------------------*/ + const char *hostName; + int portNum; + int masterSocket; + /* The file descriptor for the socket on which the master listens */ + int ioPortNum[MAX_IO_SERVERS]; + int combinePortNum, decodePortNum; + struct childState * childState; /* malloc'ed */ + unsigned int numIoServers; + time_t startUpBegin, startUpEnd; + time_t shutDownBegin, shutDownEnd; + const char * error; + struct scheduler scheduler; + + time(&startUpBegin); + + scheduler.nextFrame = 0; + scheduler.numFramesInJob = inputSourceP->numInputFiles; + scheduler.numMachines = numMachines; + + PrintStartStats(startUpBegin, FALSE, 0, 0, inputSourceP); + + hostName = GetHostName(); + + hostEntry = gethostbyname(hostName); + if (hostEntry == NULL) + errorExit("Could not find host name '%s' in database", hostName); + + CreateListeningSocket(&masterSocket, &portNum, &error); + if (error) + errorExit("Unable to create socket on which to listen. %s", error); + + if (debugSockets) + fprintf(stdout, "---MASTER USING PORT %d\n", portNum); + + startCombineServer(encoder_name, numMachines, hostName, portNum, + inputSourceP->numInputFiles, + paramFileName, masterSocket, + &combinePortNum); + + if (referenceFrame == DECODED_FRAME) + startDecodeServer(encoder_name, numMachines, hostName, portNum, + inputSourceP->numInputFiles, + paramFileName, masterSocket, + &decodePortNum); + + startChildren(&scheduler, encoder_name, hostName, portNum, + paramFileName, parallelPerfect, forceIalign, + framePatternLen, parallelTestFrames, + niceProcesses, + masterSocket, combinePortNum, decodePortNum, + ioPortNum, &numIoServers, + &childState); + + time(&startUpEnd); + + feedTheChildren(&scheduler, childState, + masterSocket, hostName, combinePortNum, + forceIalign, framePatternLen, + parallelTimeChunks != -1, parallelTimeChunks); + + assert(scheduler.nextFrame == scheduler.numFramesInJob); + + time(&shutDownBegin); + + stopIoServers(hostName, ioPortNum, numIoServers); + + waitForCombineServerToTerminate(masterSocket); + + close(masterSocket); + + time(&shutDownEnd); + + printFinalStats(statFile, startUpBegin, startUpEnd, + shutDownBegin, shutDownEnd, numMachines, + childState, inputSourceP->numInputFiles); + + if (statFile) + fclose(statFile); + + free(childState); + strfree(hostName); +} + + + +void +NotifyMasterDone(const char * const masterHostName, + int const masterPortNum, + int const childNum, + unsigned int const seconds, + boolean * const moreWorkToDoP, + int * const nextFrameStartP, + int * const nextFrameEndP) { +/*---------------------------------------------------------------------------- + Tell the master, at 'masterHostName':'masterPortNum' that child + number 'childNum' has finished its assignment, and the decoding + took 'seconds' wall clock seconds. Get the next assignment, if + any, from the master. + + If the master gives us a new assignment, return *moreWorkToDoP == + TRUE and the frames the master wants us to do as *nextFrameStartP + and nextFrameEndP. Otherwise (there is no more work for machine + 'childNum' to do), return *moreWorkToDoP == FALSE. +-----------------------------------------------------------------------------*/ + int clientSocket; + time_t tempTimeStart, tempTimeEnd; + const char * error; + + machineDebug("CHILD: NOTIFYING MASTER Machine %d assignment complete", + childNum); + + time(&tempTimeStart); + + ConnectToSocket(masterHostName, masterPortNum, &hostEntry, + &clientSocket, &error); + if (error) + errorExit("CHILD: Can't connect to master to tell him we've finished " + "our assignment. %s", error); + + WriteInt(clientSocket, childNum); + WriteInt(clientSocket, seconds); + + ReadInt(clientSocket, nextFrameStartP); + ReadInt(clientSocket, nextFrameEndP); + + *moreWorkToDoP = (*nextFrameStartP >= 0); + + if (*moreWorkToDoP) + machineDebug("CHILD: Master says next assignment: start %d end %d", + *nextFrameStartP, *nextFrameEndP); + else + machineDebug("CHILD: Master says no more work for us."); + + close(clientSocket); + + time(&tempTimeEnd); + IOtime += (tempTimeEnd-tempTimeStart); +} + + + +void +DecodeServer(int const numInputFiles, + const char * const decodeFileName, + const char * const masterHostName, + int const masterPortNum) { +/*---------------------------------------------------------------------------- + Execute the decode server. + + The decode server handles transfer of decoded frames to/from processes. + + It is necessary only if referenceFrame == DECODED_FRAME. + + Communicate to the master at hostname 'masterHostName':'masterPortNum'. + +-----------------------------------------------------------------------------*/ + int otherSock; + int decodePortNum; + int frameReady; + boolean *ready; + int *waitMachine; + int *waitPort; + int *waitList; + int slaveNumber; + int slavePort; + int waitPtr; + struct hostent *nullHost = NULL; + int clientSocket; + const char * error; + + /* should keep list of port numbers to notify when frames become ready */ + + ready = (boolean *) calloc(numInputFiles, sizeof(boolean)); + waitMachine = (int *) calloc(numInputFiles, sizeof(int)); + waitPort = (int *) malloc(numMachines*sizeof(int)); + waitList = (int *) calloc(numMachines, sizeof(int)); + + CreateListeningSocket(&decodeServerSocket, &decodePortNum, &error); + if (error) + errorExit("Unable to create socket on which to listen. %s", error); + + machineDebug("DECODE SERVER LISTENING ON PORT %d", decodePortNum); + + TransmitPortNum(masterHostName, masterPortNum, decodePortNum); + + frameDone = (boolean *) malloc(numInputFiles*sizeof(boolean)); + memset((char *)frameDone, 0, numInputFiles*sizeof(boolean)); + + /* wait for ready signals and requests */ + while ( TRUE ) { + const char * error; + + AcceptConnection(decodeServerSocket, &otherSock, &error); + if (error) + errorExit("DECODE SERVER: " + "Failed to accept next connection. %s", error); + + ReadInt(otherSock, &frameReady); + + if ( frameReady == -2 ) { + ReadInt(otherSock, &frameReady); + + machineDebug("DECODE SERVER: REQUEST FOR FRAME %d", frameReady); + + /* now respond if it's ready yet */ + WriteInt(otherSock, frameDone[frameReady]); + + if ( ! frameDone[frameReady] ) { + /* read machine number, port number */ + ReadInt(otherSock, &slaveNumber); + ReadInt(otherSock, &slavePort); + + machineDebug("DECODE SERVER: WAITING: SLAVE %d, PORT %d", + slaveNumber, slavePort); + + waitPort[slaveNumber] = slavePort; + if ( waitMachine[frameReady] == 0 ) { + waitMachine[frameReady] = slaveNumber+1; + } else { + /* someone already waiting for this frame */ + /* follow list of waiters to the end */ + waitPtr = waitMachine[frameReady]-1; + while ( waitList[waitPtr] != 0 ) { + waitPtr = waitList[waitPtr]-1; + } + + waitList[waitPtr] = slaveNumber+1; + waitList[slaveNumber] = 0; + } + } + } else { + frameDone[frameReady] = TRUE; + + machineDebug("DECODE SERVER: FRAME %d READY", frameReady); + + if ( waitMachine[frameReady] ) { + /* need to notify one or more machines it's ready */ + waitPtr = waitMachine[frameReady]-1; + while ( waitPtr >= 0 ) { + const char * error; + ConnectToSocket(machineName[waitPtr], waitPort[waitPtr], + &nullHost, + &clientSocket, &error); + if (error) + errorExit("DECODE SERVER: " + "Can't connect to child machine. %s", + error); + close(clientSocket); + waitPtr = waitList[waitPtr]-1; + } + } + } + + close(otherSock); + } + + machineDebug("DECODE SERVER: Shutting down"); + + /* tell Master server we are done */ + TransmitPortNum(masterHostName, masterPortNum, decodePortNum); + + close(decodeServerSocket); +} + + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/param.c b/converter/ppm/ppmtompeg/param.c new file mode 100644 index 00000000..5ea69ab6 --- /dev/null +++ b/converter/ppm/ppmtompeg/param.c @@ -0,0 +1,1077 @@ +/*===========================================================================* + * param.c + * + * Procedures to read in parameter file + * + *===========================================================================*/ + +/* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ + +#define _XOPEN_SOURCE 500 + /* This makes sure popen() is in stdio.h. In GNU libc 2.1.3, + _POSIX_C_SOURCE = 2 is sufficient, but on AIX 4.3, the higher level + _XOPEN_SOURCE is required. 2000.09.09 + + This also makes sure strdup() is in string.h. + */ +#define _BSD_SOURCE 1 + /* Make sure string.h defines strncasecmp */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> + +#include "nstring.h" +#include "mallocvar.h" +#include "all.h" +#include "mtypes.h" +#include "mpeg.h" +#include "motion_search.h" +#include "prototypes.h" +#include "parallel.h" +#include "readframe.h" +#include "fsize.h" +#include "frames.h" +#include "jpeg.h" +#include "input.h" +#include "frametype.h" +#include "param.h" + +#include "rate.h" +#include "opts.h" + +/*===========* + * CONSTANTS * + *===========*/ + +#define INPUT_ENTRY_BLOCK_SIZE 128 + +#define FIRST_OPTION 0 +#define OPTION_GOP 0 +#define OPTION_PATTERN 1 +#define OPTION_PIXEL 2 +#define OPTION_PQSCALE 3 +#define OPTION_OUTPUT 4 +#define OPTION_RANGE 5 +#define OPTION_PSEARCH_ALG 6 +#define OPTION_IQSCALE 7 +#define OPTION_INPUT_DIR 8 +#define OPTION_INPUT_CONVERT 9 +#define OPTION_INPUT 10 +#define OPTION_BQSCALE 11 +#define OPTION_BASE_FORMAT 12 +#define OPTION_SPF 13 +#define OPTION_BSEARCH_ALG 14 +#define OPTION_REF_FRAME 15 +#define LAST_OPTION 15 + +/* put any non-required options after LAST_OPTION */ +#define OPTION_RESIZE 16 +#define OPTION_IO_CONVERT 17 +#define OPTION_SLAVE_CONVERT 18 +#define OPTION_IQTABLE 19 +#define OPTION_NIQTABLE 20 +#define OPTION_FRAME_RATE 21 +#define OPTION_ASPECT_RATIO 22 +#define OPTION_YUV_SIZE 23 +#define OPTION_SPECIFICS 24 +#define OPTION_DEFS_SPECIFICS 25 +#define OPTION_BUFFER_SIZE 26 +#define OPTION_BIT_RATE 27 +#define OPTION_USER_DATA 28 +#define OPTION_YUV_FORMAT 29 +#define OPTION_GAMMA 30 +#define OPTION_PARALLEL 31 +#define OPTION_FRAME_INPUT 32 +#define OPTION_GOP_INPUT 33 + +#define NUM_OPTIONS 33 + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern char currentPath[MAXPATHLEN]; +char outputFileName[256]; +int outputWidth, outputHeight; +char inputConversion[1024]; +char ioConversion[1024]; +char slaveConversion[1024]; +char yuvConversion[256]; +char specificsFile[256],specificsDefines[1024]=""; +boolean GammaCorrection=FALSE; +float GammaValue; +char userDataFileName[256]={0}; +boolean specificsOn = FALSE; +char currentGOPPath[MAXPATHLEN]; +char currentFramePath[MAXPATHLEN]; +boolean keepTempFiles; + +static const char * const optionText[LAST_OPTION+1] = { + "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE", + "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR", + "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT", + "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"}; +static boolean optionSeen[NUM_OPTIONS+1]; + /* optionSeen[x] means we have seen option x in the parameter file we've + been reading. + */ + +int numMachines; +char machineName[MAX_MACHINES][256]; +char userName[MAX_MACHINES][256]; +char executable[MAX_MACHINES][1024]; +char remoteParamFile[MAX_MACHINES][1024]; +boolean remote[MAX_MACHINES]; +int mult_seq_headers = 0; /* 0 for none, N for header/N GOPs */ + + +/*===========================================================================* + * + * SkipSpacesTabs + * + * skip all spaces and tabs + * + * RETURNS: point to next character not a space or tab + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static const char * +SkipSpacesTabs(const char * const start) { + + const char * p; + + for (p = start; *p == ' ' || *p == '\t'; ++p); + + return p; +} + + + +/*===========================================================================* + * + * GetAspectRatio + * + * take a character string with the pixel aspect ratio + * and returns the correct aspect ratio code for use in the Sequence header + * + * RETURNS: aspect ratio code as per MPEG-I spec + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int +GetAspectRatio(const char * const p) +{ + float ratio; + int ttRatio; + int retval; + + sscanf(p, "%f", &ratio); + ttRatio = (int)(0.5+ratio*10000.0); + + if ( ttRatio == 10000 ) retval = 1; + else if ( ttRatio == 6735 ) retval = 2; + else if ( ttRatio == 7031 ) retval = 3; + else if ( ttRatio == 7615 ) retval = 4; + else if ( ttRatio == 8055 ) retval = 5; + else if ( ttRatio == 8437 ) retval = 6; + else if ( ttRatio == 8935 ) retval = 7; + else if ( ttRatio == 9157 ) retval = 8; + else if ( ttRatio == 9815 ) retval = 9; + else if ( ttRatio == 10255 ) retval = 10; + else if ( ttRatio == 10695 ) retval = 11; + else if ( ttRatio == 10950 ) retval = 12; + else if ( ttRatio == 11575 ) retval = 13; + else if ( ttRatio == 12015 ) retval = 14; + else { + fprintf(stderr,"INVALID ASPECT RATIO: %s frames/sec\n", p); + exit(1); + } + return retval; +} + + + +/*===========================================================================* + * + * ReadMachineNames + * + * read a list of machine names for parallel execution + * + * RETURNS: nothing + * + * SIDE EFFECTS: machine info updated + * + *===========================================================================*/ +static void +ReadMachineNames(FILE * const fpointer) +{ + char input[256]; + const char *charPtr; + + while ( (fgets(input, 256, fpointer) != NULL) && + (strncmp(input, "END_PARALLEL", 12) != 0) ) { + if ( input[0] == '#' || input[0] == '\n') { + continue; + } + + if ( strncmp(input, "REMOTE", 6) == 0 ) { + charPtr = SkipSpacesTabs(&input[6]); + remote[numMachines] = TRUE; + + sscanf(charPtr, "%s %s %s %s", machineName[numMachines], + userName[numMachines], executable[numMachines], + remoteParamFile[numMachines]); + } else { + remote[numMachines] = FALSE; + + sscanf(input, "%s %s %s", machineName[numMachines], + userName[numMachines], executable[numMachines]); + } + + numMachines++; + } +} + + +/*===========================================================================* + * + * GetFrameRate + * + * take a character string with the input frame rate + * and return the correct frame rate code for use in the Sequence header + * + * RETURNS: frame rate code as per MPEG-I spec + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static int +GetFrameRate(const char * const p) +{ + float rate; + int thouRate; + int retval; + + sscanf(p, "%f", &rate); + thouRate = (int)(0.5+1000.0*rate); + + if ( thouRate == 23976 ) retval = 1; + else if ( thouRate == 24000 ) retval = 2; + else if ( thouRate == 25000 ) retval = 3; + else if ( thouRate == 29970 ) retval = 4; + else if ( thouRate == 30000 ) retval = 5; + else if ( thouRate == 50000 ) retval = 6; + else if ( thouRate == 59940 ) retval = 7; + else if ( thouRate == 60000 ) retval = 8; + else { + fprintf(stderr,"INVALID FRAME RATE: %s frames/sec\n", p); + exit(1); + } + return retval; +} + + + +static void +mergeInputSource(struct inputSource * const baseSourceP, + struct inputSource * const addedSourceP) { + + unsigned int i; + + baseSourceP->ifArraySize += addedSourceP->numInputFileEntries; + REALLOCARRAY_NOFAIL(baseSourceP->inputFileEntries, + baseSourceP->ifArraySize); + for (i = 0; i < addedSourceP->numInputFileEntries; ++i) + baseSourceP->inputFileEntries[baseSourceP->numInputFileEntries++] = + addedSourceP->inputFileEntries[i]; + + free(addedSourceP); + /* Note the space allocated for the *addedSourceP input file + entries themselves is still allocated, and used by + *baseSourceP. + */ +} + + + +/* Forward declaration for recursively called function */ +static void +ReadInputFileNames(FILE * const fpointer, + const char * const endInput, + struct inputSource * const inputSourceP); + +static void +expandBackTickLine(const char * const input, + struct inputSource * const inputSourceP) { + + FILE *fp; + char cmd[300]; + const char * start; + const char * end; + char cdcmd[110]; + + start = &input[1]; + end = &input[strlen(input)-1]; + + while (*end != '`') { + end--; + } + + end--; + + if (optionSeen[OPTION_INPUT_DIR]) + sprintf(cdcmd,"cd %s;",currentPath); + else + strcpy(cdcmd,""); + + { + char tmp[300]; + strncpy(tmp,start,end-start+1); + sprintf(cmd,"(%s %s)", cdcmd, tmp); + } + + fp = popen(cmd, "r"); + if (fp == NULL) { + pm_error("Unable to resolve backtick entry in input file list. " + "Could not open piped command: '%s'", cmd); + } else { + struct inputSource subInputSource; + ReadInputFileNames(fp, "HOPE-THIS_ISNT_A_FILENAME.xyz5555", + &subInputSource); + + mergeInputSource(inputSourceP, &subInputSource); + } +} + + + +static void +ReadInputFileNames(FILE * const fpointer, + const char * const endInput, + struct inputSource * const inputSourceP) { +/*---------------------------------------------------------------------------- + Read a list of input file names from the parameter file. Add + the information to *inputSourceP. + + If inputSourceP == NULL, read off the list, but ignore it. +-----------------------------------------------------------------------------*/ + char input[256]; + bool endStatementRead; + + /* read param file up through endInput statement. Each line until + endInput is a file specification. + */ + endStatementRead = FALSE; + + while (!endStatementRead) { + char * rc; + rc = fgets(input, sizeof(input), fpointer); + + if (feof(fpointer)) + pm_error("End of file before section end statement '%s'", + endInput); + else if (rc == NULL) + pm_error("Error reading file names from parameter file."); + else { + if (strncmp(input, endInput, strlen(endInput)) == 0) + endStatementRead = TRUE; + else if ((input[0] == '#') || (input[0] == '\n')) { + /* It's a comment or blank line. Ignore it */ + } else if (input[0] == '`' ) { + expandBackTickLine(input, inputSourceP); + } else { + /* get rid of trailing whitespace including newline */ + while (ISSPACE(input[strlen(input)-1])) + input[strlen(input)-1] = '\0'; + if (inputSourceP) + AddInputFiles(inputSourceP, input); + } + } + } +} + + + +static void +initOptionSeen(void) { + + unsigned int index; + + for (index = FIRST_OPTION; index < NUM_OPTIONS; ++index) + optionSeen[index] = FALSE; +} + + + +static void +verifyNoMissingEncodeFramesOption(void) { + if (!optionSeen[OPTION_GOP]) + pm_error("GOP_SIZE option missing"); + if (!optionSeen[OPTION_PATTERN]) + pm_error("PATTERN option missing"); + if (!optionSeen[OPTION_PIXEL]) + pm_error("PIXEL option missing"); + if (!optionSeen[OPTION_PQSCALE]) + pm_error("PQSCALE option missing"); + if (!optionSeen[OPTION_OUTPUT]) + pm_error("OUTPUT option missing"); + if (!optionSeen[OPTION_RANGE]) + pm_error("RANGE option missing"); + if (!optionSeen[OPTION_PSEARCH_ALG]) + pm_error("PSEARCH_ALG option missing"); + if (!optionSeen[OPTION_IQSCALE]) + pm_error("IQSCALE option missing"); + if (!optionSeen[OPTION_INPUT_DIR]) + pm_error("INPUT_DIR option missing"); + if (!optionSeen[OPTION_INPUT_CONVERT]) + pm_error("INPUT_CONVERT option missing"); + if (!optionSeen[OPTION_BQSCALE]) + pm_error("BQSCALE option missing"); + if (!optionSeen[OPTION_BASE_FORMAT]) + pm_error("BASE_FILE_FORMAT option missing"); + if (!optionSeen[OPTION_SPF]) + pm_error("SLICES_PER_FRAME option missing"); + if (!optionSeen[OPTION_BSEARCH_ALG]) + pm_error("BSEARCH_ALG option missing"); + if (!optionSeen[OPTION_REF_FRAME]) + pm_error("REFERENCE_FRAME option missing"); +} + + + +static void +verifyNoMissingCombineGopsOption(void) { + + if (!optionSeen[OPTION_GOP_INPUT]) + pm_error("GOP_INPUT option missing"); + if (!optionSeen[OPTION_YUV_SIZE]) + pm_error("YUV_SIZE option missing"); + if (!optionSeen[OPTION_OUTPUT]) + pm_error("OUTPUT option missing"); +} + + + +static void +verifyNoMissingCombineFramesOption(void) { + + if (!optionSeen[OPTION_GOP]) + pm_error("GOP_SIZE option missing"); + if (!optionSeen[OPTION_YUV_SIZE]) + pm_error("YUV_SIZE option missing"); + if (!optionSeen[OPTION_OUTPUT]) + pm_error("OUTPUT option missing"); +} + + + +static void +verifyNoMissingOption(int const function) { +/*---------------------------------------------------------------------------- + Verify that the parameter file contains every option it is supposed to. + Abort program if not. +-----------------------------------------------------------------------------*/ + switch(function) { + case ENCODE_FRAMES: + verifyNoMissingEncodeFramesOption(); + break; + case COMBINE_GOPS: + verifyNoMissingCombineGopsOption(); + break; + case COMBINE_FRAMES: + verifyNoMissingCombineFramesOption(); + break; + default: + pm_error("Internal error - impossible value for 'function': %d", + function); + } +} + + + +static void +processIqtable(FILE * const fpointer) { + + unsigned int row; + unsigned int col; + char input[256]; + + for (row = 0; row < 8; ++row) { + const char * charPtr; + + fgets(input, 256, fpointer); + charPtr = input; + if (8 != sscanf(charPtr,"%d %d %d %d %d %d %d %d", + &qtable[row*8+0], &qtable[row*8+1], + &qtable[row*8+2], &qtable[row*8+3], + &qtable[row*8+4], &qtable[row*8+5], + &qtable[row*8+6], &qtable[row*8+7])) { + pm_error("Line %d of IQTABLE doesn't have 8 elements!", + row); + } + for (col = 0; col < 8; ++col) { + if ((qtable[row*8+col]<1) || (qtable[row*8+col]>255)) { + pm_message( + "Warning: IQTable Element %1d,%1d (%d) " + "corrected to 1-255.", + row+1, col+1, qtable[row*8+col]); + qtable[row*8+col] = (qtable[row*8+col]<1)?1:255; + } + } + } + + if (qtable[0] != 8) { + pm_message("Warning: IQTable Element 1,1 reset to 8, " + "since it must be 8."); + qtable[0] = 8; + } + customQtable = qtable; +} + + + +static void +setInputSource(int const function, + struct inputSource ** const inputSourcePP, + struct inputSource * const inputSourceP, + struct inputSource * const gopInputSourceP, + struct inputSource * const frameInputSourceP) { +/*---------------------------------------------------------------------------- + Given three the three input sources described by the parameter + file, 'inputSourceP', 'gopInputSourceP', and 'frameInputSourceP', + return as *inputSourcePP the appropriate one of them for the + function 'function', and destroy the other two. +-----------------------------------------------------------------------------*/ + switch (function) { + case ENCODE_FRAMES: + *inputSourcePP = inputSourceP; + DestroyInputSource(gopInputSourceP); + DestroyInputSource(frameInputSourceP); + break; + case COMBINE_GOPS: + *inputSourcePP = gopInputSourceP; + DestroyInputSource(inputSourceP); + DestroyInputSource(frameInputSourceP); + break; + case COMBINE_FRAMES: + *inputSourcePP = frameInputSourceP; + DestroyInputSource(inputSourceP); + DestroyInputSource(gopInputSourceP); + break; + default: + pm_error("INTERNAL ERROR: invalid 'function' %d", function); + } +} + + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + + +static void +removeTrailingWhite(const char * const rawLine, + const char ** const editedLineP) { + + char * buffer; + char * p; + + buffer = strdup(rawLine); + + if (!buffer) + pm_error("Unable to get memory to process parameter file"); + + p = buffer + strlen(buffer) - 1; /* Point to last character */ + + /* Position p to just before the trailing white space (might be one + character before beginning of string!) + */ + while (p >= buffer && isspace(*p)) + --p; + + ++p; /* Move to first trailing whitespace character */ + + *p = '\0'; /* Chop off all the trailing whitespace */ + + *editedLineP = buffer; +} + + + +static void +readNiqTable(FILE * const fpointer) { + + unsigned int row; + for (row = 0; row < 8; ++row) { + char input[256]; + unsigned int col; + fgets(input, sizeof(input), fpointer); + if (8 != sscanf(input, "%d %d %d %d %d %d %d %d", + &niqtable[row*8+0], &niqtable[row*8+1], + &niqtable[row*8+2], &niqtable[row*8+3], + &niqtable[row*8+4], &niqtable[row*8+5], + &niqtable[row*8+6], &niqtable[row*8+7])) { + pm_error("Line %d of NIQTABLE doesn't have 8 elements!", + row); + } + for ( col = 0; col < 8; col++ ) { + if ((niqtable[row*8+col]<1) || (niqtable[row*8+col]>255)) { + pm_message( + "Warning: NIQTable Element %1d,%1d (%d) " + "corrected to 1-255.", + row + 1, col + 1, niqtable[row * 8 + col]); + niqtable[row * 8 + col] = (niqtable[row*8+col] < 1) ? 1 : 255; + } + } + } + + customNIQtable = niqtable; +} + + + +static void +processRanges(const char * const arg) { + + int numRanges; + int a, b; + + numRanges = sscanf(arg, "%d %d", &a, &b); + + if (numRanges == 2) + SetSearchRange(a, b); + else if (sscanf(arg, "%d [%d]", &a, &b) == 2) + SetSearchRange(a, b); + else + SetSearchRange(a, a); +} + + + +static void +processParamLine(char const input[], + FILE * const fpointer, + bool * const yuvUsedP, + struct inputSource * const inputSourceP, + struct inputSource * const frameInputSourceP, + struct inputSource * const gopInputSourceP, + struct params * const paramP) { + + switch(input[0]) { + case 'A': + if (STRNEQ(input, "ASPECT_RATIO", 12)) { + aspectRatio = GetAspectRatio(SkipSpacesTabs(&input[12])); + optionSeen[OPTION_ASPECT_RATIO] = TRUE; + } + break; + + case 'B': + if (STRNEQ(input, "BQSCALE", 7)) { + SetBQScale(atoi(SkipSpacesTabs(&input[7]))); + optionSeen[OPTION_BQSCALE] = TRUE; + } else if (STRNEQ(input, "BASE_FILE_FORMAT", 16)) { + const char * arg = SkipSpacesTabs(&input[16]); + SetFileFormat(arg); + if (STRNEQ(arg, "YUV", 3) || STREQ(arg, "Y")) + *yuvUsedP = TRUE; + optionSeen[OPTION_BASE_FORMAT] = TRUE; + } else if (STRNEQ(input, "BSEARCH_ALG", 11)) { + SetBSearchAlg(SkipSpacesTabs(&input[11])); + optionSeen[OPTION_BSEARCH_ALG] = TRUE; + } else if (STRNEQ(input, "BIT_RATE", 8)) { + setBitRate(SkipSpacesTabs(&input[8])); + optionSeen[OPTION_BIT_RATE] = TRUE; + } else if (STRNEQ(input, "BUFFER_SIZE", 11)) { + setBufferSize(SkipSpacesTabs(&input[11])); + optionSeen[OPTION_BUFFER_SIZE] = TRUE; + } + break; + + case 'C': + if (STRNEQ(input, "CDL_FILE", 8)) { + strcpy(specificsFile, SkipSpacesTabs(&input[8])); + specificsOn = TRUE; + optionSeen[OPTION_SPECIFICS] = TRUE; + } else if (STRNEQ(input, "CDL_DEFINES", 11)) { + strcpy(specificsDefines, SkipSpacesTabs(&input[11])); + optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; + } + break; + + case 'F': + if (STRNEQ(input, "FRAME_INPUT_DIR", 15)) { + const char * const arg = SkipSpacesTabs(&input[15]); + if (STRNCASEEQ(arg, "stdin", 5)) + SetStdinInput(frameInputSourceP); + + strcpy(currentFramePath, arg); + } else if (STRNEQ(input, "FRAME_INPUT", 11)) { + ReadInputFileNames(fpointer, "FRAME_END_INPUT", + frameInputSourceP->stdinUsed ? + NULL : frameInputSourceP); + optionSeen[OPTION_FRAME_INPUT] = TRUE; + } else if (STRNEQ(input, "FORCE_I_ALIGN", 13)) { + forceIalign = TRUE; + } else if (STRNEQ(input, "FORCE_ENCODE_LAST_FRAME", 23)) { + /* NO-OP. We used to drop trailing B frames by default and you + needed this option to change the last frame to I so you could + encode all the frames. Now we just do that all the time. + Why wouldn't we? + */ + } else if (STRNEQ(input, "FRAME_RATE", 10)) { + frameRate = GetFrameRate(SkipSpacesTabs(&input[10])); + frameRateRounded = (int) VidRateNum[frameRate]; + if ((frameRate % 3) == 1) + frameRateInteger = FALSE; + optionSeen[OPTION_FRAME_RATE] = TRUE; + } + break; + + case 'G': + if (STRNEQ(input, "GOP_SIZE", 8)) { + SetGOPSize(atoi(SkipSpacesTabs(&input[8]))); + optionSeen[OPTION_GOP] = TRUE; + } else if (STRNEQ(input, "GOP_INPUT_DIR", 13)) { + const char * const arg = SkipSpacesTabs(&input[13]); + if (STRNCASEEQ(arg, "stdin", 5)) + SetStdinInput(gopInputSourceP); + + strcpy(currentGOPPath, arg); + } else if (STRNEQ(input, "GOP_INPUT", 9)) { + ReadInputFileNames(fpointer, "GOP_END_INPUT", + gopInputSourceP->stdinUsed ? + NULL : gopInputSourceP); + optionSeen[OPTION_GOP_INPUT] = TRUE; + } else if (STRNEQ(input, "GAMMA", 5)) { + GammaCorrection = TRUE; + sscanf(SkipSpacesTabs(&input[5]), "%f", &GammaValue); + optionSeen[OPTION_GAMMA] = TRUE; + } + break; + + case 'I': + if (STRNEQ(input, "IQSCALE", 7)) { + SetIQScale(atoi(SkipSpacesTabs(&input[7]))); + optionSeen[OPTION_IQSCALE] = TRUE; + } else if (STRNEQ(input, "INPUT_DIR", 9)) { + const char * const arg = SkipSpacesTabs(&input[9]); + if (STRNCASEEQ(arg, "stdin", 5)) + SetStdinInput(inputSourceP); + strcpy(currentPath, arg); + optionSeen[OPTION_INPUT_DIR] = TRUE; + } else if (STRNEQ(input, "INPUT_CONVERT", 13)) { + strcpy(inputConversion, SkipSpacesTabs(&input[13])); + optionSeen[OPTION_INPUT_CONVERT] = TRUE; + } else if (STREQ(input, "INPUT")) { + ReadInputFileNames(fpointer, "END_INPUT", + inputSourceP->stdinUsed ? + NULL : inputSourceP); + optionSeen[OPTION_INPUT] = TRUE; + } else if (STRNEQ(input, "IO_SERVER_CONVERT", 17)) { + strcpy(ioConversion, SkipSpacesTabs(&input[17])); + optionSeen[OPTION_IO_CONVERT] = TRUE; + } else if (STRNEQ(input, "IQTABLE", 7)) { + processIqtable(fpointer); + + optionSeen[OPTION_IQTABLE] = TRUE; + } + break; + + case 'K': + if (STRNEQ(input, "KEEP_TEMP_FILES", 15)) + keepTempFiles = TRUE; + break; + + case 'N': + if (STRNEQ(input, "NIQTABLE", 8)) { + readNiqTable(fpointer); + + optionSeen[OPTION_NIQTABLE] = TRUE; + } + break; + + case 'O': + if (STRNEQ(input, "OUTPUT", 6)) { + const char * const arg = SkipSpacesTabs(&input[6]); + if ( whichGOP == -1 ) + strcpy(outputFileName, arg); + else + sprintf(outputFileName, "%s.gop.%d", arg, whichGOP); + + optionSeen[OPTION_OUTPUT] = TRUE; + } + break; + + case 'P': + if (STRNEQ(input, "PATTERN", 7)) { + SetFramePattern(SkipSpacesTabs(&input[7])); + optionSeen[OPTION_PATTERN] = TRUE; + } else if (STRNEQ(input, "PIXEL", 5)) { + SetPixelSearch(SkipSpacesTabs(&input[5])); + optionSeen[OPTION_PIXEL] = TRUE; + } else if (STRNEQ(input, "PQSCALE", 7)) { + SetPQScale(atoi(SkipSpacesTabs(&input[7]))); + optionSeen[OPTION_PQSCALE] = TRUE; + } else if (STRNEQ(input, "PSEARCH_ALG", 11)) { + SetPSearchAlg(SkipSpacesTabs(&input[11])); + optionSeen[OPTION_PSEARCH_ALG] = TRUE; + } else if (STRNEQ(input, "PARALLEL_TEST_FRAMES", 20)) { + SetParallelPerfect(FALSE); + parallelTestFrames = atoi(SkipSpacesTabs(&input[20])); + } else if (STRNEQ(input, "PARALLEL_TIME_CHUNKS", 20)) { + SetParallelPerfect(FALSE); + parallelTimeChunks = atoi(SkipSpacesTabs(&input[20])); + } else if (STRNEQ(input, "PARALLEL_CHUNK_TAPER", 20)) { + SetParallelPerfect(FALSE); + parallelTimeChunks = -1; + } else if (STRNEQ(input, "PARALLEL_PERFECT", 16)) { + SetParallelPerfect(TRUE); + } else if (STRNEQ(input, "PARALLEL", 8)) { + ReadMachineNames(fpointer); + optionSeen[OPTION_PARALLEL] = TRUE; + } + break; + + case 'R': + if (STRNEQ(input, "RANGE", 5)) { + processRanges(SkipSpacesTabs(&input[5])); + optionSeen[OPTION_RANGE] = TRUE; + } else if (STRNEQ(input, "REFERENCE_FRAME", 15)) { + SetReferenceFrameType(SkipSpacesTabs(&input[15])); + optionSeen[OPTION_REF_FRAME] = TRUE; + } else if (STRNEQ(input, "RSH", 3)) { + SetRemoteShell(SkipSpacesTabs(&input[3])); + } else if (STRNEQ(input, "RESIZE", 6)) { + const char * const arg = SkipSpacesTabs(&input[6]); + sscanf(arg, "%dx%d", &outputWidth, &outputHeight); + outputWidth &= ~(DCTSIZE * 2 - 1); + outputHeight &= ~(DCTSIZE * 2 - 1); + optionSeen[OPTION_RESIZE] = TRUE; + } + break; + + case 'S': + if (STRNEQ(input, "SLICES_PER_FRAME", 16)) { + SetSlicesPerFrame(atoi(SkipSpacesTabs(&input[16]))); + optionSeen[OPTION_SPF] = TRUE; + } else if (STRNEQ(input, "SLAVE_CONVERT", 13)) { + strcpy(slaveConversion, SkipSpacesTabs(&input[13])); + optionSeen[OPTION_SLAVE_CONVERT] = TRUE; + } else if (STRNEQ(input, "SPECIFICS_FILE", 14)) { + strcpy(specificsFile, SkipSpacesTabs(&input[14])); + specificsOn = TRUE; + optionSeen[OPTION_SPECIFICS] = TRUE; + } else if (STRNEQ(input, "SPECIFICS_DEFINES", 16)) { + strcpy(specificsDefines, SkipSpacesTabs(&input[17])); + optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; + } else if (STRNEQ(input, "SEQUENCE_SIZE", 13)) { + mult_seq_headers = atoi(SkipSpacesTabs(&input[13])); + } else if (STRNEQ(input, "SIZE", 4)) { + const char * const arg = SkipSpacesTabs(&input[4]); + sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } + break; + + case 'T': + if (STRNEQ(input, "TUNE", 4)) { + tuneingOn = TRUE; + ParseTuneParam(SkipSpacesTabs(&input[4])); + } + break; + + case 'U': + if (STRNEQ(input, "USER_DATA", 9)) { + strcpy(userDataFileName, SkipSpacesTabs(&input[9])); + optionSeen[OPTION_USER_DATA] = TRUE; + } + break; + + case 'W': + if (STRNEQ(input, "WARN_UNDERFLOW", 14)) + paramP->warnUnderflow = TRUE; + if (STRNEQ(input, "WARN_OVERFLOW", 13)) + paramP->warnOverflow = TRUE; + break; + + case 'Y': + if (STRNEQ(input, "YUV_SIZE", 8)) { + const char * const arg = SkipSpacesTabs(&input[8]); + sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } else if (STRNEQ(input, "Y_SIZE", 6)) { + const char * const arg = SkipSpacesTabs(&input[6]); + sscanf(arg, "%dx%d", &yuvWidth, &yuvHeight); + realWidth = yuvWidth; + realHeight = yuvHeight; + Fsize_Validate(&yuvWidth, &yuvHeight); + optionSeen[OPTION_YUV_SIZE] = TRUE; + } else if (STRNEQ(input, "YUV_FORMAT", 10)) { + strcpy(yuvConversion, SkipSpacesTabs(&input[10])); + optionSeen[OPTION_YUV_FORMAT] = TRUE; + } + break; + } +} + + + +/*===========================================================================* + * + * ReadParamFile + * + * read the parameter file + * function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and + * will slightly modify the procedure's behavior as to what it + * is looking for in the parameter file + * + * SIDE EFFECTS: sets parameters accordingly, as well as machine info for + * parallel execution and input file names + * + *===========================================================================*/ +void +ReadParamFile(const char * const fileName, + int const function, + struct params * const paramP) { + + FILE *fpointer; + char buffer[256]; + bool yuvUsed; + struct inputSource * inputSourceP; + /* Contents of INPUT section */ + struct inputSource * frameInputSourceP; + /* Contents of FRAME_INPUT section */ + struct inputSource * gopInputSourceP; + /* Contents of GOP_INPUT section */ + + fpointer = fopen(fileName, "r"); + if (fpointer == NULL) + pm_error("Error: Cannot open parameter file: %s", fileName); + + CreateInputSource(&inputSourceP); + CreateInputSource(&frameInputSourceP); + CreateInputSource(&gopInputSourceP); + + /* should set defaults */ + numMachines = 0; + sprintf(currentPath, "."); + sprintf(currentGOPPath, "."); + sprintf(currentFramePath, "."); + SetRemoteShell("rsh"); + keepTempFiles = FALSE; + paramP->warnOverflow = FALSE; + paramP->warnUnderflow = FALSE; + + initOptionSeen(); + + yuvUsed = FALSE; /* initial value */ + + while (fgets(buffer, 256, fpointer) != NULL) { + const char * input; + + removeTrailingWhite(buffer, &input); + + if (strlen(input) == 0) { + /* Ignore blank line */ + } else if (input[0] == '#') { + /* Ignore comment */ + } else + processParamLine(input, fpointer, &yuvUsed, + inputSourceP, frameInputSourceP, gopInputSourceP, + paramP); + /* May read additional lines from file */ + + strfree(input); + } + + fclose(fpointer); + + setInputSource(function, ¶mP->inputSourceP, + inputSourceP, gopInputSourceP, frameInputSourceP); + + verifyNoMissingOption(function); + + /* error checking */ + + if (!paramP->inputSourceP->stdinUsed && + paramP->inputSourceP->numInputFiles == 0) + pm_error("You have not specified any input. See the " + "INPUT_DIR, INPUT, GOP_INPUT_DIR, GOP_INPUT, " + "FRAME_INPUT_DIR, and FRAME_INPUT options"); + + if (yuvUsed) { + if (!optionSeen[OPTION_YUV_SIZE]) + pm_error("YUV format used but YUV_SIZE not given"); + + if (!optionSeen[OPTION_YUV_FORMAT]) { + strcpy (yuvConversion, "EYUV"); + pm_message("WARNING: YUV format not specified; " + "defaulting to Berkeley YUV (EYUV)"); + } + } + + if (paramP->inputSourceP->stdinUsed && optionSeen[OPTION_PARALLEL] ) + pm_error("stdin reading for parallel execution not enabled yet."); + + if (optionSeen[OPTION_PARALLEL] && !optionSeen[OPTION_YUV_SIZE]) + pm_error("Specify SIZE WxH for parallel encoding"); + + if (optionSeen[OPTION_IO_CONVERT] != optionSeen[OPTION_SLAVE_CONVERT]) + pm_error("Must have either both IO_SERVER_CONVERT and SLAVE_CONVERT " + "or neither"); + + if (optionSeen[OPTION_DEFS_SPECIFICS] && !optionSeen[OPTION_SPECIFICS]) + pm_error("Does not make sense to define Specifics file options, " + "but no specifics file!"); + + SetIOConvert(optionSeen[OPTION_IO_CONVERT]); + + SetResize(optionSeen[OPTION_RESIZE]); + + if (function == ENCODE_FRAMES) { + SetFCode(); + + if (psearchAlg == PSEARCH_TWOLEVEL) + SetPixelSearch("HALF"); + } +} + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/parse_huff.pl b/converter/ppm/ppmtompeg/parse_huff.pl new file mode 100644 index 00000000..1fc6466c --- /dev/null +++ b/converter/ppm/ppmtompeg/parse_huff.pl @@ -0,0 +1,198 @@ +# +# Copyright (c) 1993 The Regents of the University of California. +# All rights reserved. +# +# Permission to use, copy, modify, and distribute this software and its +# documentation for any purpose, without fee, and without written agreement is +# hereby granted, provided that the above copyright notice and the following +# two paragraphs appear in all copies of this software. +# +# IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT +# OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF +# CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +# ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO +# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +# + +# +# $Header: /n/picasso/users/dwallach/vid2/mpeg_encode/RCS/parse_huff.pl,v 1.3 1993/01/18 10:56:03 dwallach Exp $ +# $Log: parse_huff.pl,v $ +# Revision 1.3 1993/01/18 10:56:03 dwallach +# got RCS headers in huff.c and huff.h working +# +# Revision 1.3 1993/01/18 10:56:03 dwallach +# got RCS headers in huff.c and huff.h working +# +# Revision 1.2 1993/01/18 10:17:29 dwallach +# RCS headers installed, code indented uniformly +# +# Revision 1.2 1993/01/18 10:17:29 dwallach +# RCS headers installed, code indented uniformly +# +# + +# this program's purpose in life is to parse the Huffman tables +# and output C code which is awfully useful for translation + +# typical usage: +# perl parse_huff.pl huffman.table +# ---> generates huff.c and huff.h + +# source format: # is a comment character +# Otherwise, there are three tab-separated fields in a line: +# Run, Level, and VLC Code +# Run and Level are integers, corresponding to the RLE coding. +# The VLC code is what bits to generate, and is expected to be +# composed of 1, 0, space, and 's'. Spaces are ignored, and +# s corresponds to the sign bit. In the output of this program, +# We'll completely right-shift the data, with a 0 for the sign +# bit. The encoder will make appropriate changes before outputing. + + +open(HUFFC, "> huff.c") || die "Can't write huff.c: $!\n"; +open(HUFFH, "> huff.h") || die "Can't write huff.h: $!\n"; + +sub encode { + local($run, $level, $vlc) = @_; + local($result) = 0; + local($tmp); + $vlc =~ s/\s//g; # remove whitespace + + local($bits) = length($vlc); + + foreach (split(//, $vlc)) { + $_ = 0 if $_ eq 's'; + $result = ($result << 1) + $_; + } + + $tmp = sprintf("0x%x", $result); + eval "\$vlc$run[$level] = \$tmp"; + eval "\$bits$run[$level] = \$bits"; +} + +while(<>) { + chop; + s/\s*#.*$//; # remove comments + next if /^\s*$/; # continue if the line is purely whitespace + + ($run, $level, $vlc) = split(/\t/); + &encode($run, $level, $vlc); + + # + # we have the +1's to insure the sizes of C arrays are correct + # + $maxlevel[$run] = $level+1 if $level >= $maxlevel[$run]; + $maxlevel = $level+1 if $level >= $maxlevel; + $maxrun = $run+1 if $run >= $maxrun; +} + +# +# fix the entries that aren't defined +# +for($run = 0; $run < $maxrun; $run++) { + eval "\$vlc$run[0] = '0x0' if \$vlc$run[0] eq ''"; + eval "\$bits$run[0] = '0' if \$bits$run[0] eq ''"; +} + +# +# now, output some C code +# + +printf HUFFC <<'EOF', $maxrun, join(", ", @maxlevel); +/* + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/users/dwallach/vid2/mpeg_encode/RCS/parse_huff.pl,v 1.3 1993/01/18 10:56:03 dwallach Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#include "mtypes.h" +#include "huff.h" + +int huff_maxlevel[%s] = { %s }; + +EOF +for($run = 0; $run < $maxrun; $run++) { + printf HUFFC <<EOF, eval "join(', ', \@vlc$run)", eval "join(', ', \@bits$run)"; +uint32 huff_table$run[$maxlevel[$run]] = { %s }; +int huff_bits$run[$maxlevel[$run]] = { %s }; + +EOF +} + +printf HUFFC "uint32 *huff_table[$maxrun] = { "; +for($run = 0; $run < $maxrun; $run++) { + printf HUFFC "%shuff_table$run", ($run)?", ":""; +} +printf HUFFC " };\n"; + +printf HUFFC "int *huff_bits[$maxrun] = { "; +for($run = 0; $run < $maxrun; $run++) { + printf HUFFC "%shuff_bits$run", ($run)?", ":""; +} +printf HUFFC " };\n"; +close HUFFC; + +printf HUFFH <<'EOF', $maxrun, $maxlevel; +/* + * Copyright (c) 1993 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/users/dwallach/vid2/mpeg_encode/RCS/parse_huff.pl,v 1.3 1993/01/18 10:56:03 dwallach Exp $ + */ + +/* + * THIS FILE IS MACHINE GENERATED! DO NOT EDIT! + */ +#define HUFF_MAXRUN %s +#define HUFF_MAXLEVEL %s + +extern int huff_maxlevel[]; +extern uint32 *huff_table[]; +extern int *huff_bits[]; +EOF + diff --git a/converter/ppm/ppmtompeg/pframe.c b/converter/ppm/ppmtompeg/pframe.c new file mode 100644 index 00000000..e72fe5d6 --- /dev/null +++ b/converter/ppm/ppmtompeg/pframe.c @@ -0,0 +1,1072 @@ +/*===========================================================================* + * pframe.c + * + * Procedures concerned with generation of P-frames + * + * EXPORTED PROCEDURES: + * GenPFrame + * ResetPFrameStats + * ShowPFrameSummary + * EstimateSecondsPerPFrame + * ComputeHalfPixelData + * SetPQScale + * GetPQScale + * + * NOTE: when motion vectors are passed as arguments, they are passed as + * twice their value. In other words, a motion vector of (3,4) will + * be passed as (6,8). This allows half-pixel motion vectors to be + * passed as integers. This is true throughout the program. + * + *===========================================================================*/ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <sys/param.h> +#include "pm.h" +#include "pm_c_util.h" +#include "all.h" +#include "mtypes.h" +#include "bitio.h" +#include "frames.h" +#include "motion_search.h" +#include "prototypes.h" +#include "block.h" +#include "param.h" +#include "mheaders.h" +#include "fsize.h" +#include "postdct.h" +#include "mpeg.h" +#include "parallel.h" +#include "rate.h" +#include "opts.h" +#include "specifics.h" + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int32 zeroDiff; +static int numPIBlocks = 0; +static int numPPBlocks = 0; +static int numPSkipped = 0; +static int numPIBits = 0; +static int numPPBits = 0; +static int numFrames = 0; +static int numFrameBits = 0; +static int32 totalTime = 0; +static int qscaleP; +static float totalSNR = 0.0; +static float totalPSNR = 0.0; +extern Block **dct, **dctr, **dctb; +extern dct_data_type **dct_data; + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +static vector +halfVector(vector const vector) { + struct vector half; + + half.y = vector.y/2; + half.x = vector.x/2; + + return half; +} + +/*===========================================================================* + * + * decide if (0,0) motion is better than the given motion vector + * + * RETURNS: TRUE if (0,0) is better, FALSE if (my,mx) is better + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). 'zeroDiff' has already been computed + * as the LumMotionError() with (0,0) motion + * + * NOTES: This procedure follows the algorithm described on + * page D-48 of the MPEG-1 specification + * + *===========================================================================*/ +static boolean +ZeroMotionBetter(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector const m) { + + int bestDiff; + int CompareMode; + + /* Junk needed to adapt for TUNEing */ + CompareMode = SearchCompareMode; + SearchCompareMode = DEFAULT_SEARCH; + bestDiff = LumMotionError(currentBlockP, prev, by, bx, m, 0x7fffffff); + SearchCompareMode = CompareMode; + + if ( zeroDiff < 256*3 ) { + if ( 2*bestDiff >= zeroDiff ) { + return TRUE; + } + } else { + if ( 11*bestDiff >= 10*zeroDiff ) { + return TRUE; + } + } + return FALSE; +} + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * DoIntraCode + * + * decide if intra coding is necessary + * + * RETURNS: TRUE if intra-block coding is better; FALSE if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). + * + * NOTES: This procedure follows the algorithm described on + * page D-49 of the MPEG-1 specification + * + *===========================================================================*/ +static boolean +DoIntraCode(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector const motion) { + + unsigned int y; + int32 sum = 0, vard = 0, varc = 0; + int32 currPixel, prevPixel; + LumBlock motionBlock; + + ComputeMotionLumBlock(prev, by, bx, motion, &motionBlock); + + for (y = 0; y < 16; ++y) { + unsigned int x; + for (x = 0; x < 16; ++x) { + currPixel = currentBlockP->l[y][x]; + prevPixel = motionBlock.l[y][x]; + + sum += currPixel; + varc += currPixel*currPixel; + + vard += SQR(currPixel - prevPixel); + } + } + + vard /= 256; /* divide by 256; assumes mean is close to zero */ + varc = (varc/256) - (sum/256) * (sum/256); + + if (vard <= 64) + return FALSE; + else if (vard < varc) + return FALSE; + else + return TRUE; +} + + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * ZeroMotionSufficient + * + * decide if zero motion is sufficient without DCT correction + * + * RETURNS: TRUE no DCT required; FALSE otherwise + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: The relevant block in 'current' is raw YCC data + * + *===========================================================================*/ +static boolean +ZeroMotionSufficient(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx) { + + LumBlock motionBlock; + int fy, fx; + unsigned int y; + + fy = by * DCTSIZE; + fx = bx * DCTSIZE; + for (y = 0; y < 16; ++y) { + unsigned int x; + for (x = 0; x < 16; ++x) { + motionBlock.l[y][x] = prev->ref_y[fy+y][fx+x]; + } + } + + zeroDiff = LumBlockMAD(currentBlockP, &motionBlock, 0x7fffffff); + + return (zeroDiff <= 256); +} + + + +static void +computeCurrentBlock(MpegFrame * const current, + int const y, + int const x, + LumBlock * const currentBlockP) { + int fy, fx; + int iy; + + BLOCK_TO_FRAME_COORD(y, x, fy, fx); + for ( iy = 0; iy < 16; iy++ ) { + int ix; + for ( ix = 0; ix < 16; ix++ ) { + currentBlockP->l[iy][ix] = + (int16)current->orig_y[fy+iy][fx+ix]; + } + } +} + + + +static void +computeMotionVectors(bool const specificsOn, + bool const IntraPBAllowed, + MpegFrame * const current, + MpegFrame * const prev, + int const mbAddress, + BlockMV ** const infoP, + int const QScale, + const LumBlock * const currentBlockP, + int const y, + int const x, + bool * const useMotionP, + vector * const motionP) { + + bool useCached; + BlockMV * info; + + /* See if we have a cached answer */ + if (specificsOn) { + SpecLookup(current->id, 2, mbAddress, &info, QScale); + if (info != (BlockMV*)NULL) + useCached = TRUE; + else + useCached = FALSE; + } else + useCached = FALSE; + + if (useCached) { + if (info->typ == TYP_SKIP) { + motionP->x = motionP->y = 0; + *useMotionP = TRUE; + } else { /* assume P, since we're a P frame.... */ + motionP->x = info->fx; + motionP->y = info->fy; + *useMotionP = TRUE; + } + } else { + /* see if we should use motion vectors, and if so, what those + * vectors should be + */ + if (ZeroMotionSufficient(currentBlockP, prev, y, x)) { + motionP->x = 0; + motionP->y = 0; + *useMotionP = TRUE; + } else { + vector motion; + motion.y = motion.x = 0; /* initial values */ + PMotionSearch(currentBlockP, prev, y, x, &motion); + if (ZeroMotionBetter(currentBlockP, prev, y, x, motion)) { + motionP->y = 0; + motionP->x = 0; + } else + *motionP = motion; + if (IntraPBAllowed) + *useMotionP = !DoIntraCode(currentBlockP, prev, y, x, motion); + else + *useMotionP = TRUE; + } + } + *infoP = info; +} + + + +static void +calculateForwardDcts(MpegFrame * const current, + int const y, int const x, + Block ** const dct) { + + /* calculate forward dct's */ + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "l\n"); + + mp_fwd_dct_block2(current->y_blocks[y][x], dct[y][x]); + mp_fwd_dct_block2(current->y_blocks[y][x+1], dct[y][x+1]); + mp_fwd_dct_block2(current->y_blocks[y+1][x], dct[y+1][x]); + mp_fwd_dct_block2(current->y_blocks[y+1][x+1], dct[y+1][x+1]); + + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "c\n"); + + mp_fwd_dct_block2(current->cb_blocks[y/2][x/2], dctb[y/2][x/2]); + + mp_fwd_dct_block2(current->cr_blocks[y/2][x/2], dctr[y/2][x/2]); +} + + + +static void +computeMotionAndDct(int const lastBlockY, + int const lastBlockX, + bool const specificsOn, + bool const IntraPBAllowed, + MpegFrame * const current, + MpegFrame * const prev, + BlockMV ** const infoP, + int const QScale, + int const searchRangeP, + Block ** const dct, + int * const numPBlocksP, + int * const numIBlocksP, + int ** const pmvHistogram) { +/*---------------------------------------------------------------------------- + Loop through the frame finding motion/not and DCTing +-----------------------------------------------------------------------------*/ + int mbAddress; + int y; + + mbAddress = 0; + + for (y = 0; y < lastBlockY; y += 2) { + int x; + for (x = 0; x < lastBlockX; x += 2) { + LumBlock currentBlock; + vector motion; + bool useMotion; + + computeCurrentBlock(current, y, x, ¤tBlock); + + computeMotionVectors(specificsOn, IntraPBAllowed, + current, prev, mbAddress, infoP, + QScale, ¤tBlock, y, x, + &useMotion, &motion); + + dct_data[y][x].useMotion = useMotion; + + if (useMotion) { + int pattern; + + (*numPBlocksP)++; + + pattern = 63; + ComputeDiffDCTs(current, prev, y, x, motion, &pattern); + + assert(motion.x + searchRangeP + 1 >= 0); + assert(motion.y + searchRangeP + 1 >= 0); + + if (computeMVHist) { + assert(motion.x + searchRangeP + 1 <= 2*searchRangeP + 2); + assert(motion.y + searchRangeP + 1 <= 2*searchRangeP + 2); + ++pmvHistogram[motion.x + searchRangeP + 1] + [motion.y + searchRangeP + 1]; + } + /* Save specs for next loops */ + dct_data[y][x].pattern = pattern; + dct_data[y][x].fmotionX = motion.x; + dct_data[y][x].fmotionY = motion.y; + } else { + /* output I-block inside a P-frame */ + ++*numIBlocksP; + + calculateForwardDcts(current, y, x, dct); + } + ++mbAddress; + } + } +} + + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * GenPFrame + * + * generate a P-frame from previous frame, adding the result to the + * given bit bucket + * + * RETURNS: frame appended to bb + * + *===========================================================================*/ +void +GenPFrame(BitBucket * const bb, + MpegFrame * const current, + MpegFrame * const prev) { + + extern int **pmvHistogram; + FlatBlock fba[6], fb[6]; + Block dec[6]; + int32 y_dc_pred, cr_dc_pred, cb_dc_pred; + int x, y; + vector motion; + vector oldMotion; + int offsetX, offsetY; + vector motionRem; + vector motionQuot; + int pattern; + int mbAddrInc = 1; + int numIBlocks = 0; + int numPBlocks = 0; + int numSkipped = 0; + int numIBits = 0; + int numPBits = 0; + int totalBits; + int totalFrameBits; + int32 startTime, endTime; + int lastBlockX, lastBlockY; + int lastX, lastY; + int mbAddress; + int slicePos; + register int index; + float snr[3], psnr[3]; + int QScale; + BlockMV *info; + int bitstreamMode, newQScale; + int rc_blockStart = 0; + boolean overflowChange = FALSE; + int overflowValue = 0; + + + oldMotion.x = oldMotion.y = 0; + + if (collect_quant) {fprintf(collect_quant_fp, "# P\n");} + if (dct==NULL) AllocDctBlocks(); + numFrames++; + totalFrameBits = bb->cumulativeBits; + startTime = time_elapsed(); + + DBG_PRINT(("Generating pframe\n")); + + QScale = GetPQScale(); + /* bit allocation for rate control purposes */ + bitstreamMode = getRateMode(); + if (bitstreamMode == FIXED_RATE) { + targetRateControl(current); + } + + Mhead_GenPictureHeader(bb, P_FRAME, current->id, fCodeP); + /* Check for Qscale change */ + if (specificsOn) { + /* Set a Qscale for this frame? */ + newQScale = + SpecLookup(current->id, 0, 0 /* junk */, &info /*junk*/, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + /* Set for slice? */ + newQScale = SpecLookup(current->id, 1, 1, &info /*junk*/, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + DBG_PRINT(("Slice Header\n")); + Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); + + if ( referenceFrame == DECODED_FRAME ) { + Frame_AllocDecoded(current, TRUE); + } else if ( printSNR ) { + Frame_AllocDecoded(current, FALSE); + } + + /* don't do dct on blocks yet */ + Frame_AllocBlocks(current); + BlockifyFrame(current); + + /* for I-blocks */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + totalBits = bb->cumulativeBits; + + if ( (! pixelFullSearch) && (! prev->halfComputed) ) { + ComputeHalfPixelData(prev); + } + + lastBlockX = Fsize_x>>3; + lastBlockY = Fsize_y>>3; + lastX = lastBlockX-2; + lastY = lastBlockY-2; + + computeMotionAndDct(lastBlockY, lastBlockX, + specificsOn, IntraPBAllowed, current, prev, + &info, QScale, searchRangeP, dct, + &numPBlocks, &numIBlocks, pmvHistogram); + + mbAddress = 0; + for (y = 0; y < lastBlockY; y += 2) { + for (x = 0; x < lastBlockX; x += 2) { + slicePos = (mbAddress % blocksPerSlice); + + if ( (slicePos == 0) && (mbAddress != 0) ) { + if (specificsOn) { + /* Make sure no slice Qscale change */ + newQScale = + SpecLookup(current->id, 1, mbAddress/blocksPerSlice, + &info /*junk*/, QScale); + if (newQScale != -1) QScale = newQScale; + } + + Mhead_GenSliceEnder(bb); + Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); + + /* reset everything */ + oldMotion.x = oldMotion.y = 0; + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + mbAddrInc = 1+(x>>1); + } + + /* Determine if new Qscale needed for Rate Control purposes */ + if (bitstreamMode == FIXED_RATE) { + rc_blockStart = bb->cumulativeBits; + newQScale = needQScaleChange(qscaleP, + current->y_blocks[y][x], + current->y_blocks[y][x+1], + current->y_blocks[y+1][x], + current->y_blocks[y+1][x+1]); + if (newQScale > 0) { + QScale = newQScale; + } + } + + /* Check for Qscale change */ + if (specificsOn) { + newQScale = + SpecLookup(current->id, 2, mbAddress, &info, QScale); + if (newQScale != -1) { + QScale = newQScale; + } + } + + if (! dct_data[y][x].useMotion) { + GEN_I_BLOCK(P_FRAME, current, bb, mbAddrInc, QScale); + mbAddrInc = 1; + + numIBits += (bb->cumulativeBits-totalBits); + totalBits = bb->cumulativeBits; + + /* reset because intra-coded */ + oldMotion.x = oldMotion.y = 0; + + if ( decodeRefFrames ) { + /* need to decode block we just encoded */ + Mpost_UnQuantZigBlock(fb[0], dec[0], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[1], dec[1], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[2], dec[2], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[3], dec[3], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[4], dec[4], QScale, TRUE); + Mpost_UnQuantZigBlock(fb[5], dec[5], QScale, TRUE); + + /* now, reverse the DCT transform */ + for ( index = 0; index < 6; index++ ) { + mpeg_jrevdct((int16 *)dec[index]); + } + + /* now, unblockify */ + BlockToData(current->decoded_y, dec[0], y, x); + BlockToData(current->decoded_y, dec[1], y, x+1); + BlockToData(current->decoded_y, dec[2], y+1, x); + BlockToData(current->decoded_y, dec[3], y+1, x+1); + BlockToData(current->decoded_cb, dec[4], y>>1, x>>1); + BlockToData(current->decoded_cr, dec[5], y>>1, x>>1); + } + } else { + int fCode = fCodeP; + + /* reset because non-intra-coded */ + y_dc_pred = cr_dc_pred = cb_dc_pred = 128; + + pattern = dct_data[y][x].pattern; + motion.x = dct_data[y][x].fmotionX; + motion.y = dct_data[y][x].fmotionY; + +#ifdef BLEAH + ComputeAndPrintPframeMAD(currentBlock, prev, y, x, motion, + mbAddress); +#endif + + if ( pixelFullSearch ) { /* should be even */ + motion.y /= 2; + motion.x /= 2; + } + + /* transform the motion vector into the appropriate values */ + offsetX = motion.x - oldMotion.x; + offsetY = motion.y - oldMotion.y; + /* if ((offsetX+(8*x)) >= (Fsize_x-8)) log(10.0); */ + encodeMotionVector(offsetX, offsetY, &motionQuot, &motionRem, + FORW_F, fCode); + +#ifdef BLEAH + if ( (motion.x != 0) || (motion.y != 0) ) { + fprintf(stdout, "FRAME (y, x) %d, %d (block %d)\n", + y, x, mbAddress); + fprintf(stdout, "motion.x = %d, motion.y = %d\n", + motion.x, motion.y); + fprintf(stdout, + " mxq, mxr = %d, %d myq, myr = %d, %d\n", + motionQuot.x, motionRem.x, + motionQuot.y, motionRem.y); + } +#endif + + oldMotion = motion; + + if ( pixelFullSearch ) { /* reset for use with PMotionSearch */ + motion.y *= 2; + motion.x *= 2; + } + calc_blocks: + /* create flat blocks and update pattern if necessary */ + /* Note DoQuant references QScale, overflowChange, + overflowValue, pattern, and the calc_blocks label */ + DoQuant(0x20, dct[y][x], fba[0]); + DoQuant(0x10, dct[y][x+1], fba[1]); + DoQuant(0x08, dct[y+1][x], fba[2]); + DoQuant(0x04, dct[y+1][x+1], fba[3]); + DoQuant(0x02, dctb[y/2][x/2], fba[4]); + DoQuant(0x01, dctr[y/2][x/2], fba[5]); + + if ( decodeRefFrames) { + for ( index = 0; index < 6; index++ ) { + if ( pattern & (1 << (5-index))) { + Mpost_UnQuantZigBlock(fba[index], dec[index], + QScale, FALSE); + mpeg_jrevdct((int16 *)dec[index]); + } else { + memset((char *)dec[index], 0, sizeof(Block)); + } + } + + /* now add the motion block */ + AddMotionBlock(dec[0], prev->decoded_y, y, x, motion); + AddMotionBlock(dec[1], prev->decoded_y, y, x+1, motion); + AddMotionBlock(dec[2], prev->decoded_y, y+1, x, motion); + AddMotionBlock(dec[3], prev->decoded_y, y+1, x+1, motion); + AddMotionBlock(dec[4], prev->decoded_cb, y/2, x/2, + halfVector(motion)); + AddMotionBlock(dec[5], prev->decoded_cr, y/2, x/2, + halfVector(motion)); + + /* now, unblockify */ + BlockToData(current->decoded_y, dec[0], y, x); + BlockToData(current->decoded_y, dec[1], y, x+1); + BlockToData(current->decoded_y, dec[2], y+1, x); + BlockToData(current->decoded_y, dec[3], y+1, x+1); + BlockToData(current->decoded_cb, dec[4], y/2, x/2); + BlockToData(current->decoded_cr, dec[5], y/2, x/2); + } + + if ((motion.x == 0) && (motion.y == 0)) { + if ( pattern == 0 ) { + /* can only skip if: + * 1) not the last block in frame + * 2) not the last block in slice + * 3) not the first block in slice + */ + + if ( ((y < lastY) || (x < lastX)) && + (slicePos+1 != blocksPerSlice) && + (slicePos != 0) ) { + mbAddrInc++; /* skipped macroblock */ + numSkipped++; + numPBlocks--; + } else { /* first/last macroblock */ + Mhead_GenMBHeader(bb, 2 /* pict_code_type */, + mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCode /* forw_f_code */, + 1 /* back_f_code */, + motionRem.x /* horiz_forw_r */, + motionRem.y /* vert_forw_r */, + 0 /* horiz_back_r */, + 0 /* vert_back_r */, + 1 /* motion_forw */, + motionQuot.x /* m_horiz_forw */, + motionQuot.y /* m_vert_forw */, + 0 /* motion_back */, + 0 /* m_horiz_back */, + 0 /* m_vert_back */, + 0 /* mb_pattern */, + 0 /* mb_intra */); + mbAddrInc = 1; + } + } else { + DBG_PRINT(("MB Header(%d,%d)\n", x, y)); + Mhead_GenMBHeader(bb, 2 /* pict_code_type */, + mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCode /* forw_f_code */, + 1 /* back_f_code */, + 0 /* horiz_forw_r */, + 0 /* vert_forw_r */, + 0 /* horiz_back_r */, + 0 /* vert_back_r */, + 0 /* motion_forw */, + 0 /* m_horiz_forw */, + 0 /* m_vert_forw */, + 0 /* motion_back */, + 0 /* m_horiz_back */, + 0 /* m_vert_back */, + pattern /* mb_pattern */, + 0 /* mb_intra */); + mbAddrInc = 1; + } + } else { + /* DBG_PRINT(("MB Header(%d,%d)\n", x, y)); */ + + Mhead_GenMBHeader(bb, 2 /* pict_code_type */, + mbAddrInc /* addr_incr */, + QScale /* q_scale */, + fCode /* forw_f_code */, + 1 /* back_f_code */, + motionRem.x /* horiz_forw_r */, + motionRem.y /* vert_forw_r */, + 0 /* horiz_back_r */, + 0 /* vert_back_r */, + 1 /* motion_forw */, + motionQuot.x /* m_horiz_forw */, + motionQuot.y /* m_vert_forw */, + 0 /* motion_back */, + 0 /* m_horiz_back */, + 0 /* m_vert_back */, + pattern /* mb_pattern */, + 0 /* mb_intra */); + mbAddrInc = 1; + } + + /* now output the difference */ + { + unsigned int x; + for (x = 0; x < 6; ++x) { + if (GET_ITH_BIT(pattern, 5-x)) + Mpost_RLEHuffPBlock(fba[x], bb); + } + } + numPBits += (bb->cumulativeBits-totalBits); + totalBits = bb->cumulativeBits; + } + + if (overflowChange) { + /* undo an overflow-caused Qscale change */ + overflowChange = FALSE; + QScale -= overflowValue; + overflowValue = 0; + } + + mbAddress++; + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + incMacroBlockBits( bb->cumulativeBits- rc_blockStart); + rc_blockStart = bb->cumulativeBits; + MB_RateOut(TYPE_PFRAME); + } + } + } + + if ( printSNR ) { + BlockComputeSNR(current,snr,psnr); + totalSNR += snr[0]; + totalPSNR += psnr[0]; + } + +#ifdef BLEAHBLEAH + { + FILE *filePtr; + + filePtr = fopen("PFRAME.yuv", "wb"); + + for ( y = 0; y < Fsize_y; y++ ) + { + for ( x = 0; x < Fsize_x; x++ ) + fprintf(filePtr, "%d ", current->decoded_y[y][x]); + fprintf(filePtr, "\n"); + } + + fclose(filePtr); + } +#endif + + Mhead_GenSliceEnder(bb); + /* Rate Control */ + if (bitstreamMode == FIXED_RATE) { + updateRateControl(TYPE_PFRAME); + } + + /* UPDATE STATISTICS */ + endTime = time_elapsed(); + totalTime += (endTime-startTime); + + if ( showBitRatePerFrame ) { + /* ASSUMES 30 FRAMES PER SECOND */ + fprintf(bitRateFile, "%5d\t%8d\n", current->id, + 30*(bb->cumulativeBits-totalFrameBits)); + } + + if ( frameSummary && (! realQuiet) ) { + fprintf(stdout, "FRAME %d (P): I BLOCKS: %d; " + "P BLOCKS: %d SKIPPED: %d (%ld seconds)\n", + current->id, numIBlocks, numPBlocks, numSkipped, + (long)(endTime-startTime)/TIME_RATE); + if ( printSNR ) { + fprintf(stdout, "FRAME %d: SNR: %.1f\t%.1f\t%.1f\t" + "PSNR: %.1f\t%.1f\t%.1f\n", + current->id, snr[0], snr[1], snr[2], + psnr[0], psnr[1], psnr[2]); + } + } + + numFrameBits += (bb->cumulativeBits-totalFrameBits); + numPIBlocks += numIBlocks; + numPPBlocks += numPBlocks; + numPSkipped += numSkipped; + numPIBits += numIBits; + numPPBits += numPBits; +} + + +/*===========================================================================* + * + * ResetPFrameStats + * + * reset the P-frame statistics + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void + ResetPFrameStats() +{ + numPIBlocks = 0; + numPPBlocks = 0; + numPSkipped = 0; + numPIBits = 0; + numPPBits = 0; + numFrames = 0; + numFrameBits = 0; + totalTime = 0; +} + + +/*===========================================================================* + * + * SetPQScale + * + * set the P-frame Q-scale + * + * RETURNS: nothing + * + * SIDE EFFECTS: qscaleP + * + *===========================================================================*/ +void + SetPQScale(qP) +int qP; +{ + qscaleP = qP; +} + + +/*===========================================================================* + * + * GetPQScale + * + * return the P-frame Q-scale + * + * RETURNS: the P-frame Q-scale + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int + GetPQScale() +{ + return qscaleP; +} + + +float +PFrameTotalTime(void) { + return (float)totalTime/(float)TIME_RATE; +} + + + +void +ShowPFrameSummary(unsigned int const inputFrameBits, + unsigned int const totalBits, + FILE * const fpointer) { + + if (numFrames > 0) { + + fprintf(fpointer, "-------------------------\n"); + fprintf(fpointer, "*****P FRAME SUMMARY*****\n"); + fprintf(fpointer, "-------------------------\n"); + + if ( numPIBlocks != 0 ) { + fprintf(fpointer, " I Blocks: %5d (%6d bits) (%5d bpb)\n", + numPIBlocks, numPIBits, numPIBits/numPIBlocks); + } else { + fprintf(fpointer, " I Blocks: %5d\n", 0); + } + + if ( numPPBlocks != 0 ) { + fprintf(fpointer, " P Blocks: %5d (%6d bits) (%5d bpb)\n", + numPPBlocks, numPPBits, numPPBits/numPPBlocks); + } else { + fprintf(fpointer, " P Blocks: %5d\n", 0); + } + + fprintf(fpointer, " Skipped: %5d\n", numPSkipped); + + fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf) (%2.1f%% of total)\n", + numFrames, numFrameBits, numFrameBits/numFrames, + 100.0*(float)numFrameBits/(float)totalBits); + fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", + numFrames*inputFrameBits/numFrameBits, + 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits)); + if ( printSNR ) + fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", + totalSNR/(float)numFrames, totalPSNR/(float)numFrames); + if ( totalTime == 0 ) { + fprintf(fpointer, " Seconds: NONE\n"); + } else { + fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) (%9ld mps)\n", + (long)(totalTime/TIME_RATE), + (float)((float)(TIME_RATE*numFrames)/(float)totalTime), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(24.0*(float)totalTime)), + (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(256.0*24.0*(float)totalTime))); + } + } +} + + + +/*===========================================================================* + * + * EstimateSecondsPerPFrame + * + * compute an estimate of the number of seconds required per P-frame + * + * RETURNS: the estimate, in seconds + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +float + EstimateSecondsPerPFrame() +{ + if ( numFrames == 0 ) { + return 10.0; + } else { + return (float)totalTime/((float)TIME_RATE*(float)numFrames); + } +} + + +/*===========================================================================* + * + * ComputeHalfPixelData + * + * compute all half-pixel data required for half-pixel motion vector + * search (luminance only) + * + * RETURNS: frame->halfX, ->halfY, and ->halfBoth modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void + ComputeHalfPixelData(frame) +MpegFrame *frame; +{ + register int x, y; + + /* we add 1 before dividing by 2 because .5 is supposed to be rounded up + * (see MPEG-1, page D-31) + */ + + if ( frame->halfX == NULL ) { /* need to allocate memory */ + Frame_AllocHalf(frame); + } + + /* compute halfX */ + for ( y = 0; y < Fsize_y; y++ ) { + for ( x = 0; x < Fsize_x-1; x++ ) { + frame->halfX[y][x] = (frame->ref_y[y][x]+ + frame->ref_y[y][x+1]+1)>>1; + } + } + + /* compute halfY */ + for ( y = 0; y < Fsize_y-1; y++ ) { + for ( x = 0; x < Fsize_x; x++ ) { + frame->halfY[y][x] = (frame->ref_y[y][x]+ + frame->ref_y[y+1][x]+1)>>1; + } + } + + /* compute halfBoth */ + for ( y = 0; y < Fsize_y-1; y++ ) { + for ( x = 0; x < Fsize_x-1; x++ ) { + frame->halfBoth[y][x] = (frame->ref_y[y][x]+ + frame->ref_y[y][x+1]+ + frame->ref_y[y+1][x]+ + frame->ref_y[y+1][x+1]+2)>>2; + } + } + + frame->halfComputed = TRUE; +} + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ diff --git a/converter/ppm/ppmtompeg/postdct.c b/converter/ppm/ppmtompeg/postdct.c new file mode 100644 index 00000000..56a23de9 --- /dev/null +++ b/converter/ppm/ppmtompeg/postdct.c @@ -0,0 +1,626 @@ +/*===========================================================================* + * postdct.c * + * * + * Procedures concerned with MPEG post-DCT processing: * + * quantization and RLE Huffman encoding * + * * + * EXPORTED PROCEDURES: * + * Mpost_QuantZigBlock * + * Mpost_RLEHuffIBlock * + * Mpost_RLEHuffPBlock * + * Mpost_UnQuantZigBlock * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/postdct.c,v 1.12 1995/06/21 18:26:39 smoot Exp $ + * $Log: postdct.c,v $ + * Revision 1.12 1995/06/21 18:26:39 smoot + * added length estimator for P-blocks + * + * Revision 1.11 1995/04/23 23:22:59 eyhung + * nothing changed + * + * Revision 1.10 1995/04/14 23:10:46 smoot + * Added overflow detection to MPOST_DCT so it will adjust Qscales (above) + * + * Revision 1.9 1995/02/15 23:15:32 smoot + * killed useless asserts + * + * Revision 1.8 1995/02/01 21:48:41 smoot + * assure out is set properly, short circuit 0 revquant + * + * Revision 1.7 1995/01/30 19:56:37 smoot + * Killed a <0 shift + * + * Revision 1.6 1995/01/25 23:07:33 smoot + * Better DBG_PRINTs, multiply/divide instead of shifts + * + * Revision 1.5 1995/01/19 23:09:10 eyhung + * Changed copyrights + * + * Revision 1.4 1995/01/16 08:17:08 eyhung + * added realQuiet + * + * Revision 1.3 1994/11/12 02:11:58 keving + * nothing + * + * Revision 1.2 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.1 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.11 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.10 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.9 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.8 1993/02/24 18:57:19 keving + * nothing + * + * Revision 1.7 1993/02/23 22:58:36 keving + * nothing + * + * Revision 1.6 1993/02/23 22:54:56 keving + * nothing + * + * Revision 1.5 1993/02/17 23:18:20 dwallach + * checkin prior to keving's joining the project + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include "all.h" +#include "mtypes.h" +#include "bitio.h" +#include "huff.h" +#include "postdct.h" +#include "opts.h" + +/*==================* + * STATIC VARIABLES * + *==================*/ + +/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */ +int ZAG[] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +/* + * possible optimization: reorder the qtable in the correct zigzag order, to + * reduce the number of necessary lookups + * + * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15. + */ +int32 qtable[] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +int32 niqtable[] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16 +}; + +int32 *customQtable = NULL; +int32 *customNIQtable = NULL; + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern boolean realQuiet; + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Mpost_UnQuantZigBlock + * + * unquantize and zig-zag (decode) a single block + * see section 2.4.4.1 of MPEG standard + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_UnQuantZigBlock(in, out, qscale, iblock) + FlatBlock in; + Block out; + int qscale; + boolean iblock; +{ + register int index; + int start; + int position; + register int qentry; + int level, coeff; + + if ( iblock ) { + /* qtable[0] must be 8 */ + out[0][0] = (int16)(in[0] * 8); + + /* don't need to do anything fancy here, because we saved orig + value, not encoded dc value */ + start = 1; + } else { + start = 0; + } + + for ( index = start; index < DCTSIZE_SQ; index++ ) { + position = ZAG[index]; + level = in[index]; + + if (level == 0) { + ((int16 *)out)[position] = 0; + continue; + } + + + if ( iblock ) { + qentry = qtable[position] * qscale; + coeff = (level*qentry)/8; + if ( (coeff & 1) == 0 ) { + if ( coeff < 0 ) { + coeff++; + } else if ( coeff > 0 ) { + coeff--; + } + } + } else { + qentry = niqtable[position] * qscale; + if ( level == 0 ) { + coeff = 0; + } else if ( level < 0 ) { + coeff = (((2*level)-1)*qentry) / 16; + if ( (coeff & 1) == 0 ) { + coeff++; + } + } else { + coeff = (((2*level)+1)*qentry) >> 4; + if ( (coeff & 1) == 0 ) { + coeff--; + } + } + + if ( coeff > 2047 ) { + coeff = 2047; + } else if ( coeff < -2048 ) { + coeff = -2048; + } + } + + ((int16 *)out)[position] = coeff; + } +} + + +/*===========================================================================* + * + * Mpost_QuantZigBlock + * + * quantize and zigzags a block + * + * RETURNS: MPOST_OVERFLOW if a generated value is outside |255| + * MPOST_ZERO if all coeffs are zero + * MPOST_NON_ZERO otherwisw + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +Mpost_QuantZigBlock(in, out, qscale, iblock) + Block in; + FlatBlock out; + register int qscale; + int iblock; +{ + register int i; + register int16 temp; + register int qentry; + register int position; + boolean nonZero = FALSE; + boolean overflow = FALSE; + + DBG_PRINT(("Mpost_QuantZigBlock...\n")); + if (iblock) { + /* + * the DC coefficient is handled specially -- it's not + * sensitive to qscale, but everything else is + */ + temp = ((int16 *) in)[ZAG[0]]; + qentry = qtable[ZAG[0]]; + + if (temp < 0) { + temp = -temp; + temp += (qentry >> 1); + temp /= qentry; + temp = -temp; + } else { + temp += (qentry >> 1); + temp /= qentry; + } + if ( temp != 0 ) { + nonZero = TRUE; + } + out[0] = temp; + + for (i = 1; i < DCTSIZE_SQ; i++) { + position = ZAG[i]; + temp = ((int16 *) in)[position]; + qentry = qtable[position] * qscale; + + /* see 1993 MPEG doc, section D.6.3.4 */ + if (temp < 0) { + temp = -temp; + temp = (temp << 3); /* temp > 0 */ + temp += (qentry >> 1); + temp /= qentry; + temp = -temp; + } else { + temp = (temp << 3); /* temp > 0 */ + temp += (qentry >> 1); + temp /= qentry; + } + + if ( temp != 0 ) { + nonZero = TRUE; + out[i] = temp; + if (temp < -255) { + temp = -255; + overflow = TRUE; + } else if (temp > 255) { + temp = 255; + overflow = TRUE; + } + } else out[i]=0; + } + } else { + for (i = 0; i < DCTSIZE_SQ; i++) { + position = ZAG[i]; + temp = ((int16 *) in)[position]; + + /* multiply by non-intra qtable */ + qentry = qscale * niqtable[position]; + + /* see 1993 MPEG doc, D.6.4.5 */ + temp *= 8; + temp /= qentry; /* truncation toward 0 -- correct */ + + if ( temp != 0 ) { + nonZero = TRUE; + out[i] = temp; + if (temp < -255) { + temp = -255; + overflow = TRUE; + } else if (temp > 255) { + temp = 255; + overflow = TRUE; + } + + } else out[i]=0; + } + } + + if (overflow) return MPOST_OVERFLOW; + if (nonZero) return MPOST_NON_ZERO; + return MPOST_ZERO; +} + + + +/*===========================================================================* + * + * Mpost_RLEHuffIBlock + * + * generate the huffman bits from an I-block + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_RLEHuffIBlock(in, out) + FlatBlock in; + BitBucket *out; +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register uint32 code; + register int nbits; + + /* + * yes, Virginia, we start at 1. The DC coefficient is handled + * specially, elsewhere. Not here. + */ + for (i = 1; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if ( (nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) { + /* + * encode using the Huffman tables + */ + + DBG_PRINT(("rle_huff %02d.%02d: Run %02d, Level %4d\n", i, ZAG[i], nzeros, cur)); + code = (huff_table[nzeros])[acur]; + nbits = (huff_bits[nzeros])[acur]; + + if (cur < 0) { + code |= 1; /* the sign bit */ + } + Bitio_Write(out, code, nbits); + } else { + /* + * encode using the escape code + */ + DBG_PRINT(("Escape\n")); + Bitio_Write(out, 0x1, 6); /* ESCAPE */ + DBG_PRINT(("Run Length\n")); + Bitio_Write(out, nzeros, 6); /* Run-Length */ + + /* + * this shouldn't happen, but the other + * choice is to bomb out and dump core... + * Hmmm, seems to happen with small Qtable entries (1) -srs + */ + if (cur < -255) { + cur = -255; + } else if (cur > 255) { + cur = 255; + } + + DBG_PRINT(("Level\n")); + if (acur < 128) { + Bitio_Write(out, cur, 8); + } else { + if (cur < 0) { + Bitio_Write(out, 0x8001 + cur + 255, 16); + } else { + Bitio_Write(out, cur, 16); + } + } + } + nzeros = 0; + } else { + nzeros++; + } + } + DBG_PRINT(("End of block\n")); + Bitio_Write(out, 0x2, 2); /* end of block marker */ +} + + +/*===========================================================================* + * + * Mpost_RLEHuffPBlock + * + * generate the huffman bits from an P-block + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +Mpost_RLEHuffPBlock(in, out) + FlatBlock in; + BitBucket *out; +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register uint32 code; + register int nbits; + boolean first_dct = TRUE; + + /* + * yes, Virginia, we start at 0. + */ + for (i = 0; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if ((nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) { + /* + * encode using the Huffman tables + */ + + DBG_PRINT(("rle_huff %02d.%02d: Run %02d, Level %4d\n", i, ZAG[i], nzeros, cur)); + if ( first_dct && (nzeros == 0) && (acur == 1) ) { + /* actually, only needs = 0x2 */ + code = (cur == 1) ? 0x2 : 0x3; + nbits = 2; + } else { + code = (huff_table[nzeros])[acur]; + nbits = (huff_bits[nzeros])[acur]; + } + + assert(nbits); + + if (cur < 0) { + code |= 1; /* the sign bit */ + } + Bitio_Write(out, code, nbits); + first_dct = FALSE; + } else { + /* + * encode using the escape code + */ + DBG_PRINT(("Escape\n")); + Bitio_Write(out, 0x1, 6); /* ESCAPE */ + DBG_PRINT(("Run Length\n")); + Bitio_Write(out, nzeros, 6); /* Run-Length */ + + /* + * this shouldn't happen, but the other + * choice is to bomb out and dump core... + * Hmmm, seems to happen with small Qtable entries (1) -srs + */ + if (cur < -255) { + cur = -255; + } else if (cur > 255) { + cur = 255; + } + + DBG_PRINT(("Level\n")); + if (acur < 128) { + Bitio_Write(out, cur, 8); + } else { + if (cur < 0) { + Bitio_Write(out, 0x8001 + cur + 255, 16); + } else { + Bitio_Write(out, cur, 16); + } + } + + first_dct = FALSE; + } + nzeros = 0; + } else { + nzeros++; + } + } + + /* actually, should REALLY return FALSE and not use this! */ + + if ( first_dct ) { /* have to give a first_dct even if all 0's */ + fprintf(stderr, "HUFF called with all-zero coefficients\n"); + fprintf(stderr, "exiting...\n"); + exit(1); + } + + DBG_PRINT(("End of block\n")); + Bitio_Write(out, 0x2, 2); /* end of block marker */ +} + + +/*===========================================================================* + * + * CalcRLEHuffLength + * + * count the huffman bits for an P-block + * + * RETURNS: number of bits + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +CalcRLEHuffLength(in) + FlatBlock in; +{ + register int i; + register int nzeros = 0; + register int16 cur; + register int16 acur; + register int nbits; + register int countbits=0; + boolean first_dct = TRUE; + + for (i = 0; i < DCTSIZE_SQ; i++) { + cur = in[i]; + acur = ABS(cur); + if (cur) { + if ((nzeros < HUFF_MAXRUN) && (acur < huff_maxlevel[nzeros])) { + /* + * encode using the Huffman tables + */ + + if ( first_dct && (nzeros == 0) && (acur == 1) ) { + nbits = 2; + } else { + nbits = (huff_bits[nzeros])[acur]; + } + countbits += nbits; + first_dct = FALSE; + } else { + countbits += 12; /* ESCAPE + runlength */ + + if (acur < 128) { + countbits += 8; + } else { + countbits += 16; + } + + first_dct = FALSE; + } + nzeros = 0; + } else { + nzeros++; + } + } + + countbits += 2; /* end of block marker */ + return countbits; +} diff --git a/converter/ppm/ppmtompeg/ppmtompeg.c b/converter/ppm/ppmtompeg/ppmtompeg.c new file mode 100644 index 00000000..2296e2cb --- /dev/null +++ b/converter/ppm/ppmtompeg/ppmtompeg.c @@ -0,0 +1,722 @@ +/*===========================================================================* + * main.c + * + * Main procedure + * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#define _BSD_SOURCE /* Make sure strdup() is in string.h */ + +#include <assert.h> +#include <sys/utsname.h> + +#include "all.h" +#include "mtypes.h" +#include "mpeg.h" +#include "motion_search.h" +#include "prototypes.h" +#include "param.h" +#include "parallel.h" +#include "readframe.h" +#include "combine.h" +#include "frames.h" +#include "jpeg.h" +#include "specifics.h" +#include "opts.h" +#include "frametype.h" +#include "input.h" +#include "gethostname.h" + +#include "pm_c_util.h" +#include "ppm.h" +#include "nstring.h" + +#include <time.h> + +int main _ANSI_ARGS_((int argc, char **argv)); + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +boolean showBitRatePerFrame; +boolean frameSummary; + +extern time_t IOtime; +int whichGOP = -1; +boolean ioServer = FALSE; +boolean outputServer = FALSE; +boolean decodeServer = FALSE; +int quietTime = 0; +boolean realQuiet = FALSE; +boolean noFrameSummaryOption = FALSE; +boolean debugSockets = FALSE; +boolean debugMachines = FALSE; +boolean bitRateInfoOption = FALSE; +boolean computeMVHist = FALSE; +int baseFormat; +extern boolean specificsOn; +extern FrameSpecList *fsl; +boolean pureDCT=FALSE; +char encoder_name[1024]; +const char * hostname; + + +/*================================* + * External PROCEDURE prototypes * + *================================*/ + +void init_idctref _ANSI_ARGS_((void)); +void init_fdct _ANSI_ARGS_((void)); + + +struct cmdlineInfo { + bool childProcess; + int function; + const char * masterHostname; + int masterPortNumber; + unsigned int outputFrames; + int maxMachines; + const char * paramFileName; + bool specificFrames; + unsigned int frameStart; + unsigned int frameEnd; +}; + + + +static void +parseArgs(int const argc, + char ** const argv, + struct cmdlineInfo * const cmdlineP) { + + int idx; + + if (argc-1 < 1) + pm_error("You must specify at least one argument: the parameter " + "file name"); + + cmdlineP->function = ENCODE_FRAMES; + cmdlineP->childProcess = FALSE; /* initial assumption */ + cmdlineP->outputFrames = 0; + cmdlineP->maxMachines = MAXINT; + cmdlineP->specificFrames = FALSE; + + /* parse the arguments */ + idx = 1; + while ( idx < argc-1 ) { + if ( argv[idx][0] != '-' ) + pm_error("argument '%s', which must be an option because " + "it is not the last argument, " + "does not start with '-'", argv[idx]); + + if ( strcmp(argv[idx], "-stat") == 0 ) { + if ( idx+1 < argc-1 ) { + SetStatFileName(argv[idx+1]); + idx += 2; + } else { + pm_error("Invalid -stat option"); + } + } else if ( strcmp(argv[idx], "-gop") == 0 ) { + if ((cmdlineP->function != ENCODE_FRAMES) || + (cmdlineP->specificFrames)) + pm_error("Invalid -gop option"); + + if ( idx+1 < argc-1 ) { + whichGOP = atoi(argv[idx+1]); + idx += 2; + } else { + pm_error("Invalid -gop option"); + } + } else if ( strcmp(argv[idx], "-frames") == 0 ) { + if ( (cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) ) { + pm_error("invalid -frames option"); + } + + if ( idx+2 < argc-1 ) { + int const frameStart = atoi(argv[idx+1]); + int const frameEnd = atoi(argv[idx+2]); + + if (frameStart > frameEnd) + pm_error("Start frame number %d is greater than end " + "frame number %d", frameStart, frameEnd); + if (frameStart < 0) + pm_error("Start frame number %d is less than zero", + frameStart); + + cmdlineP->specificFrames = TRUE; + cmdlineP->frameStart = frameStart; + cmdlineP->frameEnd = frameEnd; + + idx += 3; + } else + pm_error("-frames needs to be followed by two values"); + } else if (strcmp(argv[idx], "-combine_gops") == 0) { + if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || + (cmdlineP->specificFrames)) { + pm_error("Invalid -combine_gops option"); + } + + cmdlineP->function = COMBINE_GOPS; + idx++; + } else if (strcmp(argv[idx], "-combine_frames") == 0) { + if ((cmdlineP->function != ENCODE_FRAMES) || (whichGOP != -1) || + (cmdlineP->specificFrames)) + pm_error("Invalid -combine_frames option"); + + cmdlineP->function = COMBINE_FRAMES; + idx++; + } else if ( strcmp(argv[idx], "-child") == 0 ) { + if ( idx+7 < argc-1 ) { + int combinePortNumber; + /* This used to be important information, when the child + notified the combine server. Now the master notifies + the combine server after the child notifies the master + it is done. So this value is unused. + */ + cmdlineP->masterHostname = argv[idx+1]; + cmdlineP->masterPortNumber = atoi(argv[idx+2]); + ioPortNumber = atoi(argv[idx+3]); + combinePortNumber = atoi(argv[idx+4]); + decodePortNumber = atoi(argv[idx+5]); + machineNumber = atoi(argv[idx+6]); + remoteIO = atoi(argv[idx+7]); + + IOhostName = cmdlineP->masterHostname; + } else + pm_error("Not enough option values for -child option. " + "Need 7."); + + cmdlineP->childProcess = TRUE; + idx += 8; + } else if ( strcmp(argv[idx], "-io_server") == 0 ) { + if ( idx+2 < argc-1 ) { + cmdlineP->masterHostname = argv[idx+1]; + cmdlineP->masterPortNumber = atoi(argv[idx+2]); + } else { + pm_error("Invalid -io_server option"); + } + + ioServer = TRUE; + idx += 3; + } else if ( strcmp(argv[idx], "-output_server") == 0 ) { + if ( idx+3 < argc-1 ) { + cmdlineP->masterHostname = argv[idx+1]; + cmdlineP->masterPortNumber = atoi(argv[idx+2]); + cmdlineP->outputFrames = atoi(argv[idx+3]); + } else { + pm_error("-output_server option requires 3 option values. " + "You specified %d", argc-1 - idx); + } + + outputServer = TRUE; + idx += 4; + } else if ( strcmp(argv[idx], "-decode_server") == 0 ) { + if ( idx+3 < argc-1 ) { + cmdlineP->masterHostname = argv[idx+1]; + cmdlineP->masterPortNumber = atoi(argv[idx+2]); + cmdlineP->outputFrames = atoi(argv[idx+3]); + } else { + pm_error("Invalid -decode_server option"); + } + + cmdlineP->function = COMBINE_FRAMES; + decodeServer = TRUE; + idx += 4; + } else if ( strcmp(argv[idx], "-nice") == 0 ) { + niceProcesses = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-max_machines") == 0 ) { + if ( idx+1 < argc-1 ) { + cmdlineP->maxMachines = atoi(argv[idx+1]); + } else { + pm_error("Invalid -max_machines option"); + } + + idx += 2; + } else if ( strcmp(argv[idx], "-quiet") == 0 ) { + if ( idx+1 < argc-1 ) { + quietTime = atoi(argv[idx+1]); + } else { + pm_error("Invalid -quiet option"); + } + + idx += 2; + } else if ( strcmp(argv[idx], "-realquiet") == 0 ) { + realQuiet = TRUE; + idx++; + } else if (( strcmp(argv[idx], "-float_dct") == 0 ) || + ( strcmp(argv[idx], "-float-dct") == 0 )) { + pureDCT = TRUE; + init_idctref(); + init_fdct(); + idx++; + } else if ( strcmp(argv[idx], "-no_frame_summary") == 0 ) { + if ( idx < argc-1 ) { + noFrameSummaryOption = TRUE; + } else { + pm_error("Invalid -no_frame_summary option"); + } + + idx++; + } else if ( strcmp(argv[idx], "-snr") == 0 ) { + printSNR = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-mse") == 0 ) { + printSNR = printMSE = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-debug_sockets") == 0 ) { + debugSockets = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-debug_machines") == 0 ) { + debugMachines = TRUE; + idx++; + } else if ( strcmp(argv[idx], "-bit_rate_info") == 0 ) { + if ( idx+1 < argc-1 ) { + bitRateInfoOption = TRUE; + SetBitRateFileName(argv[idx+1]); + idx += 2; + } else { + pm_error("Invalid -bit_rate_info option"); + } + } else if ( strcmp(argv[idx], "-mv_histogram") == 0 ) { + computeMVHist = TRUE; + idx++; + } else { + pm_error("Unrecognized option: '%s'", argv[idx]); + } + } + + cmdlineP->paramFileName = argv[argc-1]; +} + + + +static void +compileTests() { + + /* There was code here (assert() calls) that verified that uint16 + is 16 bits, etc. It caused compiler warnings that said, "Of + course it is!" (actually, "statement has no effect"). There + isn't enough chance that uint16, etc. are defined incorrectly + to warrant those asserts. 2000.05.07 + */ + + if ( (-8 >> 3) != -1 ) { + fprintf(stderr, "ERROR: Right shifts are NOT arithmetic!!!\n"); + fprintf(stderr, "Change >> to multiplies by powers of 2\n"); + exit(1); + } +} + + + +static void +announceJob(enum frameContext const context, + bool const childProcess, + unsigned int const frameStart, + unsigned int const frameEnd, + const char * const outputFileName) { + + if (!realQuiet) { + const char * outputDest; + const char * combineDest; + + if (context == CONTEXT_JUSTFRAMES) + asprintfN(&outputDest, "to individual frame files"); + else + asprintfN(&outputDest, "to file '%s'", outputFileName); + + if (childProcess) + combineDest = strdup("for delivery to combine server"); + else + combineDest = strdup(""); + + pm_message("%s: ENCODING FRAMES %u-%u to %s %s", + hostname, frameStart, frameEnd, outputDest, combineDest); + + strfree(combineDest); + strfree(outputDest); + } +} + + + +static void +encodeSomeFrames(struct inputSource * const inputSourceP, + boolean const childProcess, + enum frameContext const context, + unsigned int const frameStart, + unsigned int const frameEnd, + int32 const qtable[], + int32 const niqtable[], + FILE * const ofp, + const char * const outputFileName, + bool const wantVbvUnderflowWarning, + bool const wantVbvOverflowWarning, + boolean const printStats, + unsigned int * const encodeTimeP) { + + time_t framesTimeStart, framesTimeEnd; + unsigned int inputFrameBits; + unsigned int totalBits; + + announceJob(context, childProcess, frameStart, frameEnd, outputFileName); + + time(&framesTimeStart); + if (printStats) + PrintStartStats(framesTimeStart, context == CONTEXT_JUSTFRAMES, + frameStart, frameEnd, inputSourceP); + + GenMPEGStream(inputSourceP, context, frameStart, frameEnd, + qtable, niqtable, childProcess, ofp, outputFileName, + wantVbvUnderflowWarning, wantVbvOverflowWarning, + &inputFrameBits, &totalBits); + + time(&framesTimeEnd); + + *encodeTimeP = (unsigned int)(framesTimeEnd - framesTimeStart); + + if (!realQuiet) + pm_message("%s: COMPLETED FRAMES %u-%u (%u seconds)", + hostname, frameStart, frameEnd, *encodeTimeP); + + if (printStats) + PrintEndStats(framesTimeStart, framesTimeEnd, + inputFrameBits, totalBits); +} + + + + +static void +encodeFrames(struct inputSource * const inputSourceP, + boolean const childProcess, + const char * const masterHostname, + int const masterPortNumber, + int const whichGOP, + bool const specificFrames, + unsigned int const whichFrameStart, + unsigned int const whichFrameEnd, + int32 const qtable[], + int32 const niqtable[], + FILE * const ofp, + const char * const outputFileName, + bool const wantVbvUnderflowWarning, + bool const wantVbvOverflowWarning) { +/*---------------------------------------------------------------------------- + Encode the stream. If 'specificFrames' is true, then encode frames + 'whichFrameStart' through 'whichFrameEnd' individually. Otherwise, + encode the entire input stream as a complete MPEG stream. + + 'childProcess' means to do it as a child process that is under the + supervision of a master process and is possibly doing only part of + a larger batch. + + (If we had proper modularity, we wouldn't care, but parallel operation + was glued on to this program after it was complete). + + One thing we don't do when running as a child process is print + statistics; our master will do that for the whole job. +----------------------------------------------------------------------------*/ + unsigned int frameStart, frameEnd; + enum frameContext context; + unsigned int lastEncodeTime; + /* How long it took the encoder to do the last set of frames */ + boolean printStats; + /* We want the encoder to print start & end stats */ + + if (whichGOP != -1) { + /* He wants just one particular GOP from the middle of the movie. */ + ComputeGOPFrames(whichGOP, &frameStart, &frameEnd, + inputSourceP->numInputFiles); + context = CONTEXT_GOP; + } else if (specificFrames) { + /* He wants some pure frames from the middle of the movie */ + if (whichFrameStart > whichFrameEnd) + pm_error("You specified a starting frame number (%d) that is " + "greater than the ending frame number (%d) " + "you specified.", whichFrameStart, whichFrameEnd); + if (whichFrameEnd + 1 > inputSourceP->numInputFiles) + pm_error("You specified ending frame number %d, which is " + "beyond the number of input files you supplied (%u)", + whichFrameEnd, inputSourceP->numInputFiles); + + frameStart = whichFrameStart; + frameEnd = whichFrameEnd; + context = CONTEXT_JUSTFRAMES; + } else { + /* He wants the whole movie */ + frameStart = 0; + frameEnd = inputSourceP->numInputFiles - 1; + context = CONTEXT_WHOLESTREAM; + } + + printStats = !childProcess; + + encodeSomeFrames(inputSourceP, childProcess, context, frameStart, frameEnd, + customQtable, customNIQtable, + ofp, outputFileName, + wantVbvUnderflowWarning, wantVbvOverflowWarning, + printStats, + &lastEncodeTime); + + if (childProcess) { + boolean moreWorkToDo; + + /* A child is not capable of generating GOP or stream headers */ + assert(context == CONTEXT_JUSTFRAMES); + + moreWorkToDo = TRUE; /* initial assumption */ + while (moreWorkToDo) { + int nextFrameStart, nextFrameEnd; + + NotifyMasterDone(masterHostname, masterPortNumber, machineNumber, + lastEncodeTime, &moreWorkToDo, + &nextFrameStart, &nextFrameEnd); + if (moreWorkToDo) + encodeSomeFrames(inputSourceP, childProcess, + CONTEXT_JUSTFRAMES, + nextFrameStart, nextFrameEnd, + customQtable, customNIQtable, + NULL, outputFileName, + wantVbvUnderflowWarning, + wantVbvOverflowWarning, + FALSE, + &lastEncodeTime); + } + if (!realQuiet) + pm_message("%s: Child exiting. Master has no more work.", + hostname); + } +} + + + + +static void +runMaster(struct inputSource * const inputSourceP, + const char * const paramFileName, + const char * const outputFileName) { + + if (paramFileName[0] != '/' && paramFileName[0] != '~') + pm_error("For parallel mode, you must " + "use an absolute path for parameter file. " + "You specified '%s'", paramFileName); + else + MasterServer(inputSourceP, paramFileName, outputFileName); +} + + + +static void +getUserFrameFile(void * const handle, + unsigned int const frameNumber, + FILE ** const ifPP) { + + struct inputSource * const inputSourceP = (struct inputSource *) handle; + + if (inputSourceP->stdinUsed) + pm_error("You cannot combine frames from Standard Input."); + /* Because Caller detects end of frames by EOF */ + + if (frameNumber >= inputSourceP->numInputFiles) + *ifPP = NULL; + else { + const char * fileName; + const char * inputFileName; + + GetNthInputFileName(inputSourceP, frameNumber, &inputFileName); + + asprintfN(&fileName, "%s/%s", currentFramePath, inputFileName); + + *ifPP = fopen(fileName, "rb"); + if (*ifPP == NULL) + pm_error("Unable to open file '%s'. Errno = %d (%s)", + fileName, errno, strerror(errno)); + + strfree(inputFileName); + strfree(fileName); + } +} + + + +static void +nullDisposeFile(void * const handle, + unsigned int const frameNumber) { + + +} + + + +static unsigned int +framePoolSize(bool const sequentialInput) { +/*---------------------------------------------------------------------------- + Return the number of frames that our frame memory pool needs to have. + + 'sequentialInput' means we'll be reading from input that comes in frame + number order and we can't go back, so we'll have to have a bigger buffer + of frames than otherwise. +-----------------------------------------------------------------------------*/ + unsigned int numOfFrames; + + numOfFrames = 0; /* initial value */ + + if (sequentialInput) { + unsigned int idx; + unsigned int bcount; + + for ( idx = 0, bcount = 0; idx < strlen(framePattern); idx++) { + + /* counts the maximum number of B frames between two reference + * frames. + */ + + switch( framePattern[idx] ) { + case 'b': + bcount++; + break; + case 'i': + case 'p': + if (bcount > numOfFrames) + numOfFrames = bcount; + bcount = 0; + break; + } + + /* add 2 to hold the forward and past reference frames in addition + * to the maximum number of B's + */ + } + + numOfFrames += 2; + + } else { + /* non-interactive, only 3 frames needed */ + numOfFrames = 3; + } + return numOfFrames; +} + + + +int +main(int argc, char **argv) { + FILE *ofP; + time_t initTimeStart; + struct cmdlineInfo cmdline; + struct params params; + + ppm_init(&argc, argv); + + strcpy(encoder_name, argv[0]); + + compileTests(); + + time(&initTimeStart); + + SetStatFileName(""); + + hostname = GetHostName(); + + parseArgs(argc, argv, &cmdline); + + ReadParamFile(cmdline.paramFileName, cmdline.function, ¶ms); + + /* Jim Boucher's stuff: + if we are using a movie format then break up into frames + */ + if ((!cmdline.childProcess) && (baseFormat == JMOVIE_FILE_TYPE)) + JM2JPEG(params.inputSourceP); + + if (printSNR || (referenceFrame == DECODED_FRAME)) + decodeRefFrames = TRUE; + + showBitRatePerFrame = (bitRateInfoOption && !cmdline.childProcess); + frameSummary = (!noFrameSummaryOption && !cmdline.childProcess); + + numMachines = min(numMachines, cmdline.maxMachines); + + Tune_Init(); + Frame_Init(framePoolSize(params.inputSourceP->stdinUsed)); + + if (specificsOn) + Specifics_Init(); + + ComputeFrameTable(params.inputSourceP->stdinUsed ? + 0 : params.inputSourceP->numInputFiles); + + if (ioServer) { + IoServer(params.inputSourceP, cmdline.masterHostname, + cmdline.masterPortNumber); + return 0; + } else if (outputServer) { + CombineServer(cmdline.outputFrames, + cmdline.masterHostname, cmdline.masterPortNumber, + outputFileName); + } else if (decodeServer) { + DecodeServer(cmdline.outputFrames, outputFileName, + cmdline.masterHostname, cmdline.masterPortNumber); + } else { + if ((!cmdline.specificFrames) && + ((numMachines == 0) || (cmdline.function != ENCODE_FRAMES)) ) { + ofP = fopen(outputFileName, "wb"); + if (ofP == NULL) + pm_error("Could not open output file!"); + } else + ofP = NULL; + + if (cmdline.function == ENCODE_FRAMES) { + if ((numMachines == 0) || (cmdline.specificFrames)) { + encodeFrames(params.inputSourceP, + cmdline.childProcess, + cmdline.masterHostname, cmdline.masterPortNumber, + whichGOP, cmdline.specificFrames, + cmdline.frameStart, cmdline.frameEnd, + customQtable, customNIQtable, + ofP, outputFileName, + params.warnUnderflow, params.warnOverflow); + + } else + runMaster(params.inputSourceP, + cmdline.paramFileName, outputFileName); + } else if (cmdline.function == COMBINE_GOPS) + GOPsToMPEG(params.inputSourceP, outputFileName, ofP); + else if (cmdline.function == COMBINE_FRAMES) + FramesToMPEG(ofP, params.inputSourceP, + &getUserFrameFile, &nullDisposeFile); + } + Frame_Exit(); + + strfree(hostname); + + return 0; +} diff --git a/converter/ppm/ppmtompeg/psearch.c b/converter/ppm/ppmtompeg/psearch.c new file mode 100644 index 00000000..aea1a29b --- /dev/null +++ b/converter/ppm/ppmtompeg/psearch.c @@ -0,0 +1,989 @@ +/*===========================================================================* + * psearch.c + * + * Procedures concerned with the P-frame motion search + * + *===========================================================================*/ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "motion_search.h" +#include "prototypes.h" +#include "fsize.h" +#include "param.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +/* none */ + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +int **pmvHistogram = NULL; /* histogram of P-frame motion vectors */ +int **bbmvHistogram = NULL; /* histogram of B-frame bkwd motion vectors */ +int **bfmvHistogram = NULL; /* histogram of B-frame fwd motion vectors */ +int pixelFullSearch; +int searchRangeP,searchRangeB; +/* The range, in half pixels in each direction, that we are to search + when detecting motion. Specified by RANGE statement in parameter file. + */ +int psearchAlg; +/* specified by parameter file. */ + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * Compute the best P-frame motion vector we can. If it's better than + * *motionP, update *motionP to it. + * + * PRECONDITIONS: The relevant block in 'current' is valid (it has not + * been dct'd). Thus, the data in 'current' can be + * accesed through y_blocks, cr_blocks, and cb_blocks. + * This is not the case for the blocks in 'prev.' + * Therefore, references into 'prev' should be done + * through the struct items ref_y, ref_cr, ref_cb + * + * POSTCONDITIONS: current, prev unchanged. + * Some computation could be saved by requiring + * the dct'd difference to be put into current's block + * elements here, depending on the search technique. + * However, it was decided that it mucks up the code + * organization a little, and the saving in computation + * would be relatively little (if any). + * + * NOTES: the search procedure need not check the (0,0) motion vector + * the calling procedure has a preference toward (0,0) and it + * will check it itself + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +PMotionSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP) { + + /* CALL SEARCH PROCEDURE */ + + switch(psearchAlg) { + case PSEARCH_SUBSAMPLE: + PSubSampleSearch(currentBlockP, prev, by, bx, motionP, searchRangeP); + break; + case PSEARCH_EXHAUSTIVE: + PLocalSearch(currentBlockP, prev, by, bx, + motionP, INT_MAX, searchRangeP); + break; + case PSEARCH_LOGARITHMIC: + PLogarithmicSearch(currentBlockP, prev, by, bx, motionP, searchRangeP); + break; + case PSEARCH_TWOLEVEL: + PTwoLevelSearch(currentBlockP, prev, by, bx, + motionP, INT_MAX, searchRangeP); + break; + default: + pm_error("IMPOSSIBLE PSEARCH ALG: %d", psearchAlg); + } +} + + + +/*===========================================================================* + * + * SetPixelSearch + * + * set the pixel search type (half or full) + * + * RETURNS: nothing + * + * SIDE EFFECTS: pixelFullSearch + * + *===========================================================================*/ +void +SetPixelSearch(const char * const searchType) { + if ( (strcmp(searchType, "FULL") == 0 ) || + ( strcmp(searchType, "WHOLE") == 0 )) { + pixelFullSearch = TRUE; + } else if ( strcmp(searchType, "HALF") == 0 ) { + pixelFullSearch = FALSE; + } else { + fprintf(stderr, "ERROR: Invalid pixel search type: %s\n", + searchType); + exit(1); + } +} + + +/*===========================================================================* + * + * SetPSearchAlg + * + * set the P-search algorithm + * + * RETURNS: nothing + * + * SIDE EFFECTS: psearchAlg + * + *===========================================================================*/ +void +SetPSearchAlg(const char * const alg) +{ + if ( strcmp(alg, "EXHAUSTIVE") == 0 ) { + psearchAlg = PSEARCH_EXHAUSTIVE; + } else if (strcmp(alg, "SUBSAMPLE") == 0 ) { + psearchAlg = PSEARCH_SUBSAMPLE; + } else if ( strcmp(alg, "LOGARITHMIC") == 0 ) { + psearchAlg = PSEARCH_LOGARITHMIC; + } else if ( strcmp(alg, "TWOLEVEL") == 0 ) { + psearchAlg = PSEARCH_TWOLEVEL; + } else { + fprintf(stderr, "ERROR: Invalid psearch algorithm: %s\n", alg); + exit(1); + } +} + + +/*===========================================================================* + * + * PSearchName + * + * returns a string containing the name of the search algorithm + * + * RETURNS: pointer to the string + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +const char * +PSearchName(void) +{ + const char *retval; + + switch(psearchAlg) { + case PSEARCH_EXHAUSTIVE: + retval = "EXHAUSTIVE";break; + case PSEARCH_SUBSAMPLE: + retval = "SUBSAMPLE";break; + case PSEARCH_LOGARITHMIC: + retval = "LOGARITHMIC";break; + case PSEARCH_TWOLEVEL: + retval = "TWOLEVEL";break; + default: + fprintf(stderr, "ERROR: Illegal PSEARCH ALG: %d\n", psearchAlg); + exit(1); + break; + } + return retval; +} + + +/*===========================================================================* + * + * SetSearchRange + * + * sets the range of the search to the given number of pixels, + * allocate histogram storage + * + *===========================================================================*/ +void +SetSearchRange(int const pixelsP, int const pixelsB) { + + searchRangeP = 2*pixelsP; /* +/- 'pixels' pixels */ + searchRangeB = 2*pixelsB; + + if ( computeMVHist ) { + int const max_search = max(searchRangeP, searchRangeB); + + int index; + + pmvHistogram = (int **) malloc((2*searchRangeP+3)*sizeof(int *)); + bbmvHistogram = (int **) malloc((2*searchRangeB+3)*sizeof(int *)); + bfmvHistogram = (int **) malloc((2*searchRangeB+3)*sizeof(int *)); + for ( index = 0; index < 2*max_search+3; index++ ) { + pmvHistogram[index] = + (int *) calloc(2*searchRangeP+3, sizeof(int)); + bbmvHistogram[index] = + (int *) calloc(2*searchRangeB+3, sizeof(int)); + bfmvHistogram[index] = + (int *) calloc(2*searchRangeB+3, sizeof(int)); + } + } +} + + +/*===========================================================================* + * + * USER-MODIFIABLE + * + * MotionSearchPreComputation + * + * do whatever you want here; this is called once per frame, directly + * after reading + * + * RETURNS: whatever + * + * SIDE EFFECTS: whatever + * + *===========================================================================*/ +void +MotionSearchPreComputation(MpegFrame * const frameP) { + /* do nothing */ +} + + +/*===========================================================================* + * + * PSubSampleSearch + * + * uses the subsampling algorithm to compute the P-frame vector + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + * REFERENCE: Liu and Zaccarin: New Fast Algorithms for the Estimation + * of Block Motion Vectors, IEEE Transactions on Circuits + * and Systems for Video Technology, Vol. 3, No. 2, 1993. + * + *===========================================================================*/ +int +PSubSampleSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const searchRange) { + + int my, mx; + int bestBestDiff; + int stepSize; + int x; + int bestMY[4], bestMX[4], bestDiff[4]; + int leftMY, leftMX; + int rightMY, rightMX; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + if ( searchRange < rightMY ) { + rightMY = searchRange; + } + + if ( searchRange < rightMX ) { + rightMX = searchRange; + } + + for ( x = 0; x < 4; x++ ) { + bestMY[x] = 0; + bestMX[x] = 0; + bestDiff[x] = INT_MAX; + } + + /* do A pattern */ + for (my = -searchRange; my < rightMY; my += 2*stepSize) { + if (my >= leftMY) { + for ( mx = -searchRange; mx < rightMX; mx += 2*stepSize ) { + if (mx >= leftMX) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumMotionErrorA(currentBlockP, prev, by, bx, m, + bestDiff[0]); + + if (diff < bestDiff[0]) { + bestMY[0] = my; + bestMX[0] = mx; + bestDiff[0] = diff; + } + } + } + } + } + + /* do B pattern */ + for (my = stepSize-searchRange; my < rightMY; my += 2*stepSize) { + if (my >= leftMY) { + for (mx = -searchRange; mx < rightMX; mx += 2*stepSize) { + if (mx >= leftMX) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumMotionErrorB(currentBlockP, prev, by, bx, m, + bestDiff[1]); + + if (diff < bestDiff[1]) { + bestMY[1] = my; + bestMX[1] = mx; + bestDiff[1] = diff; + } + } + } + } + } + + /* do C pattern */ + for (my = stepSize-searchRange; my < rightMY; my += 2*stepSize) { + if (my >= leftMY) { + for ( mx = stepSize-searchRange; mx < rightMX; mx += 2*stepSize ) { + if (mx >= leftMX) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumMotionErrorC(currentBlockP, prev, by, bx, m, + bestDiff[2]); + + if (diff < bestDiff[2]) { + bestMY[2] = my; + bestMX[2] = mx; + bestDiff[2] = diff; + } + } + } + } + } + + /* do D pattern */ + for (my = -searchRange; my < rightMY; my += 2*stepSize) { + if (my >= leftMY) { + for (mx = stepSize-searchRange; mx < rightMX; mx += 2*stepSize) { + if (mx >= leftMX) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumMotionErrorD(currentBlockP, prev, by, bx, m, + bestDiff[3]); + + if (diff < bestDiff[3]) { + bestMY[3] = my; + bestMX[3] = mx; + bestDiff[3] = diff; + } + } + } + } + } + + /* first check old motion */ + if ((motionP->y >= leftMY) && (motionP->y < rightMY) && + (motionP->x >= leftMX) && (motionP->x < rightMX)) { + bestBestDiff = LumMotionError(currentBlockP, prev, by, bx, + *motionP, INT_MAX); + } else + bestBestDiff = INT_MAX; + + /* look at Error of 4 different motion vectors */ + for (x = 0; x < 4; ++x) { + vector m; + m.y = bestMY[x]; + m.x = bestMX[x]; + bestDiff[x] = LumMotionError(currentBlockP, prev, by, bx, m, + bestBestDiff); + + if (bestDiff[x] < bestBestDiff) { + bestBestDiff = bestDiff[x]; + *motionP = m; + } + } + return bestBestDiff; +} + + + +static void +findBestSpaced(int const minMY, + int const minMX, + int const maxMY, + int const maxMX, + int const spacing, + const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + int * const bestDiffP, + vector * const centerP) { +/*---------------------------------------------------------------------------- + Examine every 'spacing'th half-pixel within the rectangle + ('minBoundX', 'minBoundY', 'maxBoundX', 'maxBoundY'), + + If one of the half-pixels examined has a lower "LumMotionError" value + than *bestDiffP, update *bestDiffP to that value and update + *centerP to the location of that half-pixel. +-----------------------------------------------------------------------------*/ + int const minBoundY = MAX(minMY, centerP->y - spacing); + int const minBoundX = MAX(minMX, centerP->x - spacing); + int const maxBoundY = MIN(maxMY, centerP->y + spacing + 1); + int const maxBoundX = MIN(maxMX, centerP->x + spacing + 1); + + int my; + + for (my = minBoundY; my < maxBoundY; my += spacing) { + int mx; + + for (mx = minBoundX; mx < maxBoundX; mx += spacing) { + int diff; + vector m; + + m.y = my; m.x = mx; + + diff = LumMotionError(currentBlockP, prev, by, bx, m, *bestDiffP); + + if (diff < *bestDiffP) { + *centerP = m; + *bestDiffP = diff; + } + } + } +} + + + +/*===========================================================================* + * + * PLogarithmicSearch + * + * uses logarithmic search to compute the P-frame vector + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + * REFERENCE: MPEG-I specification, pages 32-33 + * + *===========================================================================*/ +int +PLogarithmicSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const searchRange) { + + int const stepSize = (pixelFullSearch ? 2 : 1); + + int minMY, minMX, maxMY, maxMX; + int spacing; /* grid spacing */ + vector motion; + /* Distance from (bx,by) (in half-pixels) of the block that is most + like the current block among those that we have examined so far. + (0,0) means we haven't examined any. + */ + int bestDiff; + /* The difference between the current block and the block offset + 'motion' from it. + */ + + COMPUTE_MOTION_BOUNDARY(by, bx, stepSize, minMY, minMX, maxMY, maxMX); + minMX = max(minMX, - searchRange); + minMY = max(minMY, - searchRange); + maxMX = min(maxMX, + searchRange); + maxMY = min(maxMY, + searchRange); + + /* Note: The clipping to 'searchRange' above may seem superfluous because + the basic algorithm would never want to look more than 'searchRange' + pixels away, but with rounding error, it can. + */ + + motion.x = motion.y = 0; + bestDiff = INT_MAX; + + for (spacing = searchRange; spacing >= stepSize;) { + if (stepSize == 2) { /* make sure spacing is even */ + if (spacing == 2) + spacing = 0; + else { + spacing = (spacing+1)/2; + if (spacing % 2 != 0) + --spacing; + } + } else { + if (spacing == 1) { + spacing = 0; + } else + spacing = (spacing + 1) / 2; + } + if (spacing >= stepSize) + findBestSpaced(minMY, minMX, maxMY, maxMX, + spacing, currentBlockP, prev, by, bx, + &bestDiff, &motion); + } + + { + int diff; + /* check old motion -- see if it's better */ + if ((motionP->y >= minMY) && (motionP->y < maxMY) && + (motionP->x >= minMX) && (motionP->x < maxMX)) { + diff = LumMotionError(currentBlockP, prev, by, bx, + *motionP, bestDiff); + } else + diff = INT_MAX; + + if (bestDiff < diff) + *motionP = motion; + else + bestDiff = diff; + } + + return bestDiff; +} + + + +/*===========================================================================* + * + * PLocalSearch + * + * uses local exhaustive search to compute the P-frame vector + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +PLocalSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const bestSoFar, + int const searchRange) { + + int mx, my; + int bestDiff; + int stepSize; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + + stepSize = (pixelFullSearch ? 2 : 1); + + COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX); + + /* try old motion vector first */ + if (VALID_MOTION(*motionP)) { + bestDiff = LumMotionError(currentBlockP, prev, by, bx, + *motionP, bestSoFar); + + if (bestSoFar < bestDiff) + bestDiff = bestSoFar; + } else { + motionP->y = motionP->x = 0; + bestDiff = bestSoFar; + } + + /* try a spiral pattern */ + for (distance = stepSize; distance <= searchRange; distance += stepSize) { + tempRightMY = MIN(distance, rightMY); + tempRightMX = MIN(distance, rightMX); + + /* do top, bottom */ + for (my = -distance; my < tempRightMY; + my += max(tempRightMY+distance-stepSize, stepSize)) { + if (my >= leftMY) { + for ( mx = -distance; mx < tempRightMX; mx += stepSize ) { + if (mx >= leftMX) { + int diff; + vector m; + + m.y = my; m.x = mx; + diff = LumMotionError(currentBlockP, prev, by, bx, m, + bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + + /* do left, right */ + for (mx = -distance; mx < tempRightMX; + mx += max(tempRightMX+distance-stepSize, stepSize)) { + + if (mx >= leftMX) { + for (my = -distance+stepSize; my < tempRightMY-stepSize; + my += stepSize) { + if (my >= leftMY) { + int diff; + vector m; + + m.y = my; m.x = mx; + diff = LumMotionError(currentBlockP, prev, by, bx, m, + bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + } + return bestDiff; +} + + +/*===========================================================================* + * + * PTwoLevelSearch + * + * uses two-level search to compute the P-frame vector + * first does exhaustive full-pixel search, then looks at neighboring + * half-pixel motion vectors + * + * RETURNS: motion vector + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int +PTwoLevelSearch(const LumBlock * const currentBlockP, + MpegFrame * const prev, + int const by, + int const bx, + vector * const motionP, + int const bestSoFar, + int const searchRange) { + int mx, my; + int loopInc; + int diff, bestDiff; + int leftMY, leftMX; + int rightMY, rightMX; + int distance; + int tempRightMY, tempRightMX; + int xOffset, yOffset; + + /* exhaustive full-pixel search first */ + + COMPUTE_MOTION_BOUNDARY(by,bx,2,leftMY,leftMX,rightMY,rightMX); + + rightMY--; + rightMX--; + + /* convert vector into full-pixel vector */ + if (motionP->y > 0) { + if ((motionP->y % 2) == 1) { + --motionP->y; + } + } else if (((-motionP->y) % 2) == 1) + ++motionP->y; + + if (motionP->x > 0) { + if ((motionP->x % 2) == 1) + --motionP->x; + } else if ((-motionP->x % 2) == 1) + ++motionP->x; + + /* try old motion vector first */ + if (VALID_MOTION(*motionP)) { + bestDiff = LumMotionError(currentBlockP, prev, by, bx, + *motionP, bestSoFar); + + if ( bestSoFar < bestDiff ) { + bestDiff = bestSoFar; + } + } else { + motionP->y = motionP->x = 0; + bestDiff = bestSoFar; + } + + ++rightMY; + ++rightMX; + + /* try a spiral pattern */ + for ( distance = 2; distance <= searchRange; distance += 2 ) { + tempRightMY = MIN(distance, rightMY); + tempRightMX = MIN(distance, rightMX); + + /* do top, bottom */ + loopInc = max(tempRightMY + distance - 2, 2); + for (my = -distance; my < tempRightMY; my += loopInc) { + if (my >= leftMY) { + for (mx = -distance; mx < tempRightMX; mx += 2) { + if (mx >= leftMX) { + vector m; + m.y = my; m.x = mx; + diff = LumMotionError(currentBlockP, prev, by, bx, m, + bestDiff); + + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + + /* do left, right */ + loopInc = max(tempRightMX+distance-2, 2); + for (mx = -distance; mx < tempRightMX; mx += loopInc) { + if (mx >= leftMX) { + for ( my = -distance+2; my < tempRightMY-2; my += 2 ) { + if (my >= leftMY) { + int diff; + vector m; + m.y = my; m.x = mx; + diff = LumMotionError(currentBlockP, prev, by, bx, m, + bestDiff); + + if ( diff < bestDiff ) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + } + + /* now look at neighboring half-pixels */ + my = motionP->y; + mx = motionP->x; + + --rightMY; + --rightMX; + + for (yOffset = -1; yOffset <= 1; ++yOffset) { + for (xOffset = -1; xOffset <= 1; ++xOffset) { + if ((yOffset != 0) || (xOffset != 0)) { + vector m; + m.y = my+yOffset; m.x = mx+xOffset; + if (VALID_MOTION(m)) { + int diff; + diff = LumMotionError(currentBlockP, prev, by, bx, + m, bestDiff); + if (diff < bestDiff) { + *motionP = m; + bestDiff = diff; + } + } + } + } + } + return bestDiff; +} + + + +void +ShowPMVHistogram(fpointer) + FILE *fpointer; +{ + register int x, y; + int *columnTotals; + int rowTotal; + + columnTotals = (int *) calloc(2*searchRangeP+3, sizeof(int)); + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, " "); + for ( y = 0; y < 2*searchRange+3; y++ ) { + fprintf(fpointer, "%3d ", y-searchRangeP-1); + } + fprintf(fpointer, "\n"); +#endif + + for ( x = 0; x < 2*searchRangeP+3; x++ ) { +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%3d ", x-searchRangeP-1); +#endif + rowTotal = 0; + for ( y = 0; y < 2*searchRangeP+3; y++ ) { + fprintf(fpointer, "%3d ", pmvHistogram[x][y]); + rowTotal += pmvHistogram[x][y]; + columnTotals[y] += pmvHistogram[x][y]; + } +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%4d\n", rowTotal); +#else + fprintf(fpointer, "\n"); +#endif + } + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "Tot "); + for ( y = 0; y < 2*searchRangeP+3; y++ ) { + fprintf(fpointer, "%3d ", columnTotals[y]); + } +#endif + fprintf(fpointer, "\n"); +} + + +void +ShowBBMVHistogram(fpointer) + FILE *fpointer; +{ + register int x, y; + int *columnTotals; + int rowTotal; + + fprintf(fpointer, "B-frame Backwards:\n"); + + columnTotals = (int *) calloc(2*searchRangeB+3, sizeof(int)); + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, " "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", y-searchRangeB-1); + } + fprintf(fpointer, "\n"); +#endif + + for ( x = 0; x < 2*searchRangeB+3; x++ ) { +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%3d ", x-searchRangeB-1); +#endif + rowTotal = 0; + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", bbmvHistogram[x][y]); + rowTotal += bbmvHistogram[x][y]; + columnTotals[y] += bbmvHistogram[x][y]; + } +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%4d\n", rowTotal); +#else + fprintf(fpointer, "\n"); +#endif + } + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "Tot "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", columnTotals[y]); + } +#endif + fprintf(fpointer, "\n"); +} + + +void +ShowBFMVHistogram(fpointer) + FILE *fpointer; +{ + register int x, y; + int *columnTotals; + int rowTotal; + + fprintf(fpointer, "B-frame Forwards:\n"); + + columnTotals = (int *) calloc(2*searchRangeB+3, sizeof(int)); + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, " "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", y-searchRangeB-1); + } + fprintf(fpointer, "\n"); +#endif + + for ( x = 0; x < 2*searchRangeB+3; x++ ) { +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%3d ", x-searchRangeB-1); +#endif + rowTotal = 0; + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", bfmvHistogram[x][y]); + rowTotal += bfmvHistogram[x][y]; + columnTotals[y] += bfmvHistogram[x][y]; + } +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "%4d\n", rowTotal); +#else + fprintf(fpointer, "\n"); +#endif + } + +#ifdef COMPLETE_DISPLAY + fprintf(fpointer, "Tot "); + for ( y = 0; y < 2*searchRangeB+3; y++ ) { + fprintf(fpointer, "%3d ", columnTotals[y]); + } +#endif + fprintf(fpointer, "\n"); +} + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /u/smoot/md/mpeg_encode/RCS/psearch.c,v 1.9 1995/01/19 23:09:12 eyhung Exp $ + * $Log: psearch.c,v $ + * Revision 1.9 1995/01/19 23:09:12 eyhung + * Changed copyrights + * + * Revision 1.9 1995/01/19 23:09:12 eyhung + * Changed copyrights + * + * Revision 1.8 1994/12/07 00:40:36 smoot + * Added seperate P and B search ranges + * + * Revision 1.7 1994/11/12 02:09:45 eyhung + * full pixel bug + * fixed on lines 512 and 563 + * + * Revision 1.6 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.5 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.4 1993/07/22 22:23:43 keving + * nothing + * + * Revision 1.3 1993/06/30 20:06:09 keving + * nothing + * + * Revision 1.2 1993/06/03 21:08:08 keving + * nothing + * + * Revision 1.1 1993/03/02 18:27:05 keving + * nothing + * + */ + + diff --git a/converter/ppm/ppmtompeg/psocket.c b/converter/ppm/ppmtompeg/psocket.c new file mode 100644 index 00000000..707f1d84 --- /dev/null +++ b/converter/ppm/ppmtompeg/psocket.c @@ -0,0 +1,452 @@ +/*===========================================================================* + psocket.c +============================================================================== + + low level communication facilities for Ppmtompeg parallel operation + + By Bryan Henderson 2004.10.13. Contributed to the public domain by + its author. + +============================================================================*/ + +#define _XOPEN_SOURCE 500 /* Make sure stdio.h contains pclose() */ +/* _ALL_SOURCE is needed on AIX to make the C library include the + socket services (e.g. define struct sockaddr) + + Note that AIX standards.h actually sets feature declaration macros such + as _XOPEN_SOURCE, unless they are already set. +*/ +#define _ALL_SOURCE +#define __EXTENSIONS__ + /* __EXTENSIONS__ is for a broken Sun C library (uname SunOS kosh 5.8 + generic_108528-16 sun4u sparc). When you define _XOPEN_SOURCE, + it's vnode.h and resource.h fail to define some data types that they + need (e.g. timestruct_t). But with __EXTENSIONS__, they declare the + needed types anyway. Our #include <sys/socket.h> causes the broken + header files to get included. + */ + +/* On AIX, pm_config.h includes standards.h, which expects to be included + after feature declaration macros such as _XOPEN_SOURCE. So we include + pm_config.h as late as possible. +*/ + +#include "pm_config.h" /* For POSIX_IS_IMPLIED */ + +#ifdef POSIX_IS_IMPLIED +/* The OpenBSD C library, at least, is broken in that when _XOPEN_SOURCE + is defined, its sys/socket.h refers to types "u_char", etc. but does + not define them. But it is also one of the C libraries where + POSIX is implied so that we don't need to define _XOPEN_SOURCE in order + to get the POSIX routines such as pclose() defined. So we circumvent + the problem by undefining _XOPEN_SOURCE: +*/ +#undef _XOPEN_SOURCE +#endif + +#include <stdarg.h> +#include <netinet/in.h> +#include <unistd.h> +#include <netdb.h> +#include <stdio.h> +#include <errno.h> +#include <assert.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "pm.h" +#include "pm_c_util.h" +#include "nstring.h" + +#include "gethostname.h" + +#include "psocket.h" + + +/* We use type socklenx_t where we should use socklen_t from the C + library, but older systems don't have socklen_t. And there doesn't + appear to be any way for the preprocessor to know whether it exists + or not. On older systems with no socklen_t, a message length is a + signed integer, but on modern systems, socklen_t is an unsigned + integer. Until we have some kind of build-time check for the existence + of socklen_t, we just use this socklenx_t, which is an unsigned + integer, and accept compiler warnings on older system. + -Bryan 2001.04.22. +*/ +typedef unsigned int socklenx_t; + +#ifndef SOMAXCONN +#define SOMAXCONN 5 +#endif + + + +static void PM_GNU_PRINTF_ATTR(1,2) +errorExit(const char format[], ...) { + + const char * const hostname = GetHostName(); + + va_list args; + + va_start(args, format); + + fprintf(stderr, "%s: FATAL ERROR. ", hostname); + strfree(hostname); + vfprintf(stderr, format, args); + fputc('\n', stderr); + + exit(1); + + va_end(args); +} + + + +static void +unmarshallInt(unsigned char const buffer[], + int * const valueP) { +/*---------------------------------------------------------------------------- + Interpret a number which is formatted for one of our network packets. + + To wit, 32 bit big-endian pure binary. +-----------------------------------------------------------------------------*/ + union { + uint32_t value; + unsigned char bytes[4]; + } converter; + + memcpy(&converter.bytes, buffer, 4); + + /* Note that contrary to what the C data types suggest, ntohl() is + a 32 bit converter, even if a C "long" is bigger than that. + */ + *valueP = ntohl(converter.value); +} + + + +static void +safeRead(int const fd, + unsigned char * const buf, + unsigned int const nbyte) { +/*---------------------------------------------------------------------------- + Safely read from file 'fd'. Keep reading until we get + 'nbyte' bytes. +-----------------------------------------------------------------------------*/ + unsigned int numRead; + + numRead = 0; /* initial value */ + + while (numRead < nbyte) { + int const result = read(fd, &buf[numRead], nbyte-numRead); + + if (result == -1) + errorExit("read (of %u bytes (total %u) ) returned " + "errno %d (%s)", + nbyte-numRead, nbyte, errno, strerror(errno)); + else + numRead += result; + } +} + + + +void +ReadBytes(int const fd, + unsigned char * const buf, + unsigned int const nbyte) { + + safeRead(fd, buf, nbyte); +} + + + +void +ReadInt(int const socketFd, + int * const valueP) { + + unsigned char buffer[4]; + + safeRead(socketFd, buffer, sizeof(buffer)); + + unmarshallInt(buffer, valueP); +} + + + +static void +marshallInt(int const value, + unsigned char (* const bufferP)[]) { +/*---------------------------------------------------------------------------- + Put the number 'value' into the buffer at *bufferP in the form required + for one of our network packets. + + To wit, 32 bit big-endian pure binary. +-----------------------------------------------------------------------------*/ + union { + uint32_t value; + unsigned char bytes[4]; + } converter; + + unsigned char testbuffer[4]; + + /* Note that contrary to what the C data types suggest, htonl() is + a 32 bit converter, even if a C "long" is bigger than that. + */ + converter.value = htonl(value); + + (*bufferP)[0] = 7; + memcpy(testbuffer, &converter.bytes, 4); + memcpy(*bufferP, &converter.bytes, 4); +} + + + +static void +safeWrite(int const fd, + unsigned char * const buf, + unsigned int const nbyte) { +/*---------------------------------------------------------------------------- + Safely write to file 'fd'. Keep writing until we write 'nbyte' + bytes. +-----------------------------------------------------------------------------*/ + unsigned int numWritten; + + numWritten = 0; /* initial value */ + + while (numWritten < nbyte) { + int const result = write(fd, &buf[numWritten], nbyte-numWritten); + + if (result == -1) + errorExit("write (of %u bytes (total %u) ) returned " + "errno %d (%s)", + nbyte-numWritten, nbyte, errno, strerror(errno)); + numWritten += result; + } +} + + + +void +WriteBytes(int const fd, + unsigned char * const buf, + unsigned int const nbyte) { + + safeWrite(fd, buf, nbyte); +} + + + +void +WriteInt(int const socketFd, + int const value) { + + unsigned char buffer[4]; + + marshallInt(value, &buffer); + + safeWrite(socketFd, buffer, sizeof(buffer)); +} + + + +void +ConnectToSocket(const char * const machineName, + int const portNum, + struct hostent ** const hostEnt, + int * const socketFdP, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Create a socket and connect it to the specified TCP endpoint. + + That endpoint is fundamentally defined by 'machineName' and + 'portNum', but *hostEnt is the address of a host entry that caches + the results of the host name lookup. If *hostEnt is non-null, we + use it. If *hostEnt is NULL, we look up the information and update + **hostEnt. +-----------------------------------------------------------------------------*/ + int rc; + + *errorP = NULL; /* initial value */ + + if ((*hostEnt) == NULL) { + (*hostEnt) = gethostbyname(machineName); + if ((*hostEnt) == NULL) + asprintfN(errorP, "Couldn't get host by name (%s)", machineName); + } + if (!*errorP) { + rc = socket(AF_INET, SOCK_STREAM, 0); + if (rc < 0) + asprintfN(errorP, "socket() failed with errno %d (%s)", + errno, strerror(errno)); + else { + int const socketFd = rc; + + int rc; + unsigned short tempShort; + struct sockaddr_in nameEntry; + + nameEntry.sin_family = AF_INET; + memset((void *) nameEntry.sin_zero, 0, 8); + memcpy((void *) &(nameEntry.sin_addr.s_addr), + (void *) (*hostEnt)->h_addr_list[0], + (size_t) (*hostEnt)->h_length); + tempShort = portNum; + nameEntry.sin_port = htons(tempShort); + + rc = connect(socketFd, (struct sockaddr *) &nameEntry, + sizeof(struct sockaddr)); + + if (rc != 0) + asprintfN(errorP, + "connect() to host '%s', port %d failed with " + "errno %d (%s)", + machineName, portNum, errno, strerror(errno)); + else { + *errorP = NULL; + *socketFdP = socketFd; + } + if (*errorP) + close(socketFd); + } + } +} + + + +static bool +portInUseErrno(int const testErrno) { +/*---------------------------------------------------------------------------- + Return TRUE iff 'testErrno' is what a bind() would return if one requestd + a port number that is unavailable (but other port numbers might be). +-----------------------------------------------------------------------------*/ + bool retval; + + switch (testErrno) { + case EINVAL: + case EADDRINUSE: + case EADDRNOTAVAIL: + retval = TRUE; + break; + default: + retval = FALSE; + } + return retval; +} + + + +static void +bindToUnusedPort(int const socketFd, + unsigned short * const portNumP, + const char ** const errorP) { + + bool foundPort; + unsigned short trialPortNum; + + *errorP = NULL; /* initial value */ + + for (foundPort = FALSE, trialPortNum = 2048; + !foundPort && trialPortNum < 16384 && !*errorP; + ++trialPortNum) { + + struct sockaddr_in nameEntry; + int rc; + + memset((char *) &nameEntry, 0, sizeof(nameEntry)); + nameEntry.sin_family = AF_INET; + nameEntry.sin_port = htons(trialPortNum); + + rc = bind(socketFd, (struct sockaddr *) &nameEntry, + sizeof(struct sockaddr)); + + if (rc == 0) { + foundPort = TRUE; + *portNumP = trialPortNum; + } else if (!portInUseErrno(errno)) + asprintfN(errorP, "bind() of TCP port number %hu failed " + "with errno %d (%s)", + trialPortNum, errno, strerror(errno)); + } + + if (!*errorP && !foundPort) + asprintfN(errorP, "Unable to find a free port. Every TCP port " + "in the range 2048-16383 is in use"); +} + + + +void +CreateListeningSocket(int * const socketP, + int * const portNumP, + const char ** const errorP) { +/*---------------------------------------------------------------------------- + Create a TCP socket and bind it to the first unused port number we + can find. + + Return as *socketP a file handle for the socket (on which Caller can + listen()), and as *portNumP the TCP port number (to which Caller's + partner can connect). +-----------------------------------------------------------------------------*/ + int rc; + + rc = socket(AF_INET, SOCK_STREAM, 0); + if (rc < 0) + asprintfN(errorP, + "Unable to create socket. " + "socket() failed with errno %d (%s)", + errno, strerror(errno)); + else { + int const socketFd = rc; + + unsigned short portNum; + + *socketP = socketFd; + + bindToUnusedPort(socketFd, &portNum, errorP); + if (!*errorP) { + int rc; + + *portNumP = portNum; + + /* would really like to wait for 1+numMachines machines, + but this is max allowable, unfortunately + */ + rc = listen(socketFd, SOMAXCONN); + if (rc != 0) + asprintfN(errorP, "Unable to listen on TCP socket. " + "listen() fails with errno %d (%s)", + errno, strerror(errno)); + } + if (*errorP) + close(socketFd); + } +} + + + +void +AcceptConnection(int const listenSocketFd, + int * const connectSocketFdP, + const char ** const errorP) { + + struct sockaddr otherSocket; + socklenx_t otherSize; + /* This is an ugly dual-meaning variable. As input to accept(), + it is the storage size of 'otherSocket'. As output, it is the + data length of 'otherSocket'. + */ + int rc; + + otherSize = sizeof(otherSocket); + + rc = accept(listenSocketFd, &otherSocket, &otherSize); + + if (rc < 0) + asprintfN(errorP, "accept() failed with errno %d (%s). ", + errno, strerror(errno)); + else { + *connectSocketFdP = rc; + *errorP = NULL; + } +} diff --git a/converter/ppm/ppmtompeg/qtest.c b/converter/ppm/ppmtompeg/qtest.c new file mode 100644 index 00000000..b3d26593 --- /dev/null +++ b/converter/ppm/ppmtompeg/qtest.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/qtest.c,v 1.5 1995/01/19 23:09:15 eyhung Exp $ + * $Log: qtest.c,v $ + * Revision 1.5 1995/01/19 23:09:15 eyhung + * Changed copyrights + * + * Revision 1.4 1993/01/18 10:20:02 dwallach + * *** empty log message *** + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + * Revision 1.3 1993/01/18 10:17:29 dwallach + * RCS headers installed, code indented uniformly + * + */ + +#include <stdio.h> +#include "mtypes.h" +#include "mproto.h" + +main() +{ + Block a; + FlatBlock b; + BitBucket *bb; + int i, j; + + bb = new_bitbucket(); + + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + a[i][j] = rand() % 100; + mp_quant_zig_block(a, b, 1, 1); + for (i = 0; i < 64; i++) + printf("%6d ", b[i]); + printf("\n"); + + mp_rle_huff_block(b, bb); /* intuititve names, huh? */ + + printf("Huffman output is %d bits\n", bb->totalbits); +} diff --git a/converter/ppm/ppmtompeg/rate.c b/converter/ppm/ppmtompeg/rate.c new file mode 100644 index 00000000..3940956c --- /dev/null +++ b/converter/ppm/ppmtompeg/rate.c @@ -0,0 +1,986 @@ +/*============================================================================* + * rate.c * + * * + * Procedures concerned with rate control * + * * + * EXPORTED PROCEDURES: * + * initRatecontrol() * + * targetRateControl() * + * updateRateControl() * + * MB_RateOut() * + * needQScaleChange() * + * incNumBlocks() * + * incQuant() * + * incMacroBlockBits() * + * setPictureRate() * + * setBitRate() * + * getBitRate() * + * setBufferSize() * + * getBufferSize() * + * * + * NOTES: * + * Naming conventions follow those of MPEG-2 draft algorithm (chap. 10) * + *============================================================================*/ + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include <assert.h> +#include <sys/types.h> +#include <sys/times.h> + +#include "ppm.h" +#include "nstring.h" + +#include "all.h" +#include "mtypes.h" +#include "bitio.h" +#include "frames.h" +#include "prototypes.h" +#include "param.h" +#include "mheaders.h" +#include "fsize.h" +#include "postdct.h" +#include "mpeg.h" +#include "parallel.h" +#include "dct.h" +#include "rate.h" + + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +#define MAX_BIT_RATE 104857600 /* 18 digit number in units of 400 */ +#define MAX_BUFFER_SIZE 16760832 /* 10 digit number in units of 16k */ +#define DEFAULT_BUFFER_SIZE 327680 /* maximun for "constrained" bitstream */ +#define DEFAULT_VBV_FULLNESS 3 /* wait till 1/3 full */ +#define DEFAULT_PICT_RATE_CODE 5 /* code for 30 Frames/sec */ +#define DEFAULT_PICT_RATE 30 /* 30 frames per second */ +#define MAX_VBV_DELAY 32768 /* 16 digits */ + + +/* Variables from Parameter File */ + +static int RateControlMode = VARIABLE_RATE; +static int32 buffer_size = DEFAULT_BUFFER_SIZE; +static int32 bit_rate = -1; + +static bool wantVbvUnderflowWarning; +static bool wantVbvOverflowWarning; + +/* Variables for the VBV buffer defined in MPEG specs */ +static unsigned int VBV_remainingDelay; + /* delay in units of 1/90000 seconds */ +static int32 VBV_buffer = 0; /* fullness of the theoretical VBV buffer */ +static int32 bufferFillRate = 0; /* constant rate at which buffer filled */ +static int32 frameDelayIncrement = 0; /* number of "delay" units/Frame */ + +/* Global complexity measure variables */ +static int Xi, Xp, Xb; /* Global complexity measure */ + +static int Si, Sp, Sb; /* Total # bits for last pict of type (Overhead?) */ + +static float Qi, Qp, Qb; /* avg quantizaton for last picture of type */ + +/* Target bit allocations for each type of picture*/ +int Ti, Tp, Tb; + +int current_Tx; /* allocation for current frame */ + +/* Count of number of pictures of each type remaining */ +int GOP_X; +int GOP_I; +int GOP_P; +int GOP_B; + +int Nx = 0; +int Ni = 0; +int Np = 0; +int Nb = 0; + +/* Counters used while encoding frames */ + +int rc_numBlocks = 0; +int rc_totalQuant = 0; +int rc_bitsThisMB; +int rc_totalMBBits; +int rc_totalFrameBits; +int rc_totalOverheadBits = 0; + + +/* Want to print out Macroblock info every Nth MB */ +int RC_MB_SAMPLE_RATE = 0; + +static float Ki = .7; +static float Kp = 1; +static float Kb = 1.4; +static int rc_R; +static int rc_G; + +/* Rate Control variables */ + +/* Virtual buffers for each frame type */ +static int d0_i; /* Initial fullnesses */ +static int d0_p; +static int d0_b; + +static int lastFrameVirtBuf; /* fullness after last frame of this type */ +static int currentVirtBuf; /* fullness during current encoding*/ + +static int MB_cnt = -1; /* Number of MB's in picture */ + +static int rc_Q; /* reference quantization parameter */ + +static int reactionParameter; /* Reaction parameter */ + +/* Adaptive Quantization variables */ +static int act_j; /* spatial activity measure */ +static float N_act; /* Normalized spacial activity */ +static int avg_act; /* average activity value in last picture encoded */ +static int total_act_j; /* Sum of activity values in current frame */ + +static int var_sblk; /* sub-block activity */ +static int P_mean; /* Mean value of pixels in 8x8 sub-block */ + +static int mquant; /* Raw Quantization value */ +static int Qscale; /* Clipped, truncated quantization value */ + + + +/* Output-related variables */ +#ifdef RC_STATS_FILE +static FILE *RC_FILE; +#endif + +static const char * const Frame_header1 = +" Fm # Bit GOP V "; +static const char * const Frame_header2 = +" # type MBs Alloc left Ni Np Nb N_act buff Q_rc Qscale"; +static const char * const Frame_header3 = +"---- - ---- ------ ------- -- -- -- ----- ------ ---- ----"; +static const char * const Frame_trailer1 = +" avg virt % GOP % VBV"; +static const char * const Frame_trailer2 = +" Sx Qx Xx act N_act buffer alloc left left buf delay"; +static const char * const Frame_trailer3 = +"------ --.-- ------- --- --.-- ------- --- ------- --- ------- ------"; + +static const char * const MB_header1 = +"MB# #bits Q mqt Dj Q_j actj N_act totbits b/MB %alloc %done"; +static const char * const MB_header2 = +"--- ----- -- --- ------ --- ----- --.-- ------ ---- --- ---"; + +static char rc_buffer[101]; + +/* EXTERNAL Variables */ +extern char *framePattern; +extern int framePatternLen; + + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +int initGOPRateControl _ANSI_ARGS_((void)); +int determineMBCount _ANSI_ARGS_((void)); +void checkBufferFullness _ANSI_ARGS_((int count)); +void checkSpatialActivity _ANSI_ARGS_((Block blk0, Block blk1, Block blk2, Block blk3)); +void incNumBlocks _ANSI_ARGS_((int num)); +void calculateVBVDelay _ANSI_ARGS_((int num)); +int BlockExperiments _ANSI_ARGS_((int16 *OrigBlock, int16 *NewBlock, int control)); + + + +static void +analyzePattern(const char * const framePattern, + int const framePatternLen, + int * const gop_xP, + int * const gop_iP, + int * const gop_pP, + int * const gop_bP, + const char ** const errorP) { + + unsigned int i; + + /* Initialize Pattern info */ + *gop_xP = framePatternLen; + + for (i = 0, *gop_iP = 0, *gop_pP = 0, *gop_bP = 0, *errorP = NULL; + i < framePatternLen && !*errorP; + ++i) { + switch(framePattern[i]) { + case 'i': ++*gop_iP; break; + case 'p': ++*gop_pP; break; + case 'b': ++*gop_bP; break; + default: + asprintfN(errorP, "Bad pattern - not composed of i, p, and b"); + } + } + assert(*gop_xP == *gop_iP + *gop_pP + *gop_bP); +} + + + +/*===========================================================================* + * + * initRateControl + * + * initialize the allocation parameters. + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + * + * NOTES: Get rid of the redundant pattern stuff!! + *===========================================================================*/ +int +initRateControl(bool const wantUnderflowWarning, + bool const wantOverflowWarning) { + int result; + const char * error; + + wantVbvUnderflowWarning = wantUnderflowWarning; + wantVbvOverflowWarning = wantOverflowWarning; + + DBG_PRINT(("Initializing Allocation Data\n")); + +#ifdef RC_STATS_FILE + RC_FILE = fopen("RC_STATS_FILE", "w"); + if ( RC_FILE == NULL) { + DBG_PRINT(("Open of RC file failed, using stderr\n")); + RC_FILE = stderr; + fprintf(RC_FILE, "Open of RC file failed, using stderr\n"); + fflush(RC_FILE); + } +#endif + + VBV_remainingDelay = 0; + + analyzePattern(framePattern, framePatternLen, + &GOP_X, &GOP_I, &GOP_P, &GOP_B, &error); + + if (error) { + pm_message("Unable to set up rate control. Switching to variable. " + "%s", error); + strfree(error); + RateControlMode = VARIABLE_RATE; + return -1; + } + + + /* Initializing GOP bit allocation */ + rc_R = 0; + rc_G = (bit_rate * GOP_X/frameRateRounded); + + /* Initialize the "global complexity measures" */ + Xi = (160 * bit_rate/115); + Xp = (60 * bit_rate/115); + Xb = (42 * bit_rate/115); + + /* Initialize MB counters */ + rc_totalMBBits= rc_bitsThisMB= rc_totalFrameBits=rc_totalOverheadBits = 0; + rc_numBlocks = rc_totalQuant = 0; + + /* init virtual buffers */ + reactionParameter = (2 * bit_rate / frameRateRounded); + d0_i = (10 * reactionParameter / 31); + d0_p = (Kp * d0_i); + d0_b = (Kb * d0_i); + + lastFrameVirtBuf = d0_i; /* start with I Frame */ + rc_Q = lastFrameVirtBuf * 31 / reactionParameter; + + /* init spatial activity measures */ + avg_act = 400; /* Suggested initial value */ + N_act = 1; + + mquant = rc_Q * N_act; + + frameDelayIncrement = (90000 / frameRateRounded); + /* num of "delay" units per frame */ + bufferFillRate = bit_rate / frameRateRounded; + /* VBV buf fills at constant rate */ + VBV_buffer = buffer_size; + DBG_PRINT(("VBV- delay: %d, fill rate: %d, delay/Frame: %d units, " + "buffer size: %d\n", + VBV_remainginDelay, bufferFillRate, frameDelayIncrement, + buffer_size)); + + result = initGOPRateControl(); + + return result; +} + +/*===========================================================================* + * + * initGOPRateControl + * + * (re)-initialize the RC for the a new Group of Pictures. + * New bit allocation, but carry over complexity measures. + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + * + *===========================================================================*/ +int +initGOPRateControl() +{ + DBG_PRINT(("Initializing new GOP\n")); + + Nx = GOP_X; + Ni = GOP_I; + Np = GOP_P; + Nb = GOP_B; + + rc_R += rc_G; + + DBG_PRINT(("bufsize: %d, bitrate: %d, pictrate: %d, GOP bits: %d\n", + buffer_size, bit_rate, frameRateRounded, rc_R)); + DBG_PRINT(("Xi: %d, Xp: %d, Xb: %d Nx: %d, Ni: %d, Np: %d, Nb: %d\n", + Xi, Xp, Xb, Nx,Ni,Np,Nb)); + DBG_PRINT(("d0_i: %d, d0_p: %d, d0_b: %d, avg_act: %d, rc_Q: %d, " + "mquant: %d\n", + d0_i, d0_p, d0_b, avg_act, rc_Q, mquant)); + return 1; +} + + + +/*===========================================================================* + * + * targetRateControl + * + * Determine the target allocation for given picture type, initiates + * variables for rate control process. + * + * RETURNS: nothing. + * + * SIDE EFFECTS: many global variables + * + *===========================================================================*/ +void +targetRateControl(MpegFrame * const frame) { + + float temp1, minimumBits; + float tempX, tempY, tempZ; + int result; + int frameType; + const char *strPtr; + + minimumBits = (bit_rate / (8 * frameRateRounded)); + + /* Check if new GOP */ + if (Nx == 0) { + initGOPRateControl(); + } + + if (MB_cnt < 0) {MB_cnt = determineMBCount();} + + switch (frame->type) { + case TYPE_IFRAME: + frameType = 'I'; + + tempX = ( (Np * Ki * Xp) / (Xi * Kp) ); + tempY = ( (Nb * Ki * Xb) / (Xi*Kb) ); + tempZ = Ni + tempX + tempY; + temp1 = (rc_R / tempZ); + result = (int) (temp1 > minimumBits ? temp1 : minimumBits); + current_Tx = Ti = result; + lastFrameVirtBuf = d0_i; + break; + + case TYPE_PFRAME: + frameType = 'P'; + tempX = ( (Ni * Kp * Xi) / (Ki * Xp) ); + tempY = ( (Nb * Kp * Xb) / (Kb * Xp) ); + tempZ = Np + tempX + tempY; + temp1 = (rc_R/ tempZ); + result = (int) (temp1 > minimumBits ? temp1 : minimumBits); + current_Tx = Tp = result; + lastFrameVirtBuf = d0_p; + break; + + case TYPE_BFRAME: + frameType = 'B'; + tempX = ( (Ni * Kb * Xi) / (Ki * Xb) ); + tempY = ( (Np * Kb * Xp) / (Kp * Xb) ); + tempZ = Nb + tempX + tempY; + temp1 = (rc_R/ tempZ); + result = (int) (temp1 > minimumBits ? temp1 : minimumBits); + current_Tx = Tb = result; + lastFrameVirtBuf = d0_b; + break; + + default: + frameType = 'X'; + } + + N_act = 1; + rc_Q = lastFrameVirtBuf * 31 / reactionParameter; + mquant = rc_Q * N_act; + Qscale = (mquant > 31 ? 31 : mquant); + Qscale = (Qscale < 1 ? 1 : Qscale); + + /* Print headers for Frame info */ + strPtr = Frame_header1; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_header2; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_header3; + DBG_PRINT(("%s\n",strPtr)); + + /* Print Frame info */ + sprintf(rc_buffer, "%4d %1c %4d %6d %7d " + "%2d %2d %2d %2.2f %6d %4d %3d", + frame->id,frameType,MB_cnt,current_Tx,rc_R,Ni,Np,Nb, + N_act, lastFrameVirtBuf, rc_Q, Qscale); + +#ifdef RC_STATS_FILE + fprintf(RC_FILE,"%s\n", rc_buffer); + fflush(RC_FILE); +#endif + DBG_PRINT(("%s\n",rc_buffer)); + + /* Print headers for Macroblock info */ + if (RC_MB_SAMPLE_RATE) { + strPtr = MB_header1; + DBG_PRINT(("%s\n",strPtr)); + strPtr = MB_header2; + DBG_PRINT(("%s\n",strPtr)); + } +} + + + + +static void +updateVBVBuffer(int const frameBits) { +/*---------------------------------------------------------------------------- + Update the VBV buffer after each frame. This theoretical buffer is + being filled at constant rate 'bufferFillRate' from an mpeg stream. + It is emptied as each frame is grabbed by the decoder. Exception is + that the decoder will wait until the "delay" is over. + + We mark the passing of one unit of time, in which 'frameBits' bits of + mpeg data were grabbed from the buffer by the decoder. +-----------------------------------------------------------------------------*/ + if (VBV_remainingDelay) + VBV_remainingDelay -= MIN(frameDelayIncrement, VBV_remainingDelay); + else + VBV_buffer -= frameBits; + + VBV_buffer += bufferFillRate; + if (VBV_buffer < 0 && wantVbvUnderflowWarning) + pm_message("WARNING - VBV buffer underflow (%d)", VBV_buffer); + if (VBV_buffer > buffer_size && wantVbvOverflowWarning) + pm_message("WARNING - VBV buffer overflow (%d > %d)", + VBV_buffer, buffer_size); +} + + + +/*===========================================================================* + * + * updateRateControl + * + * Update the statistics kept, after end of frame. Resets + * various global variables + * + * RETURNS: nothing + * + * SIDE EFFECTS: many global variables + * + *===========================================================================*/ +void +updateRateControl(int const type) { + int totalBits, frameComplexity, pctAllocUsed, pctGOPUsed; + float avgQuant; + const char *strPtr; + + totalBits = rc_totalFrameBits; + avgQuant = ((float) rc_totalQuant / (float) rc_numBlocks); + frameComplexity = totalBits * avgQuant; + pctAllocUsed = (totalBits *100 / current_Tx); + rc_R -= totalBits; + pctGOPUsed = (rc_R *100/ rc_G); + + avg_act = (total_act_j / MB_cnt); + + updateVBVBuffer(totalBits); + + switch (type) { + case TYPE_IFRAME: + Ti = current_Tx; + d0_i = currentVirtBuf; + Ni--; + Si = totalBits; + Qi = avgQuant; + Xi = frameComplexity; + break; + case TYPE_PFRAME: + Tp = current_Tx; + d0_p = currentVirtBuf; + Np--; + Sp = totalBits; + Qp = avgQuant; + Xp = frameComplexity; + break; + case TYPE_BFRAME: + Tb = current_Tx; + d0_b = currentVirtBuf; + Nb--; + Sb = totalBits; + Qb = avgQuant; + Xb = frameComplexity; + break; + } + + + /* Print Frame info */ + strPtr = Frame_trailer1; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_trailer2; + DBG_PRINT(("%s\n",strPtr)); + strPtr = Frame_trailer3; + DBG_PRINT(("%s\n",strPtr)); + + sprintf(rc_buffer, "%6d %2.2f %6d %3d %2.2f %7d " + "%3d %7d %3d %6d %6d", + totalBits, avgQuant, frameComplexity, avg_act, N_act, + currentVirtBuf, pctAllocUsed, rc_R, pctGOPUsed, + VBV_buffer, VBV_remainingDelay); +#ifdef RC_STATS_FILE + fprintf(RC_FILE,"%s\n", rc_buffer); + fflush(RC_FILE); +#endif + DBG_PRINT(("%s\n",rc_buffer)); + + Nx--; + rc_totalMBBits= rc_bitsThisMB= rc_totalFrameBits=rc_totalOverheadBits = 0; + rc_numBlocks = rc_totalQuant = total_act_j = currentVirtBuf = 0; + + DBG_PRINT(("GOP now has %d bits remaining (%3d%%) for %d frames .. , " + "Ni= %d, Np= %d, Nb= %d\n", + rc_R, (rc_R*100/rc_G), (Ni+Np+Nb), Ni, Np, Nb)); + +} + + +/*===========================================================================* + * + * MB_RateOut + * + * Prints out sampling of MB rate control data. Every "nth" block + * stats are printed, with "n" controled by global RC_MB_SAMPLE_RATE + * (NB. "skipped" blocks do not go through this function and thus do not + * show up in the sample ) + * + * RETURNS: nothing + * + * SIDE EFFECTS: none + * + * NOTES: + * + *===========================================================================*/ +void + MB_RateOut(type) +int type; +{ + int totalBits; + int pctUsed, pctDone; + int bitsThisMB; + int bitsPerMB; + + bitsThisMB = rc_bitsThisMB; + totalBits = rc_totalFrameBits; + bitsPerMB = (totalBits / rc_numBlocks); + pctDone = (rc_numBlocks * 100/ MB_cnt); + pctUsed = (totalBits *100/current_Tx); + + sprintf(rc_buffer, "%3d %5d %2d %3d %6d %3d %6d %2.2f %6d %4d %3d %3d\n", + (rc_numBlocks - 1), bitsThisMB, Qscale, mquant, currentVirtBuf, + rc_Q, act_j, N_act, totalBits, bitsPerMB, pctUsed, pctDone); +#ifdef RC_STATS_FILE + fprintf(RC_FILE, "%s", rc_buffer); + fflush(RC_FILE); +#endif + + if ( (RC_MB_SAMPLE_RATE) && ((rc_numBlocks -1) % RC_MB_SAMPLE_RATE)) { + DBG_PRINT(("%s\n", rc_buffer)); + } else { + return; + } +} + + + +/*===========================================================================* + * + * incNumBlocks() + * + * + * RETURNS: nothing + * + * SIDE EFFECTS: rc_numBlocks + * + * NOTES: + * + *===========================================================================*/ +void incNumBlocks(num) + int num; +{ + rc_numBlocks += num; +} + + +/*===========================================================================* + * + * incMacroBlockBits() + * + * Increments the number of Macro Block bits and the total of Frame + * bits by the number passed. + * + * RETURNS: nothing + * + * SIDE EFFECTS: rc_totalMBBits + * + * NOTES: + * + *===========================================================================*/ +void incMacroBlockBits(num) + int num; +{ + rc_bitsThisMB = num; + rc_totalMBBits += num; + rc_totalFrameBits += num; +} + + +/*===========================================================================* + * + * needQScaleChange(current Q scale, 4 luminance blocks) + * + * + * RETURNS: new Qscale + * + * SIDE EFFECTS: + * + *===========================================================================*/ +int needQScaleChange(oldQScale, blk0, blk1, blk2, blk3) + int oldQScale; + Block blk0; + Block blk1; + Block blk2; + Block blk3; +{ + + /* One more MacroBlock seen */ + rc_numBlocks++; /* this notes each block num in MB */ + + checkBufferFullness(oldQScale); + + checkSpatialActivity(blk0, blk1, blk2, blk3); + + mquant = rc_Q * N_act; + Qscale = (mquant > 31 ? 31 : mquant); + Qscale = (Qscale < 1 ? 1 : Qscale); + rc_totalQuant += Qscale; + + if (oldQScale == Qscale) + return -1; + else + return Qscale; +} + + +/*===========================================================================* + * + * determineMBCount() + * + * Determines number of Macro Blocks in frame from the frame sizes + * passed. + * + * RETURNS: nothing + * + * SIDE EFFECTS: sets the count passed + * + *===========================================================================*/ +int + determineMBCount () +{ + int y,x; + + x = (Fsize_x +15)/16; + y = (Fsize_y +15)/16; + return (x * y); +} + + + +/*===========================================================================* + * + * void checkBufferFullness () + * + * Calculates the fullness of the virtual buffer for each + * frame type. Called before encoding each macro block. Along + * with the normalized spatial activity measure (N_act), it + * determine the quantization factor for the next macroblock. + * + * RETURNS: nothing + * + * SIDE EFFECTS: the "currentVirtBuf" variable + * + * NOTES: + * + *===========================================================================*/ +void checkBufferFullness (oldQScale) + int oldQScale; +{ + int temp; + + temp = lastFrameVirtBuf + rc_totalFrameBits; + temp -= (current_Tx * rc_numBlocks / MB_cnt); + currentVirtBuf = temp; + + rc_Q = (currentVirtBuf * 31 / reactionParameter); + return; +} + + +/*===========================================================================* + * + * void checkSpatialActivity() + * + * Calcualtes the spatial activity for the four luminance blocks of the + * macroblock. Along with the normalized reference quantization parameter + * (rc_Q) , it determines the quantization factor for the next macroblock. + * + * RETURNS: nothing + * + * SIDE EFFECTS: the Adaptive quantization variables- act_j, N_act. + * + * NOTES: + * + *===========================================================================*/ +void checkSpatialActivity(blk0, blk1, blk2, blk3) + Block blk0; + Block blk1; + Block blk2; + Block blk3; +{ + int temp; + int16 *blkArray[4]; + int16 *curBlock; + int16 *blk_ptr; + int var[4]; + int i, j; + + + blkArray[0] = (int16 *) blk0; + blkArray[1] = (int16 *) blk1; + blkArray[2] = (int16 *) blk2; + blkArray[3] = (int16 *) blk3; + + + for (i =0; i < 4; i++) { /* Compute the activity in each block */ + curBlock = blkArray[i]; + blk_ptr = curBlock; + P_mean = 0; + /* Find the mean pixel value */ + for (j=0; j < DCTSIZE_SQ; j ++) { + P_mean += *(blk_ptr++); + /* P_mean += curBlock[j]; + if (curBlock[j] != *(blk_ptr++)) { + printf("ARRAY ERROR: block %d\n", j); + } + */ + } + P_mean /= DCTSIZE_SQ; + + /* Now find the variance */ + curBlock = blkArray[i]; + blk_ptr = curBlock; + var[i] = 0; + for (j=0; j < DCTSIZE_SQ; j++) { +#ifdef notdef + if (curBlock[j] != *(blk_ptr++)) { + printf("ARRAY ERROR: block %d\n", j); + } + temp = curBlock[j] - P_mean; +#endif + temp = *(blk_ptr++) - P_mean; + var[i] += (temp * temp); + } + var[i] /= DCTSIZE_SQ; + } + + /* Choose the minimum variance from the 4 blocks and use as the activity */ + var_sblk = var[0]; + for (i=1; i < 4; i++) { + var_sblk = (var_sblk < var[i] ? var_sblk : var[i]); + } + + + act_j = 1 + var_sblk; + total_act_j += act_j; + temp = (2 * act_j + avg_act); + N_act = ( (float) temp / (float) (act_j + 2*avg_act) ); + + return; +} + + + + +/*============================================================================* + * + * getRateMode () + * + * Returns the rate mode- interpreted as either Fixed or Variable + * + * RETURNS: integer + * + * SIDE EFFECTS: none + * + * + *==========================================================================*/ +int getRateMode() +{ + return RateControlMode; +} + + +/*===========================================================================* + * + * setBitRate () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. MPEG standard specifies that bit rate + * be rounded up to nearest 400 bits/sec. + * + * RETURNS: nothing + * + * SIDE EFFECTS: global variables + * + * NOTES: Should this be in the 400-bit units used in sequence header? + * + *===========================================================================*/ +void setBitRate (const char * const charPtr) +{ + int rate, rnd; + + rate = atoi(charPtr); + if (rate > 0) { + RateControlMode = FIXED_RATE; + } else { + printf("Parameter File Error: invalid BIT_RATE: \"%s\", defaults to Variable ratemode\n", + charPtr); + RateControlMode = VARIABLE_RATE; + bit_rate = -1; + } + rnd = (rate % 400); + rate += (rnd ? 400 -rnd : 0); /* round UP to nearest 400 bps */ + rate = (rate > MAX_BIT_RATE ? MAX_BIT_RATE : rate); + bit_rate = rate; + DBG_PRINT(("Bit rate is: %d\n", bit_rate)); +} + + + +/*===========================================================================* + * + * getBitRate () + * + * Returns the bit rate read from the parameter file. This is the + * real rate in bits per second, not in 400 bit units as is written to + * the sequence header. + * + * RETURNS: int (-1 if Variable mode operation) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int getBitRate () +{ + return bit_rate; +} + + + + +/*===========================================================================* + * + * setBufferSize () + * + * Checks the string parsed from the parameter file. Verifies + * number and sets global values. + * + * RETURNS: nothing + * + * SIDE EFFECTS: buffer_size global variable. + * + * NOTES: The global is in bits, NOT the 16kb units used in sequence header + * + *===========================================================================*/ +void setBufferSize (const char * const charPtr) +{ + int size; + + size = atoi(charPtr); + size = (size > MAX_BUFFER_SIZE ? MAX_BUFFER_SIZE : size); + if (size > 0) { + size = (16*1024) * ((size + (16*1024 - 1)) / (16*1024)); + buffer_size = size; + } else { + buffer_size = DEFAULT_BUFFER_SIZE; + printf("Parameter File Error: invalid BUFFER_SIZE: \"%s\", defaults to : %d\n", + charPtr, buffer_size); + } + DBG_PRINT(("Buffer size is: %d\n", buffer_size)); +} + + +/*===========================================================================* + * + * getBufferSize () + * + * returns the buffer size read from the parameter file. Size is + * in bits- not in units of 16k as written to the sequence header. + * + * RETURNS: int (or -1 if invalid) + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int getBufferSize () +{ + return buffer_size; +} + + + diff --git a/converter/ppm/ppmtompeg/readframe.c b/converter/ppm/ppmtompeg/readframe.c new file mode 100644 index 00000000..d1423c1f --- /dev/null +++ b/converter/ppm/ppmtompeg/readframe.c @@ -0,0 +1,1016 @@ +/*===========================================================================* + * readframe.c + * + * procedures to read in frames + * + * EXPORTED PROCEDURES: + * ReadFrame + * SetFileType + * SetFileFormat + * + *===========================================================================*/ + +/* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#define _BSD_SOURCE /* Make sure popen() is in stdio.h */ +#include "all.h" +#include <time.h> +#include <stdio.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> +#include "ppm.h" +#include "nstring.h" + +#include "mtypes.h" +#include "frames.h" +#include "prototypes.h" +#include "parallel.h" +#include "param.h" +#include "input.h" +#include "fsize.h" +#include "rgbtoycc.h" +#include "jpeg.h" +#include "opts.h" +#include "readframe.h" + + +/*==================* + * STATIC VARIABLES * + *==================*/ + +static int fileType = BASE_FILE_TYPE; +struct YuvLine { + uint8 data[3072]; + uint8 y[1024]; + int8 cr[1024]; + int8 cb[1024]; +}; + + +/*==================* + * Portability * + *==================*/ +#ifdef __OS2__ + #define popen _popen +#endif + + +/*==================* + * Global VARIABLES * + *==================*/ + +extern boolean GammaCorrection; +extern float GammaValue; +extern int outputWidth,outputHeight; +boolean resizeFrame; +const char *CurrFile; + +/*===============================* + * INTERNAL PROCEDURE prototypes * + *===============================*/ + +static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr, + int width)); +static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer, + int width, int height)); +static void DoGamma _ANSI_ARGS_((MpegFrame *mf, int width, int height)); + +static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h)); + +#define safe_fread(ptr,sz,len,fileptr) \ + if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) { \ + fprintf(stderr,"Input file too small! (%s)\n",CurrFile); \ + exit(1);} \ + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + + +void +SetResize(bool const set) { + resizeFrame = set; +} + + + +static void +ReadPNM(MpegFrame * const mpegFrameP, + FILE * const fp) { +/*---------------------------------------------------------------------------- + Read a PPM file containing one movie frame. +-----------------------------------------------------------------------------*/ + int pnmCols, pnmRows; + xelval maxval; + xel ** xels; + + xels = ppm_readppm(fp, &pnmCols, &pnmRows, &maxval); + ERRCHK(mpegFrameP, "ppm_readppm"); + + /* + * if this is the first frame read, set the global frame size + */ + Fsize_Note(mpegFrameP->id, pnmCols, pnmRows); + + PNMtoYUV(mpegFrameP, xels, Fsize_x, Fsize_y, maxval); + ppm_freearray(xels, pnmRows); +} + + + +static void +openFile(struct inputSource * const inputSourceP, + unsigned int const frameNumber, + const char * const conversion, + FILE ** const ifPP) { + + if (inputSourceP->stdinUsed) { + if (fileType == ANY_FILE_TYPE) + pm_error( + "ERROR : You cannot use a converter on frames when " + "you supply them as Standard Input. Either specify " + "INPUT_CONVERTER * in the parameter file or supply the " + "frames in files by specifying a directory with " + "INPUT_DIRECTORY in the parameter file."); + + *ifPP = stdin; + } else { + const char * fileName; + const char * fullFileName; + + GetNthInputFileName(inputSourceP, frameNumber, &fileName); + + asprintfN(&fullFileName, "%s/%s", currentPath, fileName); + + CurrFile = fullFileName; + + if (fileType == ANY_FILE_TYPE) { + char command[1024]; + const char * convertPtr; + char * commandPtr; + const char * charPtr; + + /* replace every occurrence of '*' with fullFileName */ + convertPtr = conversion; + commandPtr = command; + while (*convertPtr != '\0') { + while ((*convertPtr != '\0') && (*convertPtr != '*')) { + *commandPtr = *convertPtr; + ++commandPtr; + ++convertPtr; + } + + if (*convertPtr == '*') { + /* copy fullFileName */ + charPtr = fullFileName; + while (*charPtr != '\0') { + *commandPtr = *charPtr; + ++commandPtr; + ++charPtr; + } + ++convertPtr; /* go past '*' */ + } + } + *commandPtr = '\0'; + + *ifPP = popen(command, "r"); + if (*ifPP == NULL) { + pm_message( + "ERROR: Couldn't execute input conversion command " + "'%s'. errno=%d (%s)", + command, errno, strerror(errno)); + if (ioServer) + pm_error("IO SERVER: EXITING!!!"); + else + pm_error("SLAVE EXITING!!!"); + } + } else { + *ifPP = fopen(fullFileName, "rb"); + if (*ifPP == NULL) + pm_error("Couldn't open input file '%s'", fullFileName); + + if (baseFormat == JMOVIE_FILE_TYPE) + unlink(fullFileName); + } + strfree(fullFileName); + strfree(fileName); + } +} + + + +static void +closeFile(struct inputSource * const inputSourceP, + FILE * const ifP) { + + if (!inputSourceP->stdinUsed) { + if (fileType == ANY_FILE_TYPE) { + int rc; + rc = pclose(ifP); + if (rc != 0) + pm_message("WARNING: pclose() failed with errno %d (%s)", + errno, strerror(errno)); + } else + fclose(ifP); + } +} + + + +static bool +fileIsAtEnd(FILE * const ifP) { + + int c; + bool eof; + + c = getc(ifP); + if (c == EOF) { + if (feof(ifP)) + eof = TRUE; + else + pm_error("File error on getc() to position to image"); + } else { + int rc; + + eof = FALSE; + + rc = ungetc(c, ifP); + if (rc == EOF) + pm_error("File error doing ungetc() to position to image."); + } + return eof; +} + + + +void +ReadFrameFile(MpegFrame * const frameP, + FILE * const ifP, + const char * const conversion, + bool * const eofP) { +/*---------------------------------------------------------------------------- + Read a frame from the file 'ifP'. + + Return *eofP == TRUE iff we encounter EOF before we can get the + frame. +-----------------------------------------------------------------------------*/ + MpegFrame tempFrame; + MpegFrame * framePtr; + + /* To make this code fit Netpbm properly, we should remove handling + of all types except PNM and use pm_nextimage() to handle sensing + of end of stream. + */ + + if (fileIsAtEnd(ifP)) + *eofP = TRUE; + else { + *eofP = FALSE; + + if (resizeFrame) { + tempFrame.inUse = FALSE; + tempFrame.orig_y = NULL; + tempFrame.y_blocks = NULL; + tempFrame.decoded_y = NULL; + tempFrame.halfX = NULL; + framePtr = &tempFrame; + } else + framePtr = frameP; + + switch(baseFormat) { + case YUV_FILE_TYPE: + + /* Encoder YUV */ + if ((strncmp (yuvConversion, "EYUV", 4) == 0) || + (strncmp (yuvConversion, "UCB", 3) == 0)) + + ReadEYUV(framePtr, ifP, realWidth, realHeight); + + else + /* Abekas-type (interlaced) YUV */ + ReadAYUV(framePtr, ifP, realWidth, realHeight); + + break; + case Y_FILE_TYPE: + ReadY(framePtr, ifP, realWidth, realHeight); + break; + case PNM_FILE_TYPE: + ReadPNM(framePtr, ifP); + break; + case SUB4_FILE_TYPE: + ReadSub4(framePtr, ifP, yuvWidth, yuvHeight); + break; + case JPEG_FILE_TYPE: + case JMOVIE_FILE_TYPE: + ReadJPEG(framePtr, ifP); + break; + default: + break; + } + + if (resizeFrame) + Frame_Resize(frameP, &tempFrame, Fsize_x, Fsize_y, + outputWidth, outputHeight); + + if (GammaCorrection) + DoGamma(frameP, Fsize_x, Fsize_y); + + if (kill_dim) + DoKillDim(frameP, Fsize_x, Fsize_y); + + MotionSearchPreComputation(frameP); + } +} + + + +void +ReadFrame(MpegFrame * const frameP, + struct inputSource * const inputSourceP, + unsigned int const frameNumber, + const char * const conversion, + bool * const endOfStreamP) { +/*---------------------------------------------------------------------------- + Read the given frame, performing conversion as necessary. +-----------------------------------------------------------------------------*/ + FILE * ifP; + + openFile(inputSourceP, frameNumber, conversion, &ifP); + + ReadFrameFile(frameP, ifP, conversion, endOfStreamP); + + if (*endOfStreamP && !inputSourceP->stdinUsed) + pm_error("Premature EOF on file containing Frame %u", frameNumber); + + closeFile(inputSourceP, ifP); +} + + + +/*===========================================================================* + * + * SetFileType + * + * set the file type to be either a base type (no conversion), or + * any type (conversion required) + * + * RETURNS: nothing + * + * SIDE EFFECTS: fileType + * + *===========================================================================*/ +void +SetFileType(const char * const conversion) +{ + if ( strcmp(conversion, "*") == 0 ) { + fileType = BASE_FILE_TYPE; + } else { + fileType = ANY_FILE_TYPE; + } +} + + +/*===========================================================================* + * + * SetFileFormat + * + * set the file format (PNM, YUV, JPEG) + * + * RETURNS: nothing + * + * SIDE EFFECTS: baseFormat + * + *===========================================================================*/ +void +SetFileFormat(const char * const format) +{ + if ( strcmp(format, "PPM") == 0 ) { + baseFormat = PNM_FILE_TYPE; + } else if ( strcmp(format, "YUV") == 0 ) { + baseFormat = YUV_FILE_TYPE; + } else if ( strcmp(format, "Y") == 0 ) { + baseFormat = Y_FILE_TYPE; + } else if ( strcmp(format, "PNM") == 0 ) { + baseFormat = PNM_FILE_TYPE; + } else if (( strcmp(format, "JPEG") == 0 ) || ( strcmp(format, "JPG") == 0 )) { + baseFormat = JPEG_FILE_TYPE; + } else if ( strcmp(format, "JMOVIE") == 0 ) { + baseFormat = JMOVIE_FILE_TYPE; + } else if ( strcmp(format, "SUB4") == 0 ) { + baseFormat = SUB4_FILE_TYPE; + } else { + fprintf(stderr, "ERROR: Invalid file format: %s\n", format); + exit(1); + } +} + + + +FILE * +ReadIOConvert(struct inputSource * const inputSourceP, + unsigned int const frameNumber) { +/*---------------------------------------------------------------------------- + Do conversion; return handle to the appropriate file. +-----------------------------------------------------------------------------*/ + FILE *ifp; + char command[1024]; + const char * fullFileName; + char *convertPtr, *commandPtr; + const char * fileName; + + GetNthInputFileName(inputSourceP, frameNumber, &fileName); + + asprintfN(&fullFileName, "%s/%s", currentPath, fileName); + + if ( strcmp(ioConversion, "*") == 0 ) { + char buff[1024]; + ifp = fopen(fullFileName, "rb"); + sprintf(buff,"fopen \"%s\"",fullFileName); + ERRCHK(ifp, buff); + return ifp; + } + + /* replace every occurrence of '*' with fullFileName */ + convertPtr = ioConversion; + commandPtr = command; + while ( *convertPtr != '\0' ) { + while ( (*convertPtr != '\0') && (*convertPtr != '*') ) { + *commandPtr = *convertPtr; + commandPtr++; + convertPtr++; + } + + if ( *convertPtr == '*' ) { + /* copy fullFileName */ + const char * charPtr; + charPtr = fullFileName; + while ( *charPtr != '\0' ) { + *commandPtr = *charPtr; + commandPtr++; + charPtr++; + } + + convertPtr++; /* go past '*' */ + } + } + *commandPtr = '\0'; + + if ( (ifp = popen(command, "r")) == NULL ) { + fprintf(stderr, "ERROR: " + "Couldn't execute input conversion command:\n"); + fprintf(stderr, "\t%s\n", command); + fprintf(stderr, "errno = %d\n", errno); + if ( ioServer ) { + fprintf(stderr, "IO SERVER: EXITING!!!\n"); + } else { + fprintf(stderr, "SLAVE EXITING!!!\n"); + } + exit(1); + } + + strfree(fullFileName); + strfree(fileName); + + return ifp; +} + + + +/*===========================================================================* + * + * ReadEYUV + * + * read a Encoder-YUV file (concatenated Y, U, and V) + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadEYUV(mf, fpointer, width, height) + MpegFrame *mf; + FILE *fpointer; + int width; + int height; +{ + register int y; + uint8 junk[4096]; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < Fsize_y; y++) { /* Y */ + safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, width-Fsize_x, fpointer); + } + } + + /* read the leftover stuff on the bottom */ + for (y = Fsize_y; y < height; y++) { + safe_fread(junk, 1, width, fpointer); + } + + for (y = 0; y < (Fsize_y >> 1); y++) { /* U */ + safe_fread(mf->orig_cb[y], 1, Fsize_x >> 1, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer); + } + } + + /* read the leftover stuff on the bottom */ + for (y = (Fsize_y >> 1); y < (height >> 1); y++) { + safe_fread(junk, 1, width>>1, fpointer); + } + + for (y = 0; y < (Fsize_y >> 1); y++) { /* V */ + safe_fread(mf->orig_cr[y], 1, Fsize_x >> 1, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer); + } + } + + /* ignore leftover stuff on the bottom */ +} + +/*===========================================================================* + * + * ReadAYUV + * + * read an Abekas-YUV file + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadAYUV(mf, fpointer, width, height) + MpegFrame *mf; + FILE *fpointer; + int width; + int height; +{ + register int x, y; + struct YuvLine line1, line2; + uint8 junk[4096]; + uint8 *cbptr, *crptr; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < Fsize_y; y += 2) { + SeparateLine(fpointer, &line1, width); + SeparateLine(fpointer, &line2, width); + + /* Copy the Y values for each line to the frame */ + for (x = 0; x < Fsize_x; x++) { + mf->orig_y[y][x] = line1.y[x]; + mf->orig_y[y+1][x] = line2.y[x]; + } + + cbptr = &(mf->orig_cb[y>>1][0]); + crptr = &(mf->orig_cr[y>>1][0]); + + /* One U and one V for each two pixels horizontal as well */ + /* Toss the second line of Cr/Cb info, averaging was worse, + so just subsample */ + for (x = 0; x < (Fsize_x >> 1); x ++) { + cbptr[x] = line1.cb[x]; + crptr[x] = line1.cr[x]; + + } + } + + /* read the leftover stuff on the bottom */ + for (y = Fsize_y; y < height; y++) { + safe_fread(junk, 1, width<<1, fpointer); + } + +} + +/*===========================================================================* + * + * SeparateLine + * + * Separates one line of pixels into Y, U, and V components + * + * RETURNS: lineptr modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +SeparateLine(fpointer, lineptr, width) + FILE *fpointer; + struct YuvLine *lineptr; + int width; +{ + uint8 junk[4096]; + int8 *crptr, *cbptr; + uint8 *yptr; + int num, length; + int safe_read_count; + + + /* Sets the deinterlacing pattern */ + + /* shorthand for UYVY */ + if (strncmp(yuvConversion, "ABEKAS", 6) == 0) { + strcpy(yuvConversion, "UYVY"); + + /* shorthand for YUYV */ + } else if (strncmp(yuvConversion, "PHILLIPS", 8) == 0) { + strcpy(yuvConversion, "YUYV"); + } + + length = strlen (yuvConversion); + + if ((length % 2) != 0) { + fprintf (stderr, "ERROR : YUV_FORMAT must represent two pixels, hence must be even in length.\n"); + exit(1); + } + + /* each line in 4:2:2 chroma format takes 2X bytes to represent X pixels. + * each line in 4:4:4 chroma format takes 3X bytes to represent X pixels. + * Therefore, half of the length of the YUV_FORMAT represents 1 pixel. + */ + safe_fread(lineptr->data, 1, Fsize_x*(length>>1), fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, (width-Fsize_x)*(length>>1), fpointer); + } + + crptr = &(lineptr->cr[0]); + cbptr = &(lineptr->cb[0]); + yptr = &(lineptr->y[0]); + + for (num = 0; num < (Fsize_x*(length>>1)); num++) { + switch (yuvConversion[num % length]) { + case 'U': + case 'u': + *(cbptr++) = (lineptr->data[num]); + break; + case 'V': + case 'v': + *(crptr++) = (lineptr->data[num]); + break; + case 'Y': + case 'y': + *(yptr++) = (lineptr->data[num]); + break; + default: + fprintf(stderr, "ERROR: YUV_FORMAT must be one of the following:\n"); + fprintf(stderr, " ABEKAS\n"); + fprintf(stderr, " EYUV\n"); + fprintf(stderr, " PHILLIPS\n"); + fprintf(stderr, " UCB\n"); + fprintf(stderr, " or any even-length string consisting of the letters U, V, and Y.\n"); + exit(1); + } + + } + +} + + +/*===========================================================================* + * + * ReadY + * + * read a Y file + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadY(mf, fpointer, width, height) + MpegFrame *mf; + FILE *fpointer; + int width; + int height; +{ + register int y; + uint8 junk[4096]; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < Fsize_y; y++) { /* Y */ + safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer); + + /* read the leftover stuff on the right side */ + if ( width != Fsize_x ) { + safe_fread(junk, 1, width-Fsize_x, fpointer); + } + } + + /* read the leftover stuff on the bottom */ + for (y = Fsize_y; y < height; y++) { + safe_fread(junk, 1, width, fpointer); + } + + for (y = 0 ; y < (Fsize_y >> 1); y++) { + memset(mf->orig_cb[y], 128, (Fsize_x>>1)); + memset(mf->orig_cr[y], 128, (Fsize_x>>1)); + } +} + + +/*===========================================================================* + * + * ReadSub4 + * + * read a YUV file (subsampled even further by 4:1 ratio) + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +static void +ReadSub4(mf, fpointer, width, height) + MpegFrame *mf; + FILE *fpointer; + int width; + int height; +{ + register int y; + register int x; + uint8 buffer[1024]; + int safe_read_count; + + Fsize_Note(mf->id, width, height); + + Frame_AllocYCC(mf); + + for (y = 0; y < (height>>1); y++) { /* Y */ + safe_fread(buffer, 1, width>>1, fpointer); + for ( x = 0; x < (width>>1); x++ ) { + mf->orig_y[2*y][2*x] = buffer[x]; + mf->orig_y[2*y][2*x+1] = buffer[x]; + mf->orig_y[2*y+1][2*x] = buffer[x]; + mf->orig_y[2*y+1][2*x+1] = buffer[x]; + } + } + + for (y = 0; y < (height >> 2); y++) { /* U */ + safe_fread(buffer, 1, width>>2, fpointer); + for ( x = 0; x < (width>>2); x++ ) { + mf->orig_cb[2*y][2*x] = buffer[x]; + mf->orig_cb[2*y][2*x+1] = buffer[x]; + mf->orig_cb[2*y+1][2*x] = buffer[x]; + mf->orig_cb[2*y+1][2*x+1] = buffer[x]; + } + } + + for (y = 0; y < (height >> 2); y++) { /* V */ + safe_fread(buffer, 1, width>>2, fpointer); + for ( x = 0; x < (width>>2); x++ ) { + mf->orig_cr[2*y][2*x] = buffer[x]; + mf->orig_cr[2*y][2*x+1] = buffer[x]; + mf->orig_cr[2*y+1][2*x] = buffer[x]; + mf->orig_cr[2*y+1][2*x+1] = buffer[x]; + } + } +} + + +/*=====================* + * INTERNAL PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * DoGamma + * + * Gamma Correct the Lum values + * + * RETURNS: nothing + * + * SIDE EFFECTS: Raises Y values to power gamma. + * + *===========================================================================*/ +static void +DoGamma(mf, w, h) +MpegFrame *mf; +int w,h; +{ + static int GammaVal[256]; + static boolean init_done=FALSE; + int i,j; + + if (!init_done) { + for(i=0; i<256; i++) + GammaVal[i]=(unsigned char) (pow(((double) i)/255.0,GammaValue)*255.0+0.5); + init_done=TRUE; + } + + for (i=0; i< h; i++) { /* For each line */ + for (j=0; j<w; j++) { /* For each Y value */ + mf->orig_y[i][j] = GammaVal[mf->orig_y[i][j]]; + }} +} + + + + +/*===========================================================================* + * + * DoKillDim + * + * Applies an input filter to small Y values. + * + * RETURNS: nothing + * + * SIDE EFFECTS: Changes Y values: + * + * Output | / + | / + | / + | ! + | / + | ! + | / + | - + | / + | -- + | / + | -- + | / + ------------------------ + ^ kill_dim_break + ^kill_dim_end + kill_dim_slope gives the slope (y = kill_dim_slope * x +0) + from 0 to kill_dim_break + * + *===========================================================================*/ + +static void +DoKillDim(mf, w, h) +MpegFrame *mf; +int w,h; +{ + static boolean init_done=FALSE; + static unsigned char mapper[256]; + register int i,j; + double slope, intercept; + + slope = (kill_dim_end - kill_dim_break*kill_dim_slope)*1.0 / + (kill_dim_end - kill_dim_break); + intercept = kill_dim_end * (1.0-slope); + + if (!init_done) { + for(i=0; i<256; i++) { + if (i >= kill_dim_end) { + mapper[i] = (char) i; + } else if (i >= kill_dim_break) { + mapper[i] = (char) (slope*i + intercept); + } else { /* i <= kill_dim_break */ + mapper[i] = (char) floor(i*kill_dim_slope + 0.49999); + } + } + init_done = TRUE; + } + + for (i=0; i < h; i++) { /* For each line */ + for (j=0; j < w; j++) { /* For each Y value */ + mf->orig_y[i][j] = mapper[mf->orig_y[i][j]]; + }} +} + + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/readframe.c,v 1.27 1995/08/14 22:31:40 smoot Exp $ + * $Log: readframe.c,v $ + * Revision 1.27 1995/08/14 22:31:40 smoot + * reads training info from PPms now (needed for piping reads) + * + * Revision 1.26 1995/08/07 21:48:36 smoot + * better error reporting, JPG == JPEG now + * + * Revision 1.25 1995/06/12 20:30:12 smoot + * added popen for OS2 + * + * Revision 1.24 1995/06/08 20:34:36 smoot + * added "b"'s to fopen calls to make MSDOS happy + * + * Revision 1.23 1995/05/03 10:16:01 smoot + * minor compile bug with static f + * + * Revision 1.22 1995/05/02 22:00:12 smoot + * added TUNEing, setting near-black values to black + * + * Revision 1.21 1995/03/27 21:00:01 eyhung + * fixed bug with some long jpeg names + * + * Revision 1.20 1995/02/02 01:05:54 eyhung + * Fixed aAdded error checking for stdin + * + * Revision 1.19 1995/02/01 05:01:12 eyhung + * Removed troubleshooting printf + * + * Revision 1.18 1995/01/31 21:08:16 eyhung + * Improved YUV_FORMAT strings with better algorithm + * + * Revision 1.17 1995/01/27 23:34:09 eyhung + * Removed temporary JPEG files created by JMOVIE input + * + * Revision 1.16 1995/01/27 21:57:43 eyhung + * Added case for reading original JMOVIES + * + * Revision 1.14 1995/01/24 23:47:51 eyhung + * Confusion with Abekas format fixed : all other YUV revisions are wrong + * + * Revision 1.13 1995/01/20 00:02:30 smoot + * added gamma correction + * + * Revision 1.12 1995/01/19 23:09:21 eyhung + * Changed copyrights + * + * Revision 1.11 1995/01/17 22:23:07 aswan + * AbekasYUV chrominance implementation fixed + * + * Revision 1.10 1995/01/17 21:26:25 smoot + * Tore our average on Abekus/Phillips reconstruct + * + * Revision 1.9 1995/01/17 08:22:34 eyhung + * Debugging of ReadAYUV + * + * Revision 1.8 1995/01/16 13:18:24 eyhung + * Interlaced YUV format (e.g. Abekas) capability added (slightly buggy) + * + * Revision 1.7 1995/01/16 06:58:23 eyhung + * Added skeleton of ReadAYUV (for Abekas YUV files) + * + * Revision 1.6 1995/01/13 23:22:23 smoot + * Added ReadY, so we can make black&white movies (how artsy!) + * + * Revision 1.5 1994/12/16 00:20:40 smoot + * Now errors out on too small an input file + * + * Revision 1.4 1994/11/12 02:11:59 keving + * nothing + * + * Revision 1.3 1994/03/15 00:27:11 keving + * nothing + * + * Revision 1.2 1993/12/22 19:19:01 keving + * nothing + * + * Revision 1.1 1993/07/22 22:23:43 keving + * nothing + * + */ diff --git a/converter/ppm/ppmtompeg/rgbtoycc.c b/converter/ppm/ppmtompeg/rgbtoycc.c new file mode 100644 index 00000000..766b8902 --- /dev/null +++ b/converter/ppm/ppmtompeg/rgbtoycc.c @@ -0,0 +1,204 @@ +/*===========================================================================* + * rgbtoycc.c * + * * + * Procedures to convert from RGB space to YUV space * + * * + * EXPORTED PROCEDURES: * + * PNMtoYUV * + * PPMtoYUV * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "pnm.h" +#include "all.h" +#include "frame.h" +#include "rgbtoycc.h" + + +static float *mult299, *mult587, *mult114, *mult16874, *mult33126, + *mult5, *mult41869, *mult08131; /* malloc'ed */ + /* These are tables we use for fast arithmetic */ +static pixval table_maxval = 0; + /* The maxval used to compute the above arrays. Zero means + the above arrays don't exist yet + */ + +static void +compute_mult_tables(const pixval maxval) { + + /* For speed, we do the arithmetic with eight tables that reduce a + bunch of multiplications and divisions to a simple table lookup. + + Because a large maxval could require a significant amount of + table space, we allocate the space dynamically. + + If we had to compute the tables for every frame, it wouldn't be + fast at all, but since all the frames normally have the same + maxval, we only need to compute them once. But just in case, + we check each frame to see if it has a different maxval and + recompute the tables if so. + */ + + if (table_maxval != maxval) { + /* We need to compute or re-compute the multiplication tables */ + if (table_maxval != 0) { + free(mult299); free(mult587); free(mult114); free(mult16874); + free(mult33126); free(mult5); free(mult41869); free(mult08131); + } + table_maxval = maxval; + + mult299 = malloc((table_maxval+1)*sizeof(float)); + mult587 = malloc((table_maxval+1)*sizeof(float)); + mult114 = malloc((table_maxval+1)*sizeof(float)); + mult16874 = malloc((table_maxval+1)*sizeof(float)); + mult33126 = malloc((table_maxval+1)*sizeof(float)); + mult5 = malloc((table_maxval+1)*sizeof(float)); + mult41869 = malloc((table_maxval+1)*sizeof(float)); + mult08131 = malloc((table_maxval+1)*sizeof(float)); + + if (mult299 == NULL || mult587 == NULL || mult114 == NULL || + mult16874 == NULL || mult33126 == NULL || mult5 == NULL || + mult41869 == NULL || mult08131 == NULL) + pm_error("Unable to allocate storage for arithmetic tables.\n" + "We need %d bytes, which is the maxval of the input " + "image, plus 1,\n" + "times the storage size of a floating point value.", + 8 * (table_maxval+1)*sizeof(float)); + + { + int index; + + for (index = 0; index <= table_maxval; index++ ) { + mult299[index] = index*0.29900 * 255 / table_maxval; + mult587[index] = index*0.58700 * 255 / table_maxval; + mult114[index] = index*0.11400 * 255 / table_maxval; + mult16874[index] = -0.16874*index * 255 / table_maxval; + mult33126[index] = -0.33126*index * 255 / table_maxval; + mult5[index] = index*0.50000 * 255 / table_maxval; + mult41869[index] = -0.41869*index * 255 / table_maxval; + mult08131[index] = -0.08131*index * 255 / table_maxval; + } + } + } +} + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + + +void +PNMtoYUV(MpegFrame * const frameP, + xel ** const xels, + unsigned int const cols, + unsigned int const rows, + xelval const maxval) { +/*---------------------------------------------------------------------------- + Set the raster of the MPEG frame *frameP from the libnetpbm input + 'xels'. Note that the raster information in a MpegFrame is in YUV + form. +-----------------------------------------------------------------------------*/ + int x, y; + uint8 *dy0, *dy1; + uint8 *dcr, *dcb; + pixel *src0, *src1; + + compute_mult_tables(maxval); /* This sets up mult299[], etc. */ + + Frame_AllocYCC(frameP); + + /* + * okay. Now, convert everything into YCbCr space. (the specific + * numbers come from the JPEG source, jccolor.c) The conversion + * equations to be implemented are therefore + * + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + * + * With Y, Cb, and Cr then normalized to the range 0 - 255. + */ + + for (y = 0; y < rows; y += 2) { + for (x = 0, src0 = xels[y], src1 = xels[y + 1], + dy0 = frameP->orig_y[y], dy1 = frameP->orig_y[y + 1], + dcr = frameP->orig_cr[y >> 1], dcb = frameP->orig_cb[y >> 1]; + x < cols; + x += 2, dy0 += 2, dy1 += 2, dcr++, + dcb++, src0 += 2, src1 += 2) { + + *dy0 = (mult299[PPM_GETR(*src0)] + + mult587[PPM_GETG(*src0)] + + mult114[PPM_GETB(*src0)]); + + *dy1 = (mult299[PPM_GETR(*src1)] + + mult587[PPM_GETG(*src1)] + + mult114[PPM_GETB(*src1)]); + + dy0[1] = (mult299[PPM_GETR(src0[1])] + + mult587[PPM_GETG(src0[1])] + + mult114[PPM_GETB(src0[1])]); + + dy1[1] = (mult299[PPM_GETR(src1[1])] + + mult587[PPM_GETG(src1[1])] + + mult114[PPM_GETB(src1[1])]); + + *dcb = ((mult16874[PPM_GETR(*src0)] + + mult33126[PPM_GETG(*src0)] + + mult5[PPM_GETB(*src0)] + + mult16874[PPM_GETR(*src1)] + + mult33126[PPM_GETG(*src1)] + + mult5[PPM_GETB(*src1)] + + mult16874[PPM_GETR(src0[1])] + + mult33126[PPM_GETG(src0[1])] + + mult5[PPM_GETB(src0[1])] + + mult16874[PPM_GETR(src1[1])] + + mult33126[PPM_GETG(src1[1])] + + mult5[PPM_GETB(src1[1])]) / 4) + 128; + + *dcr = ((mult5[PPM_GETR(*src0)] + + mult41869[PPM_GETG(*src0)] + + mult08131[PPM_GETB(*src0)] + + mult5[PPM_GETR(*src1)] + + mult41869[PPM_GETG(*src1)] + + mult08131[PPM_GETB(*src1)] + + mult5[PPM_GETR(src0[1])] + + mult41869[PPM_GETG(src0[1])] + + mult08131[PPM_GETB(src0[1])] + + mult5[PPM_GETR(src1[1])] + + mult41869[PPM_GETG(src1[1])] + + mult08131[PPM_GETB(src1[1])]) / 4) + 128; + + DBG_PRINT(("%3d,%3d: (%3d,%3d,%3d) --> (%3d,%3d,%3d)\n", + x, y, + PPM_GETR(*src0), PPM_GETG(*src0), PPM_GETB(*src0), + *dy0, *dcb, *dcr)); + } + } +} diff --git a/converter/ppm/ppmtompeg/specifics.c b/converter/ppm/ppmtompeg/specifics.c new file mode 100644 index 00000000..c7bbfb5b --- /dev/null +++ b/converter/ppm/ppmtompeg/specifics.c @@ -0,0 +1,688 @@ +/*===========================================================================* + * specifics.c * + * * + * basic procedures to deal with the specifics file * + * * + * EXPORTED PROCEDURES: * + * Specifics_Init * + * Spec_Lookup * + * SpecTypeLookup * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + + +/*==============* + * HEADER FILES * + *==============*/ + +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "frame.h" +#include "fsize.h" +#include "dct.h" +#include "specifics.h" +#include <stdio.h> +#include <string.h> +#include "prototypes.h" + +/*====================* + * System Information * + *====================*/ + +#define CPP_LOC "/lib/cpp" + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern boolean specificsOn; +extern char specificsFile[]; +extern char specificsDefines[]; +FrameSpecList *fsl; + +/*=====================* + * Internal procedures * + *=====================*/ + +void Parse_Specifics_File _ANSI_ARGS_((FILE *fp)); +void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp)); +void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp)); +FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); +void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs)); +Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, + boolean rel, int qs)); +FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); +#define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c) +#define CvtType(x) ReallyCvt(my_upper(x)) +#define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1)) +#define SkipToSpace(lp) while ((*lp != ' ') && (*lp != '\n') && (*lp != '\0')) lp++ +#define EndString(lp) ((*lp == '\n') || (*lp == '\0')) + +/*============================================================= + * SPEC FILE FORMAT (version 1): + +Specs files are processed with the c preprecoessor, so use C style comments +and #defines if you wish. + +frames, blocks, and slices are numbered from 0. +(sorry) + +In order by frame number, slice number, block number +(if you skip slices it's fine). +Can have specifics for any frame, block, or slice. +Format: +version N + Specify the version of the specifics file format (this is 1) +frame N T M + Sets frame number N to type T and Qscale M + (type T is I,B,P,other, other means unspec. I recomend - ) +slice M Q + Sets slice M (in frame N as defined by a previous frame command) + to qscale Q +block M Q + Sets block M to qscale Q, in frame N previously specified. + +Unspecified frame types are set via the last I frame set, which is forced +to act as the first I of the GOP. +FORCE_ENCODE_LAST_FRAME overrides specifics on the final frame type. +Note that Qscale changes in skipped blocks will be lost! + +Version 2: +frames and slices are the same as above, but Q in blocks can be relative, i.e. ++N or -N. Clipping to 1..31 is done but sequences like +block 1 2 +block 2 -3 +block 3 +3 + +has undefined results (as present block 3 would be Qscale 2). + +In addition motion vectors can be specified: +block M Q skip + Says to skip the block (not really an MV, but....) +block M Q bi fx fy bx by + Sets block M to quality Q. It will be a bidirectional block. + fx/fy is the forward (like a P frame) vector, bx/y is the back +block M Q forw fx fy +block M Q back bx by + Single directional. + +All vectors are specified in HALF PIXEL fixed point units, i.e. +3.5 pixels is 7 +To specify a vector but not touch the q factor, set Q to 0 + +*=============================================================*/ + + +/*=============* + * Local State * + *=============*/ + +static char version = -1; + +/*================================================================ + * + * Specifics_Init + * + * Cpp's and reads in the specifics file. Creates fsl data structure. + * + * Returns: nothing + * + * Modifies: fsl, file specificsFile".cpp" + * + *================================================================ + */ +void Specifics_Init() +{ + char command[1100]; + FILE *specificsFP; + + sprintf(command, "/bin/rm -f %s.cpp", specificsFile); + system(command); + sprintf(command, "%s -P %s %s %s.cpp", + CPP_LOC, specificsDefines, specificsFile, specificsFile); + system(command); + strcat(specificsFile, ".cpp"); + if ((specificsFP = fopen(specificsFile, "r")) == NULL) { + fprintf(stderr, "Error with specifics file, cannot open %s\n", specificsFile); + exit(1); + } + printf("Specifics file: %s\n", specificsFile); + Parse_Specifics_File(specificsFP); + sprintf(command, "/bin/rm -f %s.cpp", specificsFile); + system(command); + +} + + + + +/*================================================================ + * + * Parse_Specifics_File + * + * Read through the file passed in creating the fsl data structure + * There is a primary routine, and helpers for the specific versions. + * + * Returns: Nothing + * + * Modifies: fsl + * + *================================================================ + */ +void Parse_Specifics_File(fp) +FILE *fp; +{ + char line[1024], *lp; + int vers; + + while ((fgets(line, 1023, fp)) != NULL) { + lp = &line[0]; + while ((*lp == ' ') || (*lp == '\t')) lp++; + if (( *lp == '#' ) || (*lp=='\n')) { + continue; + } + + switch (my_upper(*lp)) { + case 'F': case 'S': case 'B': + fprintf(stderr, "Must specify version at beginning of specifics file\n"); + exit(0); + break; + case 'V': + lp += 7; + if (1 != sscanf(lp, "%d", &vers)) { + fprintf(stderr," Improper version line in specs file: %s\n", line); + } else { + switch (vers) { + case 1: + version = vers; + Parse_Specifics_File_v1(fp); + break; + case 2: + version = vers; + Parse_Specifics_File_v2(fp); + break; + default: + fprintf(stderr, "Improper version line in specs file: %s\n", line); + fprintf(stderr, "\tSpecifics file will be IGNORED.\n"); + specificsOn = FALSE; + return; + break; + }} + break; + default: + fprintf(stderr, "Specifics file: What? *%s*\n", line); + break; + }} + +} + +/* Version 1 */ +void Parse_Specifics_File_v1(fp) +FILE *fp; +{ + char line[1024],*lp; + FrameSpecList *current, *new; + char typ; + int fnum,snum, bnum, qs, newqs; + int num_scanned; + + fsl = MakeFslEntry(); + current = fsl; + + while ((fgets(line,1023, fp)) != NULL) { + lp = &line[0]; + while ((*lp == ' ') || (*lp == '\t')) lp++; + if (( *lp == '#' ) || (*lp=='\n')) { + continue; + } + + switch (my_upper(*lp)) { + case 'F': + lp += 6; + sscanf(lp, "%d %c %d", &fnum, &typ, &qs); + if (current->framenum != -1) { + new=MakeFslEntry(); + current->next = new; + current = new; + } + current->framenum = fnum; + current->frametype = CvtType(typ); + if (qs <= 0) qs = -1; + current->qscale = qs; + break; + case 'S': + lp += 6; + sscanf(lp, "%d %d", &snum, &newqs); + if (qs == newqs) break; + qs = newqs; + AddSlc(current, snum, qs); + break; + case 'B': + lp += 6; + num_scanned = sscanf(lp, "%d %d", &bnum, &newqs); + if (qs == newqs) break; + qs = newqs; + AddBs(current, bnum, FALSE, qs); + break; + case 'V': + fprintf(stderr, "Cannot specify version twice! Taking first (%d)\n", version); + break; + default: + fprintf(stderr," What? *%s*\n", line); + break; + }} + +} + +/* Version 2 */ +void Parse_Specifics_File_v2(fp) +FILE *fp; +{ + char line[1024], *lp; + FrameSpecList *current, *new; + char typ; + int fnum, snum, bnum, qs, newqs; + int num_scanned, fx=0, fy=0, sx=0, sy=0; + char kind[100]; + Block_Specifics *new_blk; + boolean relative; + + fsl = MakeFslEntry(); + current = fsl; + + while ((fgets(line,1023,fp))!=NULL) { + lp = &line[0]; + while ((*lp == ' ') || (*lp == '\t')) lp++; + if (( *lp == '#' ) || (*lp=='\n')) { + continue; + } + + switch (my_upper(*lp)) { + case 'F': + lp += 6; + sscanf(lp,"%d %c %d", &fnum, &typ, &qs); + new = MakeFslEntry(); + if (current->framenum != -1) { + current->next = new; + current = new; + } + current->framenum = fnum; + current->frametype = CvtType(typ); + if (qs <= 0) qs = -1; + current->qscale = qs; + break; + case 'S': + lp += 6; + sscanf(lp,"%d %d", &snum, &newqs); + if (qs == newqs) break; + qs = newqs; + AddSlc(current, snum, qs); + break; + case 'B': + lp += 6; + num_scanned = 0; + bnum = atoi(lp); + SkipToSpace(lp); + while ((*lp != '-') && (*lp != '+') && + ((*lp < '0') || (*lp > '9'))) lp++; + relative = ((*lp == '-') || (*lp == '+')); + newqs = atoi(lp); + SkipToSpace(lp); + if (EndString(lp)) { + num_scanned = 2; + } else { + num_scanned = 2+sscanf(lp, "%s %d %d %d %d", kind, &fx, &fy, &sx, &sy); + } + + qs = newqs; + new_blk = AddBs(current, bnum, relative, qs); + if (num_scanned > 2) { + BlockMV *tmp; + tmp = (BlockMV *) malloc(sizeof(BlockMV)); + switch (num_scanned) { + case 7: + tmp->typ = TYP_BOTH; + tmp->fx = fx; + tmp->fy = fy; + tmp->bx = sx; + tmp->by = sy; + new_blk->mv = tmp; + break; + case 3: + tmp->typ = TYP_SKIP; + new_blk->mv = tmp; + break; + case 5: + if (my_upper(kind[0]) == 'B') { + tmp->typ = TYP_BACK; + tmp->bx = fx; + tmp->by = fy; + } else { + tmp->typ = TYP_FORW; + tmp->fx = fx; + tmp->fy = fy; + } + new_blk->mv = tmp; + break; + default: + fprintf(stderr, + "Bug in specifics file! Skipping short/long entry: %s\n",line); + break; + } + } else { + new_blk->mv = (BlockMV *) NULL; + } + + break; + case 'V': + fprintf(stderr, + "Cannot specify version twice! Taking first (%d).\n", + version); + break; + default: + printf("What? *%s*\n",line); + break; + }} + +} + + + + +/*================================================================= + * + * MakeFslEntry + * + * Makes a single entry in for the fsl linked list (makes a frame) + * + * Returns: the new entry + * + * Modifies: nothing + * + *================================================================= + */ +FrameSpecList *MakeFslEntry() +{ + FrameSpecList *fslp; + fslp = (FrameSpecList *) malloc(sizeof(FrameSpecList)); + fslp->framenum = -1; + fslp->slc = (Slice_Specifics *) NULL; + fslp->bs = (Block_Specifics *) NULL; + return fslp; +} + + + + + +/*================================================================ + * + * AddSlc + * + * Adds a slice to framespeclist c with values snum and qs + * + * Returns: nothing + * + * Modifies: fsl's structure + * + *================================================================ + */ +void AddSlc(c, snum, qs) +FrameSpecList *c; +int snum,qs; +{ + Slice_Specifics *new; + static Slice_Specifics *last; + + new = (Slice_Specifics *) malloc(sizeof(Slice_Specifics)); + new->num = snum; + new->qscale = qs; + new->next = (Slice_Specifics *)NULL; + if (c->slc == (Slice_Specifics *)NULL) { + last = new; + c->slc = new; + } else { + last->next = new; + last = new; + } +} + + + + + +/*================================================================ + * + * AddBs + * + * Adds a sliceblock to framespeclist c with values bnum and qs + * + * Returns: pointer to the new block spec + * + * Modifies: fsl's structure + * + *================================================================ + */ +Block_Specifics *AddBs(c,bnum,rel,qs) +FrameSpecList *c; +boolean rel; +int bnum,qs; +{ + Block_Specifics *new; + static Block_Specifics *last; + + new = (Block_Specifics *) malloc(sizeof(Block_Specifics)); + new->num = bnum; + if (qs == 0) rel = TRUE; + new->relative = rel; + new->qscale = qs; + new->next = (Block_Specifics *)NULL; + new->mv = (BlockMV *) NULL; + if (c->bs == (Block_Specifics *)NULL) { + last = new; + c->bs = new; + } else { + last->next = new; + last = new; + } + return new; +} + + + + + + +/*================================================================ + * + * SpecLookup + * + * Find out if there is any changes to be made for the qscale + * at entry fn.num (which is of type typ). Sets info to point to + * motion vector info (if any), else NULL. + * + * Returns: new qscale or -1 + * + * Modifies: *info (well, internal cache can change) + * + *================================================================ + */ + +int SpecLookup(fn,typ,num,info,start_qs) +int fn,typ,num; +BlockMV **info; +int start_qs; +{ + static FrameSpecList *last = (FrameSpecList *) NULL; + Slice_Specifics *sptr=(Slice_Specifics *) NULL; + Block_Specifics *bptr=(Block_Specifics *) NULL; + FrameSpecList *tmp; + boolean found_it; + static int leftovers = 0; /* Used in case of forced movement into 1..31 range */ + + *info = (BlockMV * )NULL; + if (last == (FrameSpecList *) NULL){ + /* No cache, try to find number fn */ + tmp = fsl; + found_it = FALSE; + while (tmp != (FrameSpecList *) NULL) { + if (tmp->framenum == fn) { + found_it = TRUE; + break; + } else tmp = tmp->next; + } + if (!found_it) return -1; + last=tmp; + } else { + if (last->framenum != fn) { /* cache miss! */ + /* first check if it is next */ + if ((last->next != (FrameSpecList *) NULL) && + (last->next->framenum == fn)) { + last = last->next; + } else { + /* if not next, check from the start. + (this allows people to put frames out of order,even + though the spec doesnt allow it.) */ + tmp = fsl; + found_it = FALSE; + while (tmp != (FrameSpecList *) NULL) { + if (tmp->framenum==fn) {found_it = TRUE; break;} + tmp = tmp->next; + } + if (!found_it) return -1; + last = tmp; + } + } + } + /* neither of these should ever be true, unless there is a bug above */ + if (last == (FrameSpecList *) NULL) { + fprintf(stderr, "PROGRAMMER ERROR: last is null!\n"); + return -1; + } + if (last->framenum!=fn) { + fprintf(stderr, "PROGRAMMER ERROR: last has wrong number!\n"); + return -1; /* no data on it */ + } + + switch(typ) { + case 0: /* Frame: num is ignored */ + leftovers = 0; +#ifdef BLEAH + printf("QSchange frame %d to %d\n", fn, last->qscale); +#endif + return last->qscale; + break; + + case 1: /* Slice */ + leftovers = 0; + /* So, any data on slices? */ + if (last->slc == (Slice_Specifics *) NULL) return -1; + for (sptr = last->slc; sptr != (Slice_Specifics *) NULL; sptr = sptr->next) { + if (sptr->num == num) { +#ifdef BLEAH + printf("QSchange Slice %d.%d to %d\n", fn, num, sptr->qscale); +#endif + if (sptr->qscale == 0) return -1; + return sptr->qscale; + } + } + break; + + case 2: /* block */ + /* So, any data on blocks? */ + if (last->bs == (Block_Specifics *) NULL) { + return -1; + } + for (bptr=last->bs; bptr != (Block_Specifics *) NULL; bptr=bptr->next) { + if (bptr->num == num) { + int new_one; +#ifdef BLEAH + printf("QSchange Block %d.%d to %d\n", fn, num, bptr->qscale); +#endif + *info = bptr->mv; + if (bptr->relative) { + if (bptr->qscale == 0) { + /* Do nothing! */ + new_one = start_qs; + } else { + new_one = start_qs + bptr->qscale + leftovers; + if (new_one < 1) { + leftovers = new_one - 1; + new_one = 1; + } else if (new_one > 31) { + leftovers = new_one - 31; + new_one = 31; + } else leftovers = 0; + }} + else { + new_one = bptr->qscale; + leftovers = 0; + } + return new_one; + } + } + break; + default: + fprintf(stderr, "PROGRAMMER ERROR: reached unreachable code in SpecLookup\n"); + break; + } + /* no luck */ + return -1; +} + + +/*================================================================ + * + * SpecTypeLookup + * + * Find out if there is any changes to be made for the type of frame + * at frame fn. + * + * Returns: new type or -1 (unspecified) + * + *================================================================ + */ +int SpecTypeLookup(fn) +int fn; +{ + FrameSpecList *tmp; + + /* try to find number fn */ + tmp = fsl; + do { + if (tmp->framenum == fn) break; + else tmp = tmp->next; + } while (tmp != (FrameSpecList *) NULL); + if (tmp == (FrameSpecList *) NULL) { +#ifdef BLEAH + printf("Frame %d type not specified\n", fn); +#endif + return -1; + } +#ifdef BLEAH + printf("Frame %d type set to %d\n", fn, tmp->frametype); +#endif + return tmp->frametype; +} diff --git a/converter/ppm/ppmtompeg/subsample.c b/converter/ppm/ppmtompeg/subsample.c new file mode 100644 index 00000000..5ec71814 --- /dev/null +++ b/converter/ppm/ppmtompeg/subsample.c @@ -0,0 +1,280 @@ +/*===========================================================================* + * subsample.c * + * * + * Procedures concerned with subsampling * + * * + * EXPORTED PROCEDURES: * + * LumMotionErrorA * + * LumMotionErrorB * + * LumMotionErrorC * + * LumMotionErrorD * + * * + *===========================================================================*/ + +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/*==============* + * HEADER FILES * + *==============*/ + +#include "pm_c_util.h" +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "bitio.h" +#include "prototypes.h" + + + +static void +computePrevFyFx(MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + uint8 *** const prevP, + int * const fyP, + int * const fxP) { + + boolean const xHalf = (ABS(m.x) % 2 == 1); + boolean const yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, m.y/2, m.x/2, fyP, fxP); + + if (xHalf) { + if (m.x < 0) + --*fxP; + + if (yHalf) { + if (m.y < 0) + --*fyP; + + *prevP = prevFrame->halfBoth; + } else + *prevP = prevFrame->halfX; + } else if (yHalf) { + if (m.y < 0) + --*fyP; + + *prevP = prevFrame->halfY; + } else + *prevP = prevFrame->ref_y; +} + + + +static int32 +evenColDiff(const uint8 * const macross, + const int32 * const currentRow) { + + return 0 + + ABS(macross[ 0] - currentRow[ 0]) + + ABS(macross[ 2] - currentRow[ 2]) + + ABS(macross[ 4] - currentRow[ 4]) + + ABS(macross[ 6] - currentRow[ 6]) + + ABS(macross[ 8] - currentRow[ 8]) + + ABS(macross[10] - currentRow[10]) + + ABS(macross[12] - currentRow[12]) + + ABS(macross[14] - currentRow[14]); +} + + + +static int32 +oddColDiff(const uint8 * const macross, + const int32 * const currentRow) { + + return 0 + + ABS(macross[ 1] - currentRow[ 1]) + + ABS(macross[ 3] - currentRow[ 3]) + + ABS(macross[ 5] - currentRow[ 5]) + + ABS(macross[ 7] - currentRow[ 7]) + + ABS(macross[ 9] - currentRow[ 9]) + + ABS(macross[11] - currentRow[11]) + + ABS(macross[13] - currentRow[13]) + + ABS(macross[15] - currentRow[15]); +} + + + +/*===========================================================================* + * + * LumMotionErrorA + * + * compute the motion error for the A subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorA(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + uint8 ** prev; + int fy, fx; + unsigned int rowNumber; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + diff = 0; /* initial value */ + + for (rowNumber = 0; rowNumber < 16; rowNumber +=2) { + uint8 * const macross = &(prev[fy + rowNumber][fx]); + const int32 * const currentRow = currentBlockP->l[rowNumber]; + + diff += evenColDiff(macross, currentRow); + + if (diff > bestSoFar) + return diff; + } + return diff; +} + + + +/*===========================================================================* + * + * LumMotionErrorB + * + * compute the motion error for the B subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorB(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + uint8 **prev; + int fy, fx; + unsigned int rowNumber; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + diff = 0; /* initial value */ + + for (rowNumber = 0; rowNumber < 16; rowNumber +=2) { + uint8 * const macross = &(prev[fy + rowNumber][fx]); + const int32 * const currentRow = currentBlockP->l[rowNumber]; + + diff += oddColDiff(macross, currentRow); + + if (diff > bestSoFar) + return diff; + } + return diff; +} + + +/*===========================================================================* + * + * LumMotionErrorC + * + * compute the motion error for the C subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorC(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + uint8 **prev; + int fy, fx; + unsigned int rowNumber; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + diff = 0; /* initial value */ + + for (rowNumber = 1; rowNumber < 16; rowNumber +=2) { + uint8 * const macross = &(prev[fy + rowNumber][fx]); + const int32 * const currentRow = currentBlockP->l[rowNumber]; + + diff += evenColDiff(macross, currentRow); + + if (diff > bestSoFar) + return diff; + } + return diff; +} + + +/*===========================================================================* + * + * LumMotionErrorD + * + * compute the motion error for the D subsampling pattern + * + * RETURNS: the error, or some number greater if it is worse + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumMotionErrorD(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + uint8 ** prev; + int fy, fx; + unsigned int rowNumber; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + diff = 0; /* initial value */ + + for (rowNumber = 1; rowNumber < 16; rowNumber +=2) { + uint8 * const macross = &(prev[fy + rowNumber][fx]); + const int32 * const currentRow = currentBlockP->l[rowNumber]; + + diff += oddColDiff(macross, currentRow); + + if (diff > bestSoFar) + return diff; + } + return diff; +} diff --git a/converter/ppm/ppmtompeg/tst/README b/converter/ppm/ppmtompeg/tst/README new file mode 100644 index 00000000..4e35f6ba --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/README @@ -0,0 +1,30 @@ +The test in this directory is derived from that in the Berkeley mpeg +package, but we have trimmed it down for the purposes of the Netpbm +package to save space. + +First of all, the Berkeley package had Berkeley YUV files for sample input +(in the 'ts' directory). But we converted them to JPEG to save a great +deal of space (even when the package is gzipped). + +We modified the ts.param file to work with the JPEG files and updated the +expected results file to correspond to the JPEG input (the expected results +are different after the JPEG conversion because JPEG conversion is lossy). + +We kept some of the other parameter files from the Berkeley package in +case someone can get some use out of them, but did not update them to +use the JPEG files. You'll have to do that yourself. And we removed +the expected results files for them, since you can't generate those +results with the inputs we have supplied. + +Note that JPEG input doesn't really exercise the most standard function +of ppmtompeg. As its name suggests, it's main purpose is to take PPM +frames as input. You can use jpegtoppm to create PPM input and then +modify the parameter files if you want to test that. We have not, however +supplied an expected results file for that. + +The .mpg files are what ppmtojpeg output as the mpeg movie when we +ran it on the jpeg files in the 'ts' directory. + +The .stat files are what ppmtojpeg output when we used the -stat +option in generating the expected results. As part of your test, use +the -stat option and compare yours to the expected results. diff --git a/converter/ppm/ppmtompeg/tst/gop.param b/converter/ppm/ppmtompeg/tst/gop.param new file mode 100644 index 00000000..96900a3d --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/gop.param @@ -0,0 +1,30 @@ +# test suite parameter file + +PATTERN IBPBIBPBPB +OUTPUT /tmp/ts.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +INPUT_CONVERT * +GOP_SIZE 10 +SLICES_PER_FRAME 1 + +INPUT_DIR ./tst/ts + +INPUT +stennis.*.yuv [30-39] +stennis.*.yuv [30-39] +END_INPUT + +PIXEL HALF +RANGE 8 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG SIMPLE + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL diff --git a/converter/ppm/ppmtompeg/tst/par3.param b/converter/ppm/ppmtompeg/tst/par3.param new file mode 100644 index 00000000..6ee6586e --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/par3.param @@ -0,0 +1,43 @@ +# speed test parameter file + +PATTERN IBBPBBPBBPBBPBB + +OUTPUT /n/picasso/users/keving/encode/output/flowgard.mpg +GOP_SIZE 30 +SLICES_PER_FRAME 15 + +BASE_FILE_FORMAT YUV +YUV_SIZE 352x240 + +INPUT_CONVERT * + +INPUT_DIR /n/picasso/users/keving/encode/input/flowg + +INPUT +sflowg.*.yuv [0-39] +END_INPUT + +# quality parameters + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +# motion vector search parameters + +PIXEL HALF + +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +REFERENCE_FRAME ORIGINAL + +PARALLEL_TEST_FRAMES 3 +PARALLEL_TIME_CHUNKS 30 + +PARALLEL +bugs-bunny keving ~keving/encode/bin/sun/mpeg_encode +linus keving ~keving/encode/bin/sun/mpeg_encode +END_PARALLEL diff --git a/converter/ppm/ppmtompeg/tst/short.param b/converter/ppm/ppmtompeg/tst/short.param new file mode 100644 index 00000000..9189e5d6 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/short.param @@ -0,0 +1,31 @@ +# test suite parameter file + +PATTERN IBBBPBBB +OUTPUT /tmp/ts.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +INPUT_CONVERT * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR ../test/ts + +INPUT +stennis.*.yuv [30-37] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL + +# FORCE_ENCODE_LAST_FRAME diff --git a/converter/ppm/ppmtompeg/tst/test_all b/converter/ppm/ppmtompeg/tst/test_all new file mode 100755 index 00000000..67b56c9c --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/test_all @@ -0,0 +1,19 @@ +#!/bin/csh -f +cd .. +echo "First we encode three mpegs... (note requires 5MB on /tmp)" +rm -f /tmp/ts{,2,d}.{mpg,stat} +./mpeg_encode -stat /tmp/ts.stat ./tst/ts.param +./mpeg_encode -stat /tmp/ts2.stat ./tst/ts2.param +./mpeg_encode -stat /tmp/tsd.stat ./tst/tsd.param + +cd tst + +echo "Test one - tst/ts.param" +csh diffscript /tmp/ts.stat ts.stat /tmp/ts.mpg ts.mpg + +echo "Test two - tst/ts2.param (different pattern)" +csh diffscript /tmp/ts2.stat ts2.stat /tmp/ts2.mpg ts2.mpg + +echo "Test three - tst/tsd.param (uses decoded frames)" +csh diffscript /tmp/tsd.stat tsd.stat /tmp/tsd.mpg tsd.mpg + diff --git a/converter/ppm/ppmtompeg/tst/ts.mpg b/converter/ppm/ppmtompeg/tst/ts.mpg new file mode 100644 index 00000000..2bc6ae6e --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts.mpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts.param b/converter/ppm/ppmtompeg/tst/ts.param new file mode 100644 index 00000000..23e1092c --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts.param @@ -0,0 +1,29 @@ +# test suite parameter file + +PATTERN IBBPBBPBBP +OUTPUT /tmp/ts.mpg + +BASE_FILE_FORMAT JPEG +INPUT_CONVERT * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR ./tst/ts + +INPUT +stennis.*.jpg [30-39] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL +# Default string has the date in it, bad for tests! +USER_DATA /dev/null diff --git a/converter/ppm/ppmtompeg/tst/ts.stat b/converter/ppm/ppmtompeg/tst/ts.stat new file mode 100644 index 00000000..e13be8a3 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts.stat @@ -0,0 +1,52 @@ +MPEG ENCODER STATS (1.5b) +------------------------ +TIME STARTED: Thu Mar 30 19:50:43 2000 +MACHINE: unknown +FIRST FILE: ./tst/ts/stennis.30.jpg +LAST FILE: ./tst/ts/stennis.39.jpg +PATTERN: ibbpbbpbbp +GOP_SIZE: 30 +SLICES PER FRAME: 1 +RANGE: +/-10 +PIXEL SEARCH: HALF +PSEARCH: LOGARITHMIC +BSEARCH: CROSS2 +QSCALE: 8 10 25 +REFERENCE FRAME: ORIGINAL +TIME COMPLETED: Thu Mar 30 19:50:50 2000 +Total time: 7 seconds + +------------------------- +*****I FRAME SUMMARY***** +------------------------- + Blocks: 330 (105385 bits) ( 319 bpb) + Frames: 1 (105488 bits) (105488 bpf) (32.2% of total) + Compression: 19:1 ( 1.2487 bpp) + Seconds: 0 ( 7.6923 fps) ( 649846 pps) ( 2538 mps) +------------------------- +*****P FRAME SUMMARY***** +------------------------- + I Blocks: 110 ( 27261 bits) ( 247 bpb) + P Blocks: 872 (147211 bits) ( 168 bpb) + Skipped: 8 + Frames: 3 (174816 bits) (58272 bpf) (53.3% of total) + Compression: 34:1 ( 0.6898 bpp) + Seconds: 0 ( 3.2967 fps) ( 278505 pps) ( 1087 mps) +------------------------- +*****B FRAME SUMMARY***** +------------------------- + I Blocks: 1 ( 156 bits) ( 156 bpb) + B Blocks: 1979 ( 46497 bits) ( 23 bpb) + B types: 227 ( 21 bpb) forw 484 ( 16 bpb) back 1268 ( 26 bpb) bi + Skipped: 0 + Frames: 6 ( 47328 bits) ( 7888 bpf) (14.4% of total) + Compression: 257:1 ( 0.0934 bpp) + Seconds: 5 ( 1.1952 fps) ( 100972 pps) ( 394 mps) +--------------------------------------------- +Total Compression: 61:1 ( 0.3880 bpp) +Total Frames Per Second: 1.428571 (471 mps) +CPU Time: 1.650165 fps (544 mps) +Total Output Bit Rate (30 fps): 983472 bits/sec +MPEG file created in : /tmp/ts.mpg + + diff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.30.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.30.jpg new file mode 100644 index 00000000..f70e014e --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.30.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.31.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.31.jpg new file mode 100644 index 00000000..cc88a285 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.31.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.32.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.32.jpg new file mode 100644 index 00000000..221e22c9 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.32.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.33.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.33.jpg new file mode 100644 index 00000000..c702a620 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.33.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.34.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.34.jpg new file mode 100644 index 00000000..47c86806 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.34.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.35.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.35.jpg new file mode 100644 index 00000000..ed21c16b --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.35.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.36.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.36.jpg new file mode 100644 index 00000000..6fb7506b --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.36.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.37.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.37.jpg new file mode 100644 index 00000000..561bd3b2 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.37.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.38.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.38.jpg new file mode 100644 index 00000000..25ba097e --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.38.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts/stennis.39.jpg b/converter/ppm/ppmtompeg/tst/ts/stennis.39.jpg new file mode 100644 index 00000000..02b15aff --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts/stennis.39.jpg Binary files differdiff --git a/converter/ppm/ppmtompeg/tst/ts2.param b/converter/ppm/ppmtompeg/tst/ts2.param new file mode 100644 index 00000000..f72ba150 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts2.param @@ -0,0 +1,33 @@ +# test suite parameter file + +PATTERN IBBPBBPBB + +OUTPUT /tmp/ts2.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +YUV_FORMAT UCB +INPUT_CONVERT * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR ./tst/ts + +INPUT +stennis.*.yuv [30-39] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL +# Default string has the date in it, bad for tests! +USER_DATA /dev/null diff --git a/converter/ppm/ppmtompeg/tst/ts2.stat b/converter/ppm/ppmtompeg/tst/ts2.stat new file mode 100644 index 00000000..5a14ef79 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts2.stat @@ -0,0 +1,52 @@ +MPEG ENCODER STATS (1.5) +------------------------ +TIME STARTED: Mon Jun 26 14:22:56 1995 +MACHINE: odie.CS.Berkeley.EDU +FIRST FILE: ./tst/ts/stennis.30.yuv +LAST FILE: ./tst/ts/stennis.39.yuv +PATTERN: ibbpbbpbb +GOP_SIZE: 30 +SLICES PER FRAME: 1 +RANGE: +/-10 +FULL SEARCH: 0 +PSEARCH: LOGARITHMIC +BSEARCH: CROSS2 +QSCALE: 8 10 25 +REFERENCE FRAME: ORIGINAL +TIME COMPLETED: Mon Jun 26 14:23:11 1995 +Total time: 15 seconds + +------------------------- +*****I FRAME SUMMARY***** +------------------------- + Blocks: 660 (171792 bits) ( 260 bpb) + Frames: 2 (172008 bits) (86004 bpf) (60.0% of total) + Compression: 23:1 ( 1.0180 bpp) + Seconds: 0 ( 2.9851 fps) ( 252179 pps) ( 985 mps) +------------------------- +*****P FRAME SUMMARY***** +------------------------- + I Blocks: 54 ( 13161 bits) ( 243 bpb) + P Blocks: 598 ( 69956 bits) ( 116 bpb) + Skipped: 8 + Frames: 2 ( 83344 bits) (41672 bpf) (29.1% of total) + Compression: 48:1 ( 0.4933 bpp) + Seconds: 1 ( 1.2821 fps) ( 108307 pps) ( 423 mps) +------------------------- +*****B FRAME SUMMARY***** +------------------------- + I Blocks: 5 ( 391 bits) ( 78 bpb) + B Blocks: 1733 ( 29897 bits) ( 17 bpb) + B types: 250 ( 11 bpb) forw 483 ( 12 bpb) back 1000 ( 20 bpb) bi + Skipped: 491 + Frames: 6 ( 30960 bits) ( 5160 bpf) (10.8% of total) + Compression: 392:1 ( 0.0611 bpp) + Seconds: 11 ( 0.5029 fps) ( 42487 pps) ( 165 mps) +--------------------------------------------- +Total Compression: 70:1 ( 0.3392 bpp) +Total Frames Per Second: 0.666667 (220 mps) +CPU Time: 0.706215 fps (233 mps) +Total Output Bit Rate (30 fps): 859608 bits/sec +MPEG file created in : /tmp/ts2.mpg + + diff --git a/converter/ppm/ppmtompeg/tst/ts3.param b/converter/ppm/ppmtompeg/tst/ts3.param new file mode 100644 index 00000000..5f7b9efa --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts3.param @@ -0,0 +1,32 @@ +# test suite parameter file + +PATTERN IBPB +OUTPUT /tmp/ts.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +YUV_FORMAT UCB +INPUT_CONVERT * +GOP_SIZE 3 +SLICES_PER_FRAME 1 + +INPUT_DIR ./tst/ts + +INPUT +stennis.*.yuv [30-39] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL +# Default string has the date in it, bad for tests! +USER_DATA /dev/null diff --git a/converter/ppm/ppmtompeg/tst/ts4.param b/converter/ppm/ppmtompeg/tst/ts4.param new file mode 100644 index 00000000..c8ba161c --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/ts4.param @@ -0,0 +1,56 @@ +# test suite parameter file + +PATTERN IBBBPBBBBP +OUTPUT /tmp/ts.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +YUV_FORMAT UCB +INPUT_CONVERT * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR ./tst/ts + +INPUT +stennis.*.yuv [30-39] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +FRAME_RATE 25.000 + +ASPECT_RATIO 1.0 + +REFERENCE_FRAME ORIGINAL + +IQTABLE + 8 16 19 22 26 27 29 34 + 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 + +NIQTABLE + 8 16 19 22 26 27 29 34 + 9 10 11 12 13 14 15 16 + 17 18 19 20 21 22 23 24 + 25 26 27 28 29 30 31 32 + 33 34 35 36 37 38 39 40 + 41 42 43 44 45 46 47 48 + 49 50 51 52 53 54 55 56 + 57 58 59 60 61 62 63 64 +# Default string has the date in it, bad for tests! +USER_DATA /dev/null diff --git a/converter/ppm/ppmtompeg/tst/tsd.param b/converter/ppm/ppmtompeg/tst/tsd.param new file mode 100644 index 00000000..330a7a2a --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/tsd.param @@ -0,0 +1,32 @@ +# test suite parameter file + +PATTERN IBBBPBBBBP +OUTPUT /tmp/tsd.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +YUV_FORMAT UCB +INPUT_CONVERT * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR ./tst/ts + +INPUT +stennis.*.yuv [30-39] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG LOGARITHMIC +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME DECODED +# Default string has the date in it, bad for tests! +USER_DATA /dev/null diff --git a/converter/ppm/ppmtompeg/tst/tsd.stat b/converter/ppm/ppmtompeg/tst/tsd.stat new file mode 100644 index 00000000..b130e089 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/tsd.stat @@ -0,0 +1,52 @@ +MPEG ENCODER STATS (1.5b) +------------------------ +TIME STARTED: Tue Aug 15 12:31:11 1995 +MACHINE: odie.CS.Berkeley.EDU +FIRST FILE: ./tst/ts/stennis.30.yuv +LAST FILE: ./tst/ts/stennis.39.yuv +PATTERN: ibbbpbbbbp +GOP_SIZE: 30 +SLICES PER FRAME: 1 +RANGE: +/-10 +PIXEL SEARCH: HALF +PSEARCH: LOGARITHMIC +BSEARCH: CROSS2 +QSCALE: 8 10 25 +REFERENCE FRAME: DECODED +TIME COMPLETED: Tue Aug 15 12:31:31 1995 +Total time: 20 seconds + +------------------------- +*****I FRAME SUMMARY***** +------------------------- + Blocks: 330 ( 94083 bits) ( 285 bpb) + Frames: 1 ( 94192 bits) (94192 bpf) (37.0% of total) + Compression: 21:1 ( 1.1150 bpp) + Seconds: 0 ( 2.4390 fps) ( 206048 pps) ( 804 mps) +------------------------- +*****P FRAME SUMMARY***** +------------------------- + I Blocks: 97 ( 20894 bits) ( 215 bpb) + P Blocks: 560 ( 83390 bits) ( 148 bpb) + Skipped: 3 + Frames: 2 (104512 bits) (52256 bpf) (41.1% of total) + Compression: 38:1 ( 0.6186 bpp) + Seconds: 1 ( 1.0811 fps) ( 91329 pps) ( 356 mps) +------------------------- +*****B FRAME SUMMARY***** +------------------------- + I Blocks: 4 ( 588 bits) ( 147 bpb) + B Blocks: 2306 ( 54124 bits) ( 23 bpb) + B types: 283 ( 14 bpb) forw 419 ( 16 bpb) back 1604 ( 26 bpb) bi + Skipped: 0 + Frames: 7 ( 55504 bits) ( 7929 bpf) (21.8% of total) + Compression: 255:1 ( 0.0939 bpp) + Seconds: 16 ( 0.4182 fps) ( 35326 pps) ( 137 mps) +--------------------------------------------- +Total Compression: 79:1 ( 0.3011 bpp) +Total Frames Per Second: 0.500000 (165 mps) +CPU Time: 0.526316 fps (173 mps) +Total Output Bit Rate (30 fps): 763200 bits/sec +MPEG file created in : /tmp/tsd.mpg + + diff --git a/converter/ppm/ppmtompeg/tst/tstl.param b/converter/ppm/ppmtompeg/tst/tstl.param new file mode 100644 index 00000000..2b9c1718 --- /dev/null +++ b/converter/ppm/ppmtompeg/tst/tstl.param @@ -0,0 +1,31 @@ +# test suite parameter file + +PATTERN IBBBPBBBBP +OUTPUT /tmp/ts.mpg + +YUV_SIZE 352x240 + +BASE_FILE_FORMAT YUV +INPUT_CONVERT * +GOP_SIZE 30 +SLICES_PER_FRAME 1 + +INPUT_DIR ../test/ts + +INPUT +stennis.*.yuv [30-39] +END_INPUT + +PIXEL HALF +RANGE 10 + +PSEARCH_ALG TWOLEVEL +BSEARCH_ALG CROSS2 + +IQSCALE 8 +PQSCALE 10 +BQSCALE 25 + +REFERENCE_FRAME ORIGINAL +# Default string has the date in it, bad for tests! +USER_DATA /dev/null |